Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | 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. #include <malloc.h>
  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.     int                 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 int   width;
  121.     short int   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. // R_GenerateLookup
  296. //
  297. void R_GenerateLookup (int texnum)
  298. {
  299.     texture_t*          texture;
  300.     byte*               patchcount;     // patchcount[texture->width]
  301.     texpatch_t*         patch; 
  302.     patch_t*            realpatch;
  303.     int                 x;
  304.     int                 x1;
  305.     int                 x2;
  306.     int                 i;
  307.     short*              collump;
  308.     unsigned short*     colofs;
  309.        
  310.     texture = textures[texnum];
  311.  
  312.     // Composited texture not created yet.
  313.     texturecomposite[texnum] = 0;
  314.    
  315.     texturecompositesize[texnum] = 0;
  316.     collump = texturecolumnlump[texnum];
  317.     colofs = texturecolumnofs[texnum];
  318.    
  319.     // Now count the number of columns
  320.     //  that are covered by more than one patch.
  321.     // Fill in the lump / offset, so columns
  322.     //  with only a single patch are all done.
  323.     patchcount = (byte *)alloca (texture->width);
  324.     memset (patchcount, 0, texture->width);
  325.     patch = texture->patches;
  326.                
  327.     for (i=0 , patch = texture->patches;
  328.          i<texture->patchcount;
  329.          i++, patch++)
  330.     {
  331.         realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
  332.         x1 = patch->originx;
  333.         x2 = x1 + SHORT(realpatch->width);
  334.        
  335.         if (x1 < 0)
  336.             x = 0;
  337.         else
  338.             x = x1;
  339.  
  340.         if (x2 > texture->width)
  341.             x2 = texture->width;
  342.         for ( ; x<x2 ; x++)
  343.         {
  344.             patchcount[x]++;
  345.             collump[x] = patch->patch;
  346.             colofs[x] = LONG(realpatch->columnofs[x-x1])+3;
  347.         }
  348.     }
  349.        
  350.     for (x=0 ; x<texture->width ; x++)
  351.     {
  352.         if (!patchcount[x])
  353.         {
  354.             printf("R_GenerateLookup: column without a patch (%s)\n",
  355.                     texture->name);
  356.             return;
  357.         }
  358. //      I_Error ("R_GenerateLookup: column without a patch");
  359.        
  360.         if (patchcount[x] > 1)
  361.         {
  362.             // Use the cached block.
  363.             collump[x] = -1;   
  364.             colofs[x] = texturecompositesize[texnum];
  365.            
  366.             if (texturecompositesize[texnum] > 0x10000-texture->height)
  367.             {
  368.                 I_Error ("R_GenerateLookup: texture %i is >64k",
  369.                          texnum);
  370.             }
  371.            
  372.             texturecompositesize[texnum] += texture->height;
  373.         }
  374.     }  
  375. }
  376.  
  377.  
  378.  
  379.  
  380. //
  381. // R_GetColumn
  382. //
  383. byte*
  384. R_GetColumn
  385. ( int           tex,
  386.   int           col )
  387. {
  388.     int         lump;
  389.     int         ofs;
  390.        
  391.     col &= texturewidthmask[tex];
  392.     lump = texturecolumnlump[tex][col];
  393.     ofs = texturecolumnofs[tex][col];
  394.    
  395.     if (lump > 0)
  396.         return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs;
  397.  
  398.     if (!texturecomposite[tex])
  399.         R_GenerateComposite (tex);
  400.  
  401.     return texturecomposite[tex] + ofs;
  402. }
  403.  
  404.  
  405.  
  406.  
  407. //
  408. // R_InitTextures
  409. // Initializes the texture list
  410. //  with the textures from the world map.
  411. //
  412. void R_InitTextures (void)
  413. {
  414.     maptexture_t*       mtexture;
  415.     texture_t*          texture;
  416.     mappatch_t*         mpatch;
  417.     texpatch_t*         patch;
  418.  
  419.     int                 i;
  420.     int                 j;
  421.  
  422.     int*                maptex;
  423.     int*                maptex2;
  424.     int*                maptex1;
  425.    
  426.     char                name[9];
  427.     char*               names;
  428.     char*               name_p;
  429.    
  430.     int*                patchlookup;
  431.    
  432.     int                 totalwidth;
  433.     int                 nummappatches;
  434.     int                 offset;
  435.     int                 maxoff;
  436.     int                 maxoff2;
  437.     int                 numtextures1;
  438.     int                 numtextures2;
  439.  
  440.     int*                directory;
  441.    
  442.     int                 temp1;
  443.     int                 temp2;
  444.     int                 temp3;
  445.  
  446.    
  447.     // Load the patch names from pnames.lmp.
  448.     name[8] = 0;       
  449.     names = W_CacheLumpName ("PNAMES", PU_STATIC);
  450.     nummappatches = LONG ( *((int *)names) );
  451.     name_p = names+4;
  452.     patchlookup = alloca (nummappatches*sizeof(*patchlookup));
  453.    
  454.     for (i=0 ; i<nummappatches ; i++)
  455.     {
  456.         strncpy (name,name_p+i*8, 8);
  457.         patchlookup[i] = W_CheckNumForName (name);
  458.     }
  459.     Z_Free (names);
  460.    
  461.     // Load the map texture definitions from textures.lmp.
  462.     // The data is contained in one or two lumps,
  463.     //  TEXTURE1 for shareware, plus TEXTURE2 for commercial.
  464.     maptex = maptex1 = W_CacheLumpName ("TEXTURE1", PU_STATIC);
  465.     numtextures1 = LONG(*maptex);
  466.     maxoff = W_LumpLength (W_GetNumForName ("TEXTURE1"));
  467.     directory = maptex+1;
  468.        
  469.     if (W_CheckNumForName ("TEXTURE2") != -1)
  470.     {
  471.         maptex2 = W_CacheLumpName ("TEXTURE2", PU_STATIC);
  472.         numtextures2 = LONG(*maptex2);
  473.         maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2"));
  474.     }
  475.     else
  476.     {
  477.         maptex2 = NULL;
  478.         numtextures2 = 0;
  479.         maxoff2 = 0;
  480.     }
  481.     numtextures = numtextures1 + numtextures2;
  482.        
  483.     textures = Z_Malloc (numtextures*4, PU_STATIC, 0);
  484.     texturecolumnlump = Z_Malloc (numtextures*4, PU_STATIC, 0);
  485.     texturecolumnofs = Z_Malloc (numtextures*4, PU_STATIC, 0);
  486.     texturecomposite = Z_Malloc (numtextures*4, PU_STATIC, 0);
  487.     texturecompositesize = Z_Malloc (numtextures*4, PU_STATIC, 0);
  488.     texturewidthmask = Z_Malloc (numtextures*4, PU_STATIC, 0);
  489.     textureheight = Z_Malloc (numtextures*4, PU_STATIC, 0);
  490.  
  491.     totalwidth = 0;
  492.    
  493.     //  Really complex printing shit...
  494.     temp1 = W_GetNumForName ("S_START");  // P_???????
  495.     temp2 = W_GetNumForName ("S_END") - 1;
  496.     temp3 = ((temp2-temp1+63)/64) + ((numtextures+63)/64);
  497.     printf("[");
  498.     for (i = 0; i < temp3; i++)
  499.         printf(" ");
  500.     printf("         ]");
  501.     for (i = 0; i < temp3; i++)
  502.         printf("\x8");
  503.     printf("\x8\x8\x8\x8\x8\x8\x8\x8\x8\x8");  
  504.        
  505.     for (i=0 ; i<numtextures ; i++, directory++)
  506.     {
  507.         if (!(i&63))
  508.      printf (".");
  509.  
  510.         if (i == numtextures1)
  511.         {
  512.             // Start looking in second texture file.
  513.             maptex = maptex2;
  514.             maxoff = maxoff2;
  515.             directory = maptex+1;
  516.         }
  517.  
  518.         offset = LONG(*directory);
  519.  
  520.         if (offset > maxoff)
  521.             I_Error ("R_InitTextures: bad texture directory");
  522.        
  523.         mtexture = (maptexture_t *) ( (byte *)maptex + offset);
  524.  
  525.         texture = textures[i] =
  526.             Z_Malloc (sizeof(texture_t)
  527.                       + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1),
  528.                       PU_STATIC, 0);
  529.        
  530.         texture->width = SHORT(mtexture->width);
  531.         texture->height = SHORT(mtexture->height);
  532.         texture->patchcount = SHORT(mtexture->patchcount);
  533.  
  534.         // memcpy() generates a BUS error on Solaris with optimization on */
  535. #if 1
  536.         memcpy (texture->name, mtexture->name, sizeof(texture->name));
  537. #else
  538.         { char *src; char *dst;
  539.           src = (char *)mtexture->name;
  540.           dst = (char *)texture->name;
  541.           for (j=0; j<sizeof(texture->name); ++j )
  542.             *dst++ = *src++;
  543.         }
  544. #endif
  545.         mpatch = &mtexture->patches[0];
  546.         patch = &texture->patches[0];
  547.  
  548.         for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
  549.         {
  550.             patch->originx = SHORT(mpatch->originx);
  551.             patch->originy = SHORT(mpatch->originy);
  552.             patch->patch = patchlookup[SHORT(mpatch->patch)];
  553.             if (patch->patch == -1)
  554.             {
  555.                 I_Error ("R_InitTextures: Missing patch in texture %s",
  556.                          texture->name);
  557.             }
  558.         }              
  559.         texturecolumnlump[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
  560.         texturecolumnofs[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
  561.  
  562.         j = 1;
  563.         while (j*2 <= texture->width)
  564.             j<<=1;
  565.  
  566.         texturewidthmask[i] = j-1;
  567.         textureheight[i] = texture->height<<FRACBITS;
  568.                
  569.         totalwidth += texture->width;
  570.     }
  571.  
  572.     Z_Free (maptex1);
  573.     if (maptex2)
  574.         Z_Free (maptex2);
  575.    
  576.     // Precalculate whatever possible. 
  577.     for (i=0 ; i<numtextures ; i++)
  578.         R_GenerateLookup (i);
  579.    
  580.     // Create translation table for global animation.
  581.     texturetranslation = Z_Malloc ((numtextures+1)*4, PU_STATIC, 0);
  582.    
  583.     for (i=0 ; i<numtextures ; i++)
  584.         texturetranslation[i] = i;
  585. }
  586.  
  587.  
  588.  
  589. //
  590. // R_InitFlats
  591. //
  592. void R_InitFlats (void)
  593. {
  594.     int         i;
  595.        
  596.     firstflat = W_GetNumForName ("F_START") + 1;
  597.     lastflat = W_GetNumForName ("F_END") - 1;
  598.     numflats = lastflat - firstflat + 1;
  599.        
  600.     // Create translation table for global animation.
  601.     flattranslation = Z_Malloc ((numflats+1)*4, PU_STATIC, 0);
  602.    
  603.     for (i=0 ; i<numflats ; i++)
  604.         flattranslation[i] = i;
  605. }
  606.  
  607.  
  608. //
  609. // R_InitSpriteLumps
  610. // Finds the width and hoffset of all sprites in the wad,
  611. //  so the sprite does not need to be cached completely
  612. //  just for having the header info ready during rendering.
  613. //
  614. void R_InitSpriteLumps (void)
  615. {
  616.     int         i;
  617.     patch_t     *patch;
  618.        
  619.     firstspritelump = W_GetNumForName ("S_START") + 1;
  620.     lastspritelump = W_GetNumForName ("S_END") - 1;
  621.    
  622.     numspritelumps = lastspritelump - firstspritelump + 1;
  623.     spritewidth = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  624.     spriteoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  625.     spritetopoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  626.        
  627.     for (i=0 ; i< numspritelumps ; i++)
  628.     {
  629.         if (!(i&63))
  630.             printf (".");
  631.  
  632.         patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE);
  633.         spritewidth[i] = SHORT(patch->width)<<FRACBITS;
  634.         spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS;
  635.         spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS;
  636.     }
  637. }
  638.  
  639.  
  640.  
  641. //
  642. // R_InitColormaps
  643. //
  644. void R_InitColormaps (void)
  645. {
  646.     int lump, length;
  647.    
  648.     // Load in the light tables,
  649.     //  256 byte align tables.
  650.     lump = W_GetNumForName("COLORMAP");
  651.     length = W_LumpLength (lump) + 255;
  652.     colormaps = Z_Malloc (length, PU_STATIC, 0);
  653.     colormaps = (byte *)( ((int)colormaps + 255)&~0xff);
  654.     W_ReadLump (lump,colormaps);
  655. }
  656.  
  657.  
  658.  
  659. //
  660. // R_InitData
  661. // Locates all the lumps
  662. //  that will be used by all views
  663. // Must be called after W_Init.
  664. //
  665. void R_InitData (void)
  666. {
  667.     R_InitTextures ();
  668.     printf ("\nInitTextures");
  669.     R_InitFlats ();
  670.     printf ("\nInitFlats");
  671.     R_InitSpriteLumps ();
  672.     printf ("\nInitSprites");
  673.     R_InitColormaps ();
  674.     printf ("\nInitColormaps");
  675. }
  676.  
  677.  
  678.  
  679. //
  680. // R_FlatNumForName
  681. // Retrieval, get a flat number for a flat name.
  682. //
  683. int R_FlatNumForName (char* name)
  684. {
  685.     int         i;
  686.     char        namet[9];
  687.  
  688.     i = W_CheckNumForName (name);
  689.  
  690.     if (i == -1)
  691.     {
  692.         namet[8] = 0;
  693.         memcpy (namet, name,8);
  694.         I_Error ("R_FlatNumForName: %s not found",namet);
  695.     }
  696.     return i - firstflat;
  697. }
  698.  
  699.  
  700.  
  701.  
  702. //
  703. // R_CheckTextureNumForName
  704. // Check whether texture is available.
  705. // Filter out NoTexture indicator.
  706. //
  707. int     R_CheckTextureNumForName (char *name)
  708. {
  709.     int         i;
  710.  
  711.     // "NoTexture" marker.
  712.     if (name[0] == '-')        
  713.         return 0;
  714.                
  715.     for (i=0 ; i<numtextures ; i++)
  716.         if (!I_strncasecmp (textures[i]->name, name, 8) )
  717.             return i;
  718.                
  719.     return -1;
  720. }
  721.  
  722.  
  723.  
  724. //
  725. // R_TextureNumForName
  726. // Calls R_CheckTextureNumForName,
  727. //  aborts with error message.
  728. //
  729. int     R_TextureNumForName (char* name)
  730. {
  731.     int         i;
  732.        
  733.     i = R_CheckTextureNumForName (name);
  734.  
  735.     if (i==-1)
  736.     {
  737.         I_Error ("R_TextureNumForName: %s not found",
  738.                  name);
  739.     }
  740.     return i;
  741. }
  742.  
  743.  
  744.  
  745.  
  746. //
  747. // R_PrecacheLevel
  748. // Preloads all relevant graphics for the level.
  749. //
  750. int             flatmemory;
  751. int             texturememory;
  752. int             spritememory;
  753.  
  754. void R_PrecacheLevel (void)
  755. {
  756.     char*               flatpresent;
  757.     char*               texturepresent;
  758.     char*               spritepresent;
  759.  
  760.     int                 i;
  761.     int                 j;
  762.     int                 k;
  763.     int                 lump;
  764.    
  765.     texture_t*          texture;
  766.     thinker_t*          th;
  767.     spriteframe_t*      sf;
  768.  
  769.     if (demoplayback)
  770.         return;
  771.    
  772.     // Precache flats.
  773.     flatpresent = alloca(numflats);
  774.     memset (flatpresent,0,numflats);   
  775.  
  776.     for (i=0 ; i<numsectors ; i++)
  777.     {
  778.         flatpresent[sectors[i].floorpic] = 1;
  779.         flatpresent[sectors[i].ceilingpic] = 1;
  780.     }
  781.        
  782.     flatmemory = 0;
  783.  
  784.     for (i=0 ; i<numflats ; i++)
  785.     {
  786.         if (flatpresent[i])
  787.         {
  788.             lump = firstflat + i;
  789.             flatmemory += lumpinfo[lump].size;
  790.             W_CacheLumpNum(lump, PU_CACHE);
  791.         }
  792.     }
  793.    
  794.     // Precache textures.
  795.     texturepresent = alloca(numtextures);
  796.     memset (texturepresent,0, numtextures);
  797.        
  798.     for (i=0 ; i<numsides ; i++)
  799.     {
  800.         texturepresent[sides[i].toptexture] = 1;
  801.         texturepresent[sides[i].midtexture] = 1;
  802.         texturepresent[sides[i].bottomtexture] = 1;
  803.     }
  804.  
  805.     // Sky texture is always present.
  806.     // Note that F_SKY1 is the name used to
  807.     //  indicate a sky floor/ceiling as a flat,
  808.     //  while the sky texture is stored like
  809.     //  a wall texture, with an episode dependend
  810.     //  name.
  811.     texturepresent[skytexture] = 1;
  812.        
  813.     texturememory = 0;
  814.     for (i=0 ; i<numtextures ; i++)
  815.     {
  816.         if (!texturepresent[i])
  817.             continue;
  818.  
  819.         texture = textures[i];
  820.        
  821.         for (j=0 ; j<texture->patchcount ; j++)
  822.         {
  823.             lump = texture->patches[j].patch;
  824.             texturememory += lumpinfo[lump].size;
  825.             W_CacheLumpNum(lump , PU_CACHE);
  826.         }
  827.     }
  828.    
  829.     // Precache sprites.
  830.     spritepresent = alloca(numsprites);
  831.     memset (spritepresent,0, numsprites);
  832.        
  833.     for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  834.     {
  835.         if (th->function.acp1 == (actionf_p1)P_MobjThinker)
  836.             spritepresent[((mobj_t *)th)->sprite] = 1;
  837.     }
  838.        
  839.     spritememory = 0;
  840.     for (i=0 ; i<numsprites ; i++)
  841.     {
  842.         if (!spritepresent[i])
  843.             continue;
  844.  
  845.         for (j=0 ; j<sprites[i].numframes ; j++)
  846.         {
  847.             sf = &sprites[i].spriteframes[j];
  848.             for (k=0 ; k<8 ; k++)
  849.             {
  850.                 lump = firstspritelump + sf->lump[k];
  851.                 spritememory += lumpinfo[lump].size;
  852.                 W_CacheLumpNum(lump , PU_CACHE);
  853.             }
  854.         }
  855.     }
  856. }
  857.  
  858.  
  859.  
  860.  
  861.