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