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