Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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