1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
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.
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
19 // Revision 1.3 1997/01/29 20:10
21 // Preparation of data for rendering,
22 // generation of lookups, caching, retrieval by name.
24 //-----------------------------------------------------------------------------
28 rcsid[] = "$Id: r_data.c,v 1.4 1997/02/03 16:47:55 b1 Exp $";
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.
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.
79 /* Texture definition.
80 ** A DOOM wall texture is a list of patches
81 ** which are to be combined in a predefined order.
89 long columndirectory; // OBSOLETE
91 mappatch_t patches[1];
96 /* A single patch from a texture definition,
97 ** basically a rectangular area within
98 ** the texture rectangle.
102 /* Block origin (allways UL),
103 ** which has allready accounted
104 ** for the internal origin of the patch.
112 /* A maptexturedef_t describes a rectangular texture,
113 ** which is composed of one or more mappatch_t structures
114 ** that arrange graphic patches.
118 /* Keep name for switch changing, etc. */
123 /* All the patches[patchcount]
124 ** are drawn back to front into the cached texture.
127 texpatch_t patches[1];
143 texture_t** textures;
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;
154 // for global animation
155 int* flattranslation;
156 int* texturetranslation;
158 // needed for pre rendering
159 fixed_t* spritewidth;
160 fixed_t* spriteoffset;
161 fixed_t* spritetopoffset;
163 lighttable_t *colormaps;
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.
181 // R_DrawColumnInCache
182 // Clip and draw a column
183 // from a patch into a cached post.
196 while (patch->topdelta != 0xff)
198 source = (byte *)patch + 3;
199 count = patch->length;
200 position = originy + patch->topdelta;
208 if (position + count > cacheheight)
209 count = cacheheight - position;
212 memcpy (cache + position, source, count);
214 patch = (column_t *)( (byte *)patch + patch->length + 4);
221 // R_GenerateComposite
222 // Using the texture definition,
223 // the composite texture is created from the patches,
224 // and each column is cached.
226 void R_GenerateComposite (int texnum)
238 unsigned short* colofs;
240 texture = textures[texnum];
242 block = Z_Malloc (texturecompositesize[texnum],
244 &texturecomposite[texnum]);
246 collump = texturecolumnlump[texnum];
247 colofs = texturecolumnofs[texnum];
249 // Composite the columns together.
250 for (i=0 , patch = texture->patches;
251 i<texture->patchcount;
254 realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
256 x2 = x1 + SHORT(realpatch->width);
263 if (x2 > texture->width)
268 // Column does not have multiple patches?
272 patchcol = (column_t *)((byte *)realpatch
273 + LONG(realpatch->columnofs[x-x1]));
274 R_DrawColumnInCache (patchcol,
282 // Now that the texture has been built in column cache,
283 // it is purgable from zone memory.
284 Z_ChangeTag (block, PU_CACHE);
292 void R_GenerateLookup (int texnum)
295 byte* patchcount; // patchcount[texture->width]
296 byte* freepatchcount;
304 unsigned short* colofs;
306 texture = textures[texnum];
308 // Composited texture not created yet.
309 texturecomposite[texnum] = 0;
311 texturecompositesize[texnum] = 0;
312 collump = texturecolumnlump[texnum];
313 colofs = texturecolumnofs[texnum];
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);
322 for (i=0 , patch = texture->patches;
323 i<texture->patchcount;
326 realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
328 x2 = x1 + SHORT(realpatch->width);
335 if (x2 > texture->width)
340 collump[x] = patch->patch;
341 colofs[x] = LONG(realpatch->columnofs[x-x1])+3;
345 for (x=0 ; x<texture->width ; x++)
349 printf ("R_GenerateLookup: column without a patch (%s)\n",
353 // I_Error ("R_GenerateLookup: column without a patch");
355 if (patchcount[x] > 1)
357 // Use the cached block.
359 colofs[x] = texturecompositesize[texnum];
361 if (texturecompositesize[texnum] > 0x10000-texture->height)
363 I_Error ("R_GenerateLookup: texture %i is >64k",
367 texturecompositesize[texnum] += texture->height;
373 free(freepatchcount);
390 col &= texturewidthmask[tex];
391 lump = texturecolumnlump[tex][col];
392 ofs = texturecolumnofs[tex][col];
395 return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs;
397 if (!texturecomposite[tex])
398 R_GenerateComposite (tex);
400 return texturecomposite[tex] + ofs;
408 // Initializes the texture list
409 // with the textures from the world map.
411 void R_InitTextures (void)
413 maptexture_t* mtexture;
446 // Load the patch names from pnames.lmp.
448 names = W_CacheLumpName ("PNAMES", PU_STATIC);
449 nummappatches = LONG ( *((int *)names) );
451 patchlookup = malloc (nummappatches*sizeof(*patchlookup));
453 for (i=0 ; i<nummappatches ; i++)
455 strncpy (name,name_p+i*8, 8);
456 patchlookup[i] = W_CheckNumForName (name);
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;
468 if (W_CheckNumForName ("TEXTURE2") != -1)
470 maptex2 = W_CacheLumpName ("TEXTURE2", PU_STATIC);
471 numtextures2 = LONG(*maptex2);
472 maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2"));
480 numtextures = numtextures1 + numtextures2;
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);
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);
497 for (i = 0; i < temp3; i++)
500 for (i = 0; i < temp3; i++)
502 printf("\x8\x8\x8\x8\x8\x8\x8\x8\x8\x8");
504 for (i=0 ; i<numtextures ; i++, directory++)
509 if (i == numtextures1)
511 // Start looking in second texture file.
514 directory = maptex+1;
517 offset = LONG(*directory);
519 I_Error ("R_InitTextures: bad texture directory");
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),
527 texture->width = SHORT(mtexture->width);
528 texture->height = SHORT(mtexture->height);
529 texture->patchcount = SHORT(mtexture->patchcount);
531 memcpy (texture->name, mtexture->name, sizeof(texture->name));
532 mpatch = &mtexture->patches[0];
533 patch = &texture->patches[0];
535 for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
537 patch->originx = SHORT(mpatch->originx);
538 patch->originy = SHORT(mpatch->originy);
539 patch->patch = patchlookup[SHORT(mpatch->patch)];
540 if (patch->patch == -1)
542 I_Error ("R_InitTextures: Missing patch in texture %s",
546 texturecolumnlump[i] = Z_Malloc (texture->width*sizeof(short), PU_STATIC,0);
547 texturecolumnofs[i] = Z_Malloc (texture->width*sizeof(short), PU_STATIC,0);
550 while (j*2 <= texture->width)
553 texturewidthmask[i] = j-1;
554 textureheight[i] = texture->height<<FRACBITS;
556 totalwidth += texture->width;
563 // Precalculate whatever possible.
564 for (i=0 ; i<numtextures ; i++)
565 R_GenerateLookup (i);
567 // Create translation table for global animation.
568 texturetranslation = Z_Malloc ((numtextures+1)*sizeof(int), PU_STATIC, 0);
570 for (i=0 ; i<numtextures ; i++)
571 texturetranslation[i] = i;
581 void R_InitFlats (void)
585 firstflat = W_GetNumForName ("F_START") + 1;
586 lastflat = W_GetNumForName ("F_END") - 1;
587 numflats = lastflat - firstflat + 1;
589 // Create translation table for global animation.
590 flattranslation = Z_Malloc ((numflats+1)*sizeof(int), PU_STATIC, 0);
592 for (i=0 ; i<numflats ; i++)
593 flattranslation[i] = i;
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.
603 void R_InitSpriteLumps (void)
608 firstspritelump = W_GetNumForName ("S_START") + 1;
609 lastspritelump = W_GetNumForName ("S_END") - 1;
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);
616 for (i=0 ; i< numspritelumps ; i++)
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;
633 void R_InitColormaps (void)
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);
650 // Locates all the lumps
651 // that will be used by all views
652 // Must be called after W_Init.
654 void R_InitData (void)
657 printf ("\nInitTextures");
659 printf ("\nInitFlats");
660 R_InitSpriteLumps ();
661 printf ("\nInitSprites");
663 printf ("\nInitColormaps");
670 // Retrieval, get a flat number for a flat name.
672 int R_FlatNumForName (char* name)
677 i = W_CheckNumForName (name);
682 memcpy (namet, name,8);
683 I_Error ("R_FlatNumForName: %s not found",namet);
685 return i - firstflat;
692 // R_CheckTextureNumForName
693 // Check whether texture is available.
694 // Filter out NoTexture indicator.
696 int R_CheckTextureNumForName (char *name)
700 // "NoTexture" marker.
704 for (i=0 ; i<numtextures ; i++)
705 if (!cistrncmp (textures[i]->name, name, 8) )
714 // R_TextureNumForName
715 // Calls R_CheckTextureNumForName,
716 // aborts with error message.
718 int R_TextureNumForName (char* name)
722 i = R_CheckTextureNumForName (name);
726 I_Error ("R_TextureNumForName: %s not found",
737 // Preloads all relevant graphics for the level.
743 void R_PrecacheLevel (void)
746 char* texturepresent;
762 flatpresent = malloc(numflats);
763 memset (flatpresent,0,numflats);
765 for (i=0 ; i<numsectors ; i++)
767 flatpresent[sectors[i].floorpic] = 1;
768 flatpresent[sectors[i].ceilingpic] = 1;
773 for (i=0 ; i<numflats ; i++)
777 lump = firstflat + i;
778 flatmemory += lumpinfo[lump].size;
779 W_CacheLumpNum(lump, PU_CACHE);
783 // Precache textures.
784 texturepresent = malloc(numtextures);
785 memset (texturepresent,0, numtextures);
787 for (i=0 ; i<numsides ; i++)
789 texturepresent[sides[i].toptexture] = 1;
790 texturepresent[sides[i].midtexture] = 1;
791 texturepresent[sides[i].bottomtexture] = 1;
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
800 texturepresent[skytexture] = 1;
803 for (i=0 ; i<numtextures ; i++)
805 if (!texturepresent[i])
808 texture = textures[i];
810 for (j=0 ; j<texture->patchcount ; j++)
812 lump = texture->patches[j].patch;
813 texturememory += lumpinfo[lump].size;
814 W_CacheLumpNum(lump , PU_CACHE);
819 spritepresent = malloc(numsprites);
820 memset (spritepresent,0, numsprites);
822 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
824 if (th->function == P_MobjThinker)
825 spritepresent[((mobj_t *)th)->sprite] = 1;
829 for (i=0 ; i<numsprites ; i++)
831 if (!spritepresent[i])
834 for (j=0 ; j<sprites[i].numframes ; j++)
836 sf = &sprites[i].spriteframes[j];
837 for (k=0 ; k<8 ; k++)
839 lump = firstspritelump + sf->lump[k];
840 spritememory += lumpinfo[lump].size;
841 W_CacheLumpNum(lump , PU_CACHE);
847 free(texturepresent);