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