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