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.
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.
80 /* Texture definition.
81 ** A DOOM wall texture is a list of patches
82 ** which are to be combined in a predefined order.
90 void **columndirectory; // OBSOLETE
92 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];
147 texture_t** textures;
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;
158 // for global animation
159 int* flattranslation;
160 int* texturetranslation;
162 // needed for pre rendering
163 fixed_t* spritewidth;
164 fixed_t* spriteoffset;
165 fixed_t* spritetopoffset;
167 lighttable_t *colormaps;
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.
185 // R_DrawColumnInCache
186 // Clip and draw a column
187 // from a patch into a cached post.
200 while (patch->topdelta != 0xff)
202 source = (byte *)patch + 3;
203 count = patch->length;
204 position = originy + patch->topdelta;
212 if (position + count > cacheheight)
213 count = cacheheight - position;
216 memcpy (cache + position, source, count);
218 patch = (column_t *)( (byte *)patch + patch->length + 4);
225 // R_GenerateComposite
226 // Using the texture definition,
227 // the composite texture is created from the patches,
228 // and each column is cached.
230 void R_GenerateComposite (int texnum)
242 unsigned short* colofs;
244 texture = textures[texnum];
246 block = Z_Malloc (texturecompositesize[texnum],
248 &texturecomposite[texnum]);
250 collump = texturecolumnlump[texnum];
251 colofs = texturecolumnofs[texnum];
253 // Composite the columns together.
254 for (i=0 , patch = texture->patches;
255 i<texture->patchcount;
258 realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
260 x2 = x1 + SHORT(realpatch->width);
267 if (x2 > texture->width)
272 // Column does not have multiple patches?
276 patchcol = (column_t *)((byte *)realpatch
277 + LONG(realpatch->columnofs[x-x1]));
278 R_DrawColumnInCache (patchcol,
286 // Now that the texture has been built in column cache,
287 // it is purgable from zone memory.
288 Z_ChangeTag (block, PU_CACHE);
296 void R_GenerateLookup (int texnum)
299 byte* patchcount; // patchcount[texture->width]
300 byte* freepatchcount;
308 unsigned short* colofs;
310 texture = textures[texnum];
312 // Composited texture not created yet.
313 texturecomposite[texnum] = 0;
315 texturecompositesize[texnum] = 0;
316 collump = texturecolumnlump[texnum];
317 colofs = texturecolumnofs[texnum];
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);
326 for (i=0 , patch = texture->patches;
327 i<texture->patchcount;
330 realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
332 x2 = x1 + SHORT(realpatch->width);
339 if (x2 > texture->width)
344 collump[x] = patch->patch;
345 colofs[x] = LONG(realpatch->columnofs[x-x1])+3;
349 for (x=0 ; x<texture->width ; x++)
353 printf ("R_GenerateLookup: column without a patch (%s)\n",
357 // I_Error ("R_GenerateLookup: column without a patch");
359 if (patchcount[x] > 1)
361 // Use the cached block.
363 colofs[x] = texturecompositesize[texnum];
365 if (texturecompositesize[texnum] > 0x10000-texture->height)
367 I_Error ("R_GenerateLookup: texture %i is >64k",
371 texturecompositesize[texnum] += texture->height;
377 free(freepatchcount);
394 col &= texturewidthmask[tex];
395 lump = texturecolumnlump[tex][col];
396 ofs = texturecolumnofs[tex][col];
399 return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs;
401 if (!texturecomposite[tex])
402 R_GenerateComposite (tex);
404 return texturecomposite[tex] + ofs;
412 // Initializes the texture list
413 // with the textures from the world map.
415 void R_InitTextures (void)
417 maptexture_t* mtexture;
450 // Load the patch names from pnames.lmp.
452 names = W_CacheLumpName ("PNAMES", PU_STATIC);
453 nummappatches = LONG ( *((int *)names) );
455 patchlookup = malloc (nummappatches*sizeof(*patchlookup));
457 for (i=0 ; i<nummappatches ; i++)
459 strncpy (name,name_p+i*8, 8);
460 patchlookup[i] = W_CheckNumForName (name);
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;
472 if (W_CheckNumForName ("TEXTURE2") != -1)
474 maptex2 = W_CacheLumpName ("TEXTURE2", PU_STATIC);
475 numtextures2 = LONG(*maptex2);
476 maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2"));
484 numtextures = numtextures1 + numtextures2;
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);
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);
501 for (i = 0; i < temp3; i++)
504 for (i = 0; i < temp3; i++)
506 printf("\x8\x8\x8\x8\x8\x8\x8\x8\x8\x8");
508 for (i=0 ; i<numtextures ; i++, directory++)
513 if (i == numtextures1)
515 // Start looking in second texture file.
518 directory = maptex+1;
521 offset = LONG(*directory);
524 I_Error ("R_InitTextures: bad texture directory");
526 mtexture = (maptexture_t *) ( (byte *)maptex + offset);
528 texture = textures[i] =
529 Z_Malloc (sizeof(texture_t)
530 + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1),
533 texture->width = SHORT(mtexture->width);
534 texture->height = SHORT(mtexture->height);
535 texture->patchcount = SHORT(mtexture->patchcount);
537 memcpy (texture->name, mtexture->name, sizeof(texture->name));
538 mpatch = &mtexture->patches[0];
539 patch = &texture->patches[0];
541 for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
543 patch->originx = SHORT(mpatch->originx);
544 patch->originy = SHORT(mpatch->originy);
545 patch->patch = patchlookup[SHORT(mpatch->patch)];
546 if (patch->patch == -1)
548 I_Error ("R_InitTextures: Missing patch in texture %s",
552 texturecolumnlump[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
553 texturecolumnofs[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
556 while (j*2 <= texture->width)
559 texturewidthmask[i] = j-1;
560 textureheight[i] = texture->height<<FRACBITS;
562 totalwidth += texture->width;
569 // Precalculate whatever possible.
570 for (i=0 ; i<numtextures ; i++)
571 R_GenerateLookup (i);
573 // Create translation table for global animation.
574 texturetranslation = Z_Malloc ((numtextures+1)*4, PU_STATIC, 0);
576 for (i=0 ; i<numtextures ; i++)
577 texturetranslation[i] = i;
587 void R_InitFlats (void)
591 firstflat = W_GetNumForName ("F_START") + 1;
592 lastflat = W_GetNumForName ("F_END") - 1;
593 numflats = lastflat - firstflat + 1;
595 // Create translation table for global animation.
596 flattranslation = Z_Malloc ((numflats+1)*4, PU_STATIC, 0);
598 for (i=0 ; i<numflats ; i++)
599 flattranslation[i] = i;
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.
609 void R_InitSpriteLumps (void)
614 firstspritelump = W_GetNumForName ("S_START") + 1;
615 lastspritelump = W_GetNumForName ("S_END") - 1;
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);
622 for (i=0 ; i< numspritelumps ; i++)
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;
639 void R_InitColormaps (void)
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);
656 // Locates all the lumps
657 // that will be used by all views
658 // Must be called after W_Init.
660 void R_InitData (void)
663 printf ("\nInitTextures");
665 printf ("\nInitFlats");
666 R_InitSpriteLumps ();
667 printf ("\nInitSprites");
669 printf ("\nInitColormaps");
676 // Retrieval, get a flat number for a flat name.
678 int R_FlatNumForName (char* name)
683 i = W_CheckNumForName (name);
688 memcpy (namet, name,8);
689 I_Error ("R_FlatNumForName: %s not found",namet);
691 return i - firstflat;
698 // R_CheckTextureNumForName
699 // Check whether texture is available.
700 // Filter out NoTexture indicator.
702 int R_CheckTextureNumForName (char *name)
706 // "NoTexture" marker.
710 for (i=0 ; i<numtextures ; i++)
711 if (!cistrncmp (textures[i]->name, name, 8) )
720 // R_TextureNumForName
721 // Calls R_CheckTextureNumForName,
722 // aborts with error message.
724 int R_TextureNumForName (char* name)
728 i = R_CheckTextureNumForName (name);
732 I_Error ("R_TextureNumForName: %s not found",
743 // Preloads all relevant graphics for the level.
749 void R_PrecacheLevel (void)
752 char* texturepresent;
768 flatpresent = malloc(numflats);
769 memset (flatpresent,0,numflats);
771 for (i=0 ; i<numsectors ; i++)
773 flatpresent[sectors[i].floorpic] = 1;
774 flatpresent[sectors[i].ceilingpic] = 1;
779 for (i=0 ; i<numflats ; i++)
783 lump = firstflat + i;
784 flatmemory += lumpinfo[lump].size;
785 W_CacheLumpNum(lump, PU_CACHE);
789 // Precache textures.
790 texturepresent = malloc(numtextures);
791 memset (texturepresent,0, numtextures);
793 for (i=0 ; i<numsides ; i++)
795 texturepresent[sides[i].toptexture] = 1;
796 texturepresent[sides[i].midtexture] = 1;
797 texturepresent[sides[i].bottomtexture] = 1;
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
806 texturepresent[skytexture] = 1;
809 for (i=0 ; i<numtextures ; i++)
811 if (!texturepresent[i])
814 texture = textures[i];
816 for (j=0 ; j<texture->patchcount ; j++)
818 lump = texture->patches[j].patch;
819 texturememory += lumpinfo[lump].size;
820 W_CacheLumpNum(lump , PU_CACHE);
825 spritepresent = malloc(numsprites);
826 memset (spritepresent,0, numsprites);
828 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
830 if (th->function == P_MobjThinker)
831 spritepresent[((mobj_t *)th)->sprite] = 1;
835 for (i=0 ; i<numsprites ; i++)
837 if (!spritepresent[i])
840 for (j=0 ; j<sprites[i].numframes ; j++)
842 sf = &sprites[i].spriteframes[j];
843 for (k=0 ; k<8 ; k++)
845 lump = firstspritelump + sf->lump[k];
846 spritememory += lumpinfo[lump].size;
847 W_CacheLumpNum(lump , PU_CACHE);
853 free(texturepresent);