r_data.c
上传用户:xuyinpeng
上传日期:2021-05-12
资源大小:455k
文件大小:19k
源码类别:

射击游戏

开发平台:

Visual C++

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // Revision 1.3  1997/01/29 20:10
  20. // DESCRIPTION:
  21. // Preparation of data for rendering,
  22. // generation of lookups, caching, retrieval by name.
  23. //
  24. //-----------------------------------------------------------------------------
  25. static const char
  26. rcsid[] = "$Id: r_data.c,v 1.4 1997/02/03 16:47:55 b1 Exp $";
  27. #include "i_system.h"
  28. #include "z_zone.h"
  29. #include "m_swap.h"
  30. #include "w_wad.h"
  31. #include "doomdef.h"
  32. #include "r_local.h"
  33. #include "p_local.h"
  34. #include "doomstat.h"
  35. #include "r_sky.h"
  36. #ifdef LINUX
  37. #include  <alloca.h>
  38. #endif
  39. #define alloca malloc
  40. #include "r_data.h"
  41. char MsgText[256];
  42. void WriteDebug(char *);
  43. //
  44. // Graphics.
  45. // DOOM graphics for walls and sprites
  46. // is stored in vertical runs of opaque pixels (posts).
  47. // A column is composed of zero or more posts,
  48. // a patch or sprite is composed of zero or more columns.
  49. // 
  50. //
  51. // Texture definition.
  52. // Each texture is composed of one or more patches,
  53. // with patches being lumps stored in the WAD.
  54. // The lumps are referenced by number, and patched
  55. // into the rectangular texture space using origin
  56. // and possibly other attributes.
  57. //
  58. typedef struct
  59. {
  60.     short originx;
  61.     short originy;
  62.     short patch;
  63.     short stepdir;
  64.     short colormap;
  65. } mappatch_t;
  66. //
  67. // Texture definition.
  68. // A DOOM wall texture is a list of patches
  69. // which are to be combined in a predefined order.
  70. //
  71. typedef struct
  72. {
  73.     char name[8];
  74.     boolean masked;
  75.     short width;
  76.     short height;
  77.     void **columndirectory; // OBSOLETE
  78.     short patchcount;
  79.     mappatch_t patches[1];
  80. } maptexture_t;
  81. // A single patch from a texture definition,
  82. //  basically a rectangular area within
  83. //  the texture rectangle.
  84. typedef struct
  85. {
  86.     // Block origin (allways UL),
  87.     // which has allready accounted
  88.     // for the internal origin of the patch.
  89.     int originx;
  90.     int originy;
  91.     int patch;
  92. } texpatch_t;
  93. // A maptexturedef_t describes a rectangular texture,
  94. //  which is composed of one or more mappatch_t structures
  95. //  that arrange graphic patches.
  96. typedef struct
  97. {
  98.     // Keep name for switch changing, etc.
  99.     char name[8];
  100.     short width;
  101.     short height;
  102.     
  103.     // All the patches[patchcount]
  104.     //  are drawn back to front into the cached texture.
  105.     short patchcount;
  106.     texpatch_t patches[1];
  107.     
  108. } texture_t;
  109. int firstflat;
  110. int lastflat;
  111. int numflats;
  112. int firstpatch;
  113. int lastpatch;
  114. int numpatches;
  115. int firstspritelump;
  116. int lastspritelump;
  117. int numspritelumps;
  118. int numtextures;
  119. texture_t** textures;
  120. int* texturewidthmask;
  121. // needed for texture pegging
  122. fixed_t* textureheight;
  123. int* texturecompositesize;
  124. short** texturecolumnlump;
  125. unsigned short** texturecolumnofs;
  126. byte** texturecomposite;
  127. // for global animation
  128. int* flattranslation;
  129. int* texturetranslation;
  130. // needed for pre rendering
  131. fixed_t* spritewidth;
  132. fixed_t* spriteoffset;
  133. fixed_t* spritetopoffset;
  134. lighttable_t *colormaps;
  135. //
  136. // MAPTEXTURE_T CACHING
  137. // When a texture is first needed,
  138. //  it counts the number of composite columns
  139. //  required in the texture and allocates space
  140. //  for a column directory and any new columns.
  141. // The directory will simply point inside other patches
  142. //  if there is only one patch in a given column,
  143. //  but any columns with multiple patches
  144. //  will have new column_ts generated.
  145. //
  146. //
  147. // R_DrawColumnInCache
  148. // Clip and draw a column
  149. //  from a patch into a cached post.
  150. //
  151. void
  152. R_DrawColumnInCache
  153. ( column_t* patch,
  154.   byte* cache,
  155.   int originy,
  156.   int cacheheight )
  157. {
  158.     int count;
  159.     int position;
  160.     byte* source;
  161.     byte* dest;
  162.     dest = (byte *)cache + 3;
  163.     while (patch->topdelta != 0xff)
  164.     {
  165. source = (byte *)patch + 3;
  166. count = patch->length;
  167. position = originy + patch->topdelta;
  168. if (position < 0)
  169. {
  170.     count += position;
  171.     position = 0;
  172. }
  173. if (position + count > cacheheight)
  174.     count = cacheheight - position;
  175. if (count > 0)
  176.     memcpy (cache + position, source, count);
  177. patch = (column_t *)(  (byte *)patch + patch->length + 4); 
  178.     }
  179. }
  180. //
  181. // R_GenerateComposite
  182. // Using the texture definition,
  183. //  the composite texture is created from the patches,
  184. //  and each column is cached.
  185. //
  186. void R_GenerateComposite (int texnum)
  187. {
  188.     byte* block;
  189.     texture_t* texture;
  190.     texpatch_t* patch;
  191.     patch_t* realpatch;
  192.     int x;
  193.     int x1;
  194.     int x2;
  195.     int i;
  196.     column_t* patchcol;
  197.     short* collump;
  198.     unsigned short* colofs;
  199.     texture = textures[texnum];
  200.     block = Z_Malloc (texturecompositesize[texnum],
  201.       PU_STATIC, 
  202.       &texturecomposite[texnum]);
  203.     collump = texturecolumnlump[texnum];
  204.     colofs = texturecolumnofs[texnum];
  205.     
  206.     // Composite the columns together.
  207.     patch = texture->patches;
  208.     for (i=0 , patch = texture->patches;
  209.  i<texture->patchcount;
  210.  i++, patch++)
  211.     {
  212. realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
  213. x1 = patch->originx;
  214. x2 = x1 + SHORT(realpatch->width);
  215. if (x1<0)
  216.     x = 0;
  217. else
  218.     x = x1;
  219. if (x2 > texture->width)
  220.     x2 = texture->width;
  221. for ( ; x<x2 ; x++)
  222. {
  223.     // Column does not have multiple patches?
  224.     if (collump[x] >= 0)
  225. continue;
  226.     
  227.     patchcol = (column_t *)((byte *)realpatch
  228.     + LONG(realpatch->columnofs[x-x1]));
  229.     R_DrawColumnInCache (patchcol,
  230.  block + colofs[x],
  231.  patch->originy,
  232.  texture->height);
  233. }
  234.     }
  235.     // Now that the texture has been built in column cache,
  236.     //  it is purgable from zone memory.
  237.     Z_ChangeTag (block, PU_CACHE);
  238. }
  239. //
  240. // R_GenerateLookup
  241. //
  242. void R_GenerateLookup (int texnum)
  243. {
  244.     texture_t* texture;
  245.     byte* patchcount; // patchcount[texture->width]
  246.     texpatch_t* patch;
  247.     patch_t* realpatch;
  248.     int x;
  249.     int x1;
  250.     int x2;
  251.     int i;
  252.     short* collump;
  253.     unsigned short* colofs;
  254.     texture = textures[texnum];
  255.     // Composited texture not created yet.
  256.     texturecomposite[texnum] = 0;
  257.     
  258.     texturecompositesize[texnum] = 0;
  259.     collump = texturecolumnlump[texnum];
  260.     colofs = texturecolumnofs[texnum];
  261.     
  262.     // Now count the number of columns
  263.     //  that are covered by more than one patch.
  264.     // Fill in the lump / offset, so columns
  265.     //  with only a single patch are all done.
  266.     patchcount = (byte *)alloca (texture->width);
  267.     memset (patchcount, 0, texture->width);
  268.     patch = texture->patches;
  269.     for (i=0 , patch = texture->patches;
  270.  i<texture->patchcount;
  271.  i++, patch++)
  272.     {
  273. realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
  274. x1 = patch->originx;
  275. x2 = x1 + SHORT(realpatch->width);
  276. if (x1 < 0)
  277.     x = 0;
  278. else
  279.     x = x1;
  280. if (x2 > texture->width)
  281.     x2 = texture->width;
  282. for ( ; x<x2 ; x++)
  283. {
  284.     patchcount[x]++;
  285.     collump[x] = patch->patch;
  286.     colofs[x] = LONG(realpatch->columnofs[x-x1])+3;
  287. }
  288.     }
  289.     for (x=0 ; x<texture->width ; x++)
  290.     {
  291. if (!patchcount[x])
  292. {
  293.     sprintf (MsgText,"R_GenerateLookup: column without a patch (%s)n",
  294.     texture->name);
  295.         WriteDebug(MsgText);
  296.     return;
  297. }
  298. // I_Error ("R_GenerateLookup: column without a patch");
  299. if (patchcount[x] > 1)
  300. {
  301.     // Use the cached block.
  302.     collump[x] = -1;
  303.     colofs[x] = texturecompositesize[texnum];
  304.     
  305.     if (texturecompositesize[texnum] > 0x10000-texture->height)
  306.     {
  307. I_Error ("R_GenerateLookup: texture %i is >64k",
  308.  texnum);
  309.     }
  310.     
  311.     texturecompositesize[texnum] += texture->height;
  312. }
  313.     }
  314. }
  315. //
  316. // R_GetColumn
  317. //
  318. byte*
  319. R_GetColumn
  320. ( int tex,
  321.   int col )
  322. {
  323.     int lump;
  324.     int ofs;
  325.     col &= texturewidthmask[tex];
  326.     lump = texturecolumnlump[tex][col];
  327.     ofs = texturecolumnofs[tex][col];
  328.     
  329.     if (lump > 0)
  330. return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs;
  331.     if (!texturecomposite[tex])
  332. R_GenerateComposite (tex);
  333.     return texturecomposite[tex] + ofs;
  334. }
  335. //
  336. // R_InitTextures
  337. // Initializes the texture list
  338. //  with the textures from the world map.
  339. //
  340. void R_InitTextures (void)
  341. {
  342.     maptexture_t* mtexture;
  343.     texture_t* texture;
  344.     mappatch_t* mpatch;
  345.     texpatch_t* patch;
  346.     int i;
  347.     int j;
  348.     int* maptex;
  349.     int* maptex2;
  350.     int* maptex1;
  351.     
  352.     char name[9];
  353.     char* names;
  354.     char* name_p;
  355.     
  356.     int* patchlookup;
  357.     
  358.     int totalwidth;
  359.     int nummappatches;
  360.     int offset;
  361.     int maxoff;
  362.     int maxoff2;
  363.     int numtextures1;
  364.     int numtextures2;
  365.     int* directory;
  366.     
  367.     int temp1;
  368.     int temp2;
  369.     int temp3;
  370.     
  371.     // Load the patch names from pnames.lmp.
  372.     name[8] = 0;
  373.     names = W_CacheLumpName ("PNAMES", PU_STATIC);
  374.     nummappatches = LONG ( *((int *)names) );
  375.     name_p = names+4;
  376.     patchlookup = alloca (nummappatches*sizeof(*patchlookup));
  377.     
  378.     for (i=0 ; i<nummappatches ; i++)
  379.     {
  380. strncpy (name,name_p+i*8, 8);
  381. patchlookup[i] = W_CheckNumForName (name);
  382.     }
  383.     Z_Free (names);
  384.     
  385.     // Load the map texture definitions from textures.lmp.
  386.     // The data is contained in one or two lumps,
  387.     //  TEXTURE1 for shareware, plus TEXTURE2 for commercial.
  388.     maptex = maptex1 = W_CacheLumpName ("TEXTURE1", PU_STATIC);
  389.     numtextures1 = LONG(*maptex);
  390.     maxoff = W_LumpLength (W_GetNumForName ("TEXTURE1"));
  391.     directory = maptex+1;
  392.     if (W_CheckNumForName ("TEXTURE2") != -1)
  393.     {
  394. maptex2 = W_CacheLumpName ("TEXTURE2", PU_STATIC);
  395. numtextures2 = LONG(*maptex2);
  396. maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2"));
  397.     }
  398.     else
  399.     {
  400. maptex2 = NULL;
  401. numtextures2 = 0;
  402. maxoff2 = 0;
  403.     }
  404.     numtextures = numtextures1 + numtextures2;
  405.     textures = Z_Malloc (numtextures*4, PU_STATIC, 0);
  406.     texturecolumnlump = Z_Malloc (numtextures*4, PU_STATIC, 0);
  407.     texturecolumnofs = Z_Malloc (numtextures*4, PU_STATIC, 0);
  408.     texturecomposite = Z_Malloc (numtextures*4, PU_STATIC, 0);
  409.     texturecompositesize = Z_Malloc (numtextures*4, PU_STATIC, 0);
  410.     texturewidthmask = Z_Malloc (numtextures*4, PU_STATIC, 0);
  411.     textureheight = Z_Malloc (numtextures*4, PU_STATIC, 0);
  412.     totalwidth = 0;
  413.     
  414.     // Really complex printing shit...
  415.     temp1 = W_GetNumForName ("S_START");  // P_???????
  416.     temp2 = W_GetNumForName ("S_END") - 1;
  417.     temp3 = ((temp2-temp1+63)/64) + ((numtextures+63)/64);
  418.     sprintf(MsgText,"[");
  419.     WriteDebug(MsgText);
  420.     for (i = 0; i < temp3; i++)
  421. sprintf(MsgText," ");
  422.     WriteDebug(MsgText);
  423.     sprintf(MsgText,"         ]");
  424.     WriteDebug(MsgText);
  425.     for (i = 0; i < temp3; i++)
  426. sprintf(MsgText,"x8");
  427.     WriteDebug(MsgText);
  428.     sprintf(MsgText,"x8x8x8x8x8x8x8x8x8x8");
  429.     WriteDebug(MsgText);
  430.     for (i=0 ; i<numtextures ; i++, directory++)
  431.     {
  432. if (!(i&63))
  433.        {
  434.     sprintf (MsgText,".");
  435.         WriteDebug(MsgText);
  436.        }
  437. if (i == numtextures1)
  438. {
  439.     // Start looking in second texture file.
  440.     maptex = maptex2;
  441.     maxoff = maxoff2;
  442.     directory = maptex+1;
  443. }
  444. offset = LONG(*directory);
  445. if (offset > maxoff)
  446.     I_Error ("R_InitTextures: bad texture directory");
  447. mtexture = (maptexture_t *) ( (byte *)maptex + offset);
  448. texture = textures[i] =
  449.     Z_Malloc (sizeof(texture_t)
  450.       + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1),
  451.       PU_STATIC, 0);
  452. texture->width = SHORT(mtexture->width);
  453. texture->height = SHORT(mtexture->height);
  454. texture->patchcount = SHORT(mtexture->patchcount);
  455. memcpy (texture->name, mtexture->name, sizeof(texture->name));
  456. mpatch = &mtexture->patches[0];
  457. patch = &texture->patches[0];
  458. for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
  459. {
  460.     patch->originx = SHORT(mpatch->originx);
  461.     patch->originy = SHORT(mpatch->originy);
  462.     patch->patch = patchlookup[SHORT(mpatch->patch)];
  463.     if (patch->patch == -1)
  464.     {
  465. I_Error ("R_InitTextures: Missing patch in texture %s",
  466.  texture->name);
  467.     }
  468. }
  469. texturecolumnlump[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
  470. texturecolumnofs[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
  471. j = 1;
  472. while (j*2 <= texture->width)
  473.     j<<=1;
  474. texturewidthmask[i] = j-1;
  475. textureheight[i] = texture->height<<FRACBITS;
  476. totalwidth += texture->width;
  477.     }
  478.     Z_Free (maptex1);
  479.     if (maptex2)
  480. Z_Free (maptex2);
  481.     
  482.     // Precalculate whatever possible.
  483.     for (i=0 ; i<numtextures ; i++)
  484. R_GenerateLookup (i);
  485.     
  486.     // Create translation table for global animation.
  487.     texturetranslation = Z_Malloc ((numtextures+1)*4, PU_STATIC, 0);
  488.     
  489.     for (i=0 ; i<numtextures ; i++)
  490. texturetranslation[i] = i;
  491. }
  492. //
  493. // R_InitFlats
  494. //
  495. void R_InitFlats (void)
  496. {
  497.     int i;
  498.     firstflat = W_GetNumForName ("F_START") + 1;
  499.     lastflat = W_GetNumForName ("F_END") - 1;
  500.     numflats = lastflat - firstflat + 1;
  501.     // Create translation table for global animation.
  502.     flattranslation = Z_Malloc ((numflats+1)*4, PU_STATIC, 0);
  503.     
  504.     for (i=0 ; i<numflats ; i++)
  505. flattranslation[i] = i;
  506. }
  507. //
  508. // R_InitSpriteLumps
  509. // Finds the width and hoffset of all sprites in the wad,
  510. //  so the sprite does not need to be cached completely
  511. //  just for having the header info ready during rendering.
  512. //
  513. void R_InitSpriteLumps (void)
  514. {
  515.     int i;
  516.     patch_t *patch;
  517.     firstspritelump = W_GetNumForName ("S_START") + 1;
  518.     lastspritelump = W_GetNumForName ("S_END") - 1;
  519.     
  520.     numspritelumps = lastspritelump - firstspritelump + 1;
  521.     spritewidth = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  522.     spriteoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  523.     spritetopoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  524.     for (i=0 ; i< numspritelumps ; i++)
  525.     {
  526. if (!(i&63))
  527.        {
  528.     sprintf (MsgText,".");
  529.         WriteDebug(MsgText);
  530.        }
  531. patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE);
  532. spritewidth[i] = SHORT(patch->width)<<FRACBITS;
  533. spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS;
  534. spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS;
  535.     }
  536. }
  537. //
  538. // R_InitColormaps
  539. //
  540. void R_InitColormaps (void)
  541. {
  542.     int lump, length;
  543.     
  544.     // Load in the light tables, 
  545.     //  256 byte align tables.
  546.     lump = W_GetNumForName("COLORMAP"); 
  547.     length = W_LumpLength (lump) + 255; 
  548.     colormaps = Z_Malloc (length, PU_STATIC, 0); 
  549.     colormaps = (byte *)( ((int)colormaps + 255)&~0xff); 
  550.     W_ReadLump (lump,colormaps); 
  551. }
  552. //
  553. // R_InitData
  554. // Locates all the lumps
  555. //  that will be used by all views
  556. // Must be called after W_Init.
  557. //
  558. void R_InitData (void)
  559. {
  560.     R_InitTextures ();
  561.     sprintf (MsgText,"nInitTextures");
  562.     WriteDebug(MsgText);
  563.     R_InitFlats ();
  564.     sprintf (MsgText,"nInitFlats");
  565.     WriteDebug(MsgText);
  566.     R_InitSpriteLumps ();
  567.     sprintf (MsgText,"nInitSprites");
  568.     WriteDebug(MsgText);
  569.     R_InitColormaps ();
  570.     sprintf (MsgText,"nInitColormaps");
  571.     WriteDebug(MsgText);
  572. }
  573. //
  574. // R_FlatNumForName
  575. // Retrieval, get a flat number for a flat name.
  576. //
  577. int R_FlatNumForName (char* name)
  578. {
  579.     int i;
  580.     char namet[9];
  581.     i = W_CheckNumForName (name);
  582.     if (i == -1)
  583.     {
  584. namet[8] = 0;
  585. memcpy (namet, name,8);
  586. I_Error ("R_FlatNumForName: %s not found",namet);
  587.     }
  588.     return i - firstflat;
  589. }
  590. //
  591. // R_CheckTextureNumForName
  592. // Check whether texture is available.
  593. // Filter out NoTexture indicator.
  594. //
  595. int R_CheckTextureNumForName (char *name)
  596. {
  597.     int i;
  598.     char    tname[10];
  599.     // "NoTexture" marker.
  600.     if (name[0] == '-')
  601. return 0;
  602.     strncpy(tname, name, 8);
  603.     strupr(tname);
  604.     for (i=0 ; i<numtextures ; i++)
  605. if (!strncasecmp (textures[i]->name, tname, 8) )
  606.     return i;
  607.     return -1;
  608. }
  609. //
  610. // R_TextureNumForName
  611. // Calls R_CheckTextureNumForName,
  612. //  aborts with error message.
  613. //
  614. int R_TextureNumForName (char* name)
  615. {
  616.     int i;
  617.     i = R_CheckTextureNumForName (name);
  618.     if (i==-1)
  619.     {
  620. I_Error ("R_TextureNumForName: %s not found",
  621.  name);
  622.     }
  623.     return i;
  624. }
  625. //
  626. // R_PrecacheLevel
  627. // Preloads all relevant graphics for the level.
  628. //
  629. int flatmemory;
  630. int texturememory;
  631. int spritememory;
  632. void R_PrecacheLevel (void)
  633. {
  634.     char* flatpresent;
  635.     char* texturepresent;
  636.     char* spritepresent;
  637.     int i;
  638.     int j;
  639.     int k;
  640.     int lump;
  641.     
  642.     texture_t* texture;
  643.     thinker_t* th;
  644.     spriteframe_t* sf;
  645.     if (demoplayback)
  646. return;
  647.     
  648.     // Precache flats.
  649.     flatpresent = alloca(numflats);
  650.     memset (flatpresent,0,numflats);
  651.     for (i=0 ; i<numsectors ; i++)
  652.     {
  653. flatpresent[sectors[i].floorpic] = 1;
  654. flatpresent[sectors[i].ceilingpic] = 1;
  655.     }
  656.     flatmemory = 0;
  657.     for (i=0 ; i<numflats ; i++)
  658.     {
  659. if (flatpresent[i])
  660. {
  661.     lump = firstflat + i;
  662.     flatmemory += lumpinfo[lump].size;
  663.     W_CacheLumpNum(lump, PU_CACHE);
  664. }
  665.     }
  666.     
  667.     // Precache textures.
  668.     texturepresent = alloca(numtextures);
  669.     memset (texturepresent,0, numtextures);
  670.     for (i=0 ; i<numsides ; i++)
  671.     {
  672. texturepresent[sides[i].toptexture] = 1;
  673. texturepresent[sides[i].midtexture] = 1;
  674. texturepresent[sides[i].bottomtexture] = 1;
  675.     }
  676.     // Sky texture is always present.
  677.     // Note that F_SKY1 is the name used to
  678.     //  indicate a sky floor/ceiling as a flat,
  679.     //  while the sky texture is stored like
  680.     //  a wall texture, with an episode dependend
  681.     //  name.
  682.     texturepresent[skytexture] = 1;
  683.     texturememory = 0;
  684.     for (i=0 ; i<numtextures ; i++)
  685.     {
  686. if (!texturepresent[i])
  687.     continue;
  688. texture = textures[i];
  689. for (j=0 ; j<texture->patchcount ; j++)
  690. {
  691.     lump = texture->patches[j].patch;
  692.     texturememory += lumpinfo[lump].size;
  693.     W_CacheLumpNum(lump , PU_CACHE);
  694. }
  695.     }
  696.     
  697.     // Precache sprites.
  698.     spritepresent = alloca(numsprites);
  699.     memset (spritepresent,0, numsprites);
  700.     for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  701.     {
  702. if (th->function.acp1 == (actionf_p1)P_MobjThinker)
  703.     spritepresent[((mobj_t *)th)->sprite] = 1;
  704.     }
  705.     spritememory = 0;
  706.     for (i=0 ; i<numsprites ; i++)
  707.     {
  708. if (!spritepresent[i])
  709.     continue;
  710. for (j=0 ; j<sprites[i].numframes ; j++)
  711. {
  712.     sf = &sprites[i].spriteframes[j];
  713.     for (k=0 ; k<8 ; k++)
  714.     {
  715. lump = firstspritelump + sf->lump[k];
  716. spritememory += lumpinfo[lump].size;
  717. W_CacheLumpNum(lump , PU_CACHE);
  718.     }
  719. }
  720.     }
  721. }