diff options
Diffstat (limited to 'src/heretic/r_data.c')
-rw-r--r-- | src/heretic/r_data.c | 701 |
1 files changed, 701 insertions, 0 deletions
diff --git a/src/heretic/r_data.c b/src/heretic/r_data.c new file mode 100644 index 00000000..51c8fd7d --- /dev/null +++ b/src/heretic/r_data.c @@ -0,0 +1,701 @@ + +// R_data.c + +#include "DoomDef.h" +#include "R_local.h" +#include "P_local.h" + +extern void CheckAbortStartup(void); + +typedef struct +{ + int originx; // block origin (allways UL), which has allready + int originy; // accounted for the patch's internal origin + int patch; +} texpatch_t; + +// a maptexturedef_t describes a rectangular texture, which is composed of one +// or more mappatch_t structures that arrange graphic patches +typedef struct +{ + char name[8]; // for switch changing, etc + short width; + short height; + short patchcount; + texpatch_t patches[1]; // [patchcount] drawn back to front + // into the cached texture +} texture_t; + + + +int firstflat, lastflat, numflats; +int firstpatch, lastpatch, numpatches; +int firstspritelump, lastspritelump, numspritelumps; + +int numtextures; +texture_t **textures; +int *texturewidthmask; +fixed_t *textureheight; // needed for texture pegging +int *texturecompositesize; +short **texturecolumnlump; +unsigned short **texturecolumnofs; +byte **texturecomposite; + +int *flattranslation; // for global animation +int *texturetranslation; // for global animation + +fixed_t *spritewidth; // needed for pre rendering +fixed_t *spriteoffset; +fixed_t *spritetopoffset; + +lighttable_t *colormaps; + + +/* +============================================================================== + + MAPTEXTURE_T CACHING + +when a texture is first needed, it counts the number of composite columns +required in the texture and allocates space for a column directory and any +new columns. The directory will simply point inside other patches if there +is only one patch in a given column, but any columns with multiple patches +will have new column_ts generated. + +============================================================================== +*/ + +/* +=================== += += R_DrawColumnInCache += += Clip and draw a column from a patch into a cached post += +=================== +*/ + +void R_DrawColumnInCache (column_t *patch, byte *cache, int originy, int cacheheight) +{ + int count, position; + byte *source, *dest; + + dest = (byte *)cache + 3; + + while (patch->topdelta != 0xff) + { + source = (byte *)patch + 3; + count = patch->length; + position = originy + patch->topdelta; + if (position < 0) + { + count += position; + position = 0; + } + if (position + count > cacheheight) + count = cacheheight - position; + if (count > 0) + memcpy (cache + position, source, count); + + patch = (column_t *)( (byte *)patch + patch->length
+ 4);
+ } +} + + +/* +=================== += += R_GenerateComposite += +=================== +*/ + +void R_GenerateComposite (int texnum) +{ + byte *block; + texture_t *texture; + texpatch_t *patch; + patch_t *realpatch; + int x, x1, x2; + int i; + column_t *patchcol; + short *collump; + unsigned short *colofs; + + texture = textures[texnum]; + block = Z_Malloc (texturecompositesize[texnum], PU_STATIC, + &texturecomposite[texnum]); + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + +// +// composite the columns together +// + patch = texture->patches; + + for (i=0 , patch = texture->patches; i<texture->patchcount ; i++, patch++) + { + realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + + if (x1<0) + x = 0; + else + x = x1; + if (x2 > texture->width) + x2 = texture->width; + + for ( ; x<x2 ; x++) + { + if (collump[x] >= 0) + continue; // column does not have multiple patches + patchcol = (column_t *)((byte *)realpatch + + LONG(realpatch->columnofs[x-x1])); + R_DrawColumnInCache (patchcol, block + colofs[x], patch->originy, + texture->height); + } + + } + +// now that the texture has been built, it is purgable + Z_ChangeTag (block, PU_CACHE); +} + + +/* +=================== += += R_GenerateLookup += +=================== +*/ + +void R_GenerateLookup (int texnum) +{ + texture_t *texture; + byte *patchcount; // [texture->width] + texpatch_t *patch; + patch_t *realpatch; + int x, x1, x2; + int i; + short *collump; + unsigned short *colofs; + + texture = textures[texnum]; + + texturecomposite[texnum] = 0; // composited not created yet + texturecompositesize[texnum] = 0; + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + +// +// count the number of columns that are covered by more than one patch +// fill in the lump / offset, so columns with only a single patch are +// all done +// + patchcount = (byte *)alloca (texture->width); + memset (patchcount, 0, texture->width); + patch = texture->patches; + + for (i=0 , patch = texture->patches; i<texture->patchcount ; i++, patch++) + { + realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + if (x1 < 0) + x = 0; + else + x = x1; + if (x2 > texture->width) + x2 = texture->width; + for ( ; x<x2 ; x++) + { + patchcount[x]++; + collump[x] = patch->patch; + colofs[x] = LONG(realpatch->columnofs[x-x1])+3; + } + } + + for (x=0 ; x<texture->width ; x++) + { + if (!patchcount[x]) + { + printf ("R_GenerateLookup: column without a patch (%s)\n", texture->name); + return; + } +// I_Error ("R_GenerateLookup: column without a patch"); + if (patchcount[x] > 1) + { + collump[x] = -1; // use the cached block + colofs[x] = texturecompositesize[texnum]; + if (texturecompositesize[texnum] > 0x10000-texture->height) + I_Error ("R_GenerateLookup: texture %i is >64k",texnum); + texturecompositesize[texnum] += texture->height; + } + } +} + + +/* +================ += += R_GetColumn += +================ +*/ + +byte *R_GetColumn (int tex, int col) +{ + int lump, ofs; + + col &= texturewidthmask[tex]; + lump = texturecolumnlump[tex][col]; + ofs = texturecolumnofs[tex][col]; + if (lump > 0) + return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs; + if (!texturecomposite[tex]) + R_GenerateComposite (tex); + return texturecomposite[tex] + ofs; +} + + +/* +================== += += R_InitTextures += += Initializes the texture list with the textures from the world map += +================== +*/ + +void R_InitTextures (void) +{ + maptexture_t *mtexture; + texture_t *texture; + mappatch_t *mpatch; + texpatch_t *patch; + int i,j; + int *maptex, *maptex2, *maptex1; + char name[9], *names, *name_p; + int *patchlookup; + int totalwidth; + int nummappatches; + int offset, maxoff, maxoff2; + int numtextures1, numtextures2; + int *directory; + +// +// load the patch names from pnames.lmp +// + name[8] = 0; + names = W_CacheLumpName ("PNAMES", PU_STATIC); + nummappatches = LONG ( *((int *)names) ); + name_p = names+4; + patchlookup = alloca (nummappatches*sizeof(*patchlookup)); + for (i=0 ; i<nummappatches ; i++) + { + strncpy (name,name_p+i*8, 8); + patchlookup[i] = W_CheckNumForName (name); + } + Z_Free (names); + +// +// load the map texture definitions from textures.lmp +// + maptex = maptex1 = W_CacheLumpName ("TEXTURE1", PU_STATIC); + numtextures1 = LONG(*maptex); + maxoff = W_LumpLength (W_GetNumForName ("TEXTURE1")); + directory = maptex+1; + + if (W_CheckNumForName ("TEXTURE2") != -1) + { + maptex2 = W_CacheLumpName ("TEXTURE2", PU_STATIC); + numtextures2 = LONG(*maptex2); + maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2")); + } + else + { + maptex2 = NULL; + numtextures2 = 0; + maxoff2 = 0; + } + numtextures = numtextures1 + numtextures2; + + // + // Init the startup thermometer at this point... + // + { + int spramount; + spramount = W_GetNumForName("S_END") - W_GetNumForName("S_START") + 1; + InitThermo(spramount + numtextures + 6); + } + + textures = Z_Malloc (numtextures*4, PU_STATIC, 0); + texturecolumnlump = Z_Malloc (numtextures*4, PU_STATIC, 0); + texturecolumnofs = Z_Malloc (numtextures*4, PU_STATIC, 0); + texturecomposite = Z_Malloc (numtextures*4, PU_STATIC, 0); + texturecompositesize = Z_Malloc (numtextures*4, PU_STATIC, 0); + texturewidthmask = Z_Malloc (numtextures*4, PU_STATIC, 0); + textureheight = Z_Malloc (numtextures*4, PU_STATIC, 0); + + totalwidth = 0; + + for (i=0 ; i<numtextures ; i++, directory++) + { + #ifdef __NEXT__ + if(!(i&63)) + printf ("."); + #else + IncThermo(); + #endif + if (i == numtextures1) + { // start looking in second texture file + maptex = maptex2; + maxoff = maxoff2; + directory = maptex+1; + } + + offset = LONG(*directory); + if (offset > maxoff) + I_Error ("R_InitTextures: bad texture directory"); + mtexture = (maptexture_t *) ( (byte *)maptex + offset); + texture = textures[i] = Z_Malloc (sizeof(texture_t) + + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1), PU_STATIC, + 0); + texture->width = SHORT(mtexture->width); + texture->height = SHORT(mtexture->height); + texture->patchcount = SHORT(mtexture->patchcount); + memcpy (texture->name, mtexture->name, sizeof(texture->name)); + mpatch = &mtexture->patches[0]; + patch = &texture->patches[0]; + for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++) + { + patch->originx = SHORT(mpatch->originx); + patch->originy = SHORT(mpatch->originy); + patch->patch = patchlookup[SHORT(mpatch->patch)]; + if (patch->patch == -1) + I_Error ( + "R_InitTextures: Missing patch in texture %s",texture->name); + } + texturecolumnlump[i] = Z_Malloc (texture->width*2, PU_STATIC,0); + texturecolumnofs[i] = Z_Malloc (texture->width*2, PU_STATIC,0); + j = 1; + while (j*2 <= texture->width) + j<<=1; + texturewidthmask[i] = j-1; + textureheight[i] = texture->height<<FRACBITS; + + totalwidth += texture->width; + } + + Z_Free (maptex1); + if (maptex2) + Z_Free (maptex2); + +// +// precalculate whatever possible +// + for(i = 0; i < numtextures; i++) + { + R_GenerateLookup(i); + CheckAbortStartup(); + } + +// +// translation table for global animation +// + texturetranslation = Z_Malloc ((numtextures+1)*4, PU_STATIC, 0); + for (i=0 ; i<numtextures ; i++) + texturetranslation[i] = i; +} + + +/* +================ += += R_InitFlats += +================= +*/ + +void R_InitFlats (void) +{ + int i; + + firstflat = W_GetNumForName ("F_START") + 1; + lastflat = W_GetNumForName ("F_END") - 1; + numflats = lastflat - firstflat + 1; + +// translation table for global animation + flattranslation = Z_Malloc ((numflats+1)*4, PU_STATIC, 0); + for (i=0 ; i<numflats ; i++) + flattranslation[i] = i; +} + + +/* +================ += += R_InitSpriteLumps += += Finds the width and hoffset of all sprites in the wad, so the sprite doesn't += need to be cached just for the header during rendering +================= +*/ + +void R_InitSpriteLumps (void) +{ + int i; + patch_t *patch; + + firstspritelump = W_GetNumForName ("S_START") + 1; + lastspritelump = W_GetNumForName ("S_END") - 1; + numspritelumps = lastspritelump - firstspritelump + 1; + spritewidth = Z_Malloc (numspritelumps*4, PU_STATIC, 0); + spriteoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0); + spritetopoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0); + + for (i=0 ; i< numspritelumps ; i++) + { + #ifdef __NEXT__ + if (!(i&63)) + printf ("."); + #else + IncThermo(); + #endif + patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE); + spritewidth[i] = SHORT(patch->width)<<FRACBITS; + spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS; + spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS; + } +} + + +/* +================ += += R_InitColormaps += +================= +*/ + +void R_InitColormaps (void) +{ + int lump, length;
+//
+// load in the light tables
+// 256 byte align tables +// + lump = W_GetNumForName("COLORMAP");
+ length = W_LumpLength (lump) + 255;
+ colormaps = Z_Malloc (length, PU_STATIC, 0);
+ colormaps = (byte *)( ((int)colormaps + 255)&~0xff);
+ W_ReadLump (lump,colormaps);
+} + + +/* +================ += += R_InitData += += Locates all the lumps that will be used by all views += Must be called after W_Init +================= +*/ + +void R_InitData (void) +{ + tprintf("\nR_InitTextures ",0); + R_InitTextures (); +//printf ("."); + tprintf("R_InitFlats\n",0); + R_InitFlats (); + IncThermo(); +//printf ("."); + tprintf("R_InitSpriteLumps ",0); + R_InitSpriteLumps (); + IncThermo(); +//printf ("."); + R_InitColormaps (); +} + + +//============================================================================= + +/* +================ += += R_FlatNumForName += +================ +*/ + +int R_FlatNumForName (char *name) +{ + int i; + char namet[9]; + + i = W_CheckNumForName (name); + if (i == -1) + { + namet[8] = 0; + memcpy (namet, name,8); + I_Error ("R_FlatNumForName: %s not found",namet); + } + return i - firstflat; +} + + +/* +================ += += R_CheckTextureNumForName += +================ +*/ + +int R_CheckTextureNumForName (char *name) +{ + int i; + + if (name[0] == '-') // no texture marker + return 0; + + for (i=0 ; i<numtextures ; i++) + if (!strncasecmp (textures[i]->name, name, 8) ) + return i; + + return -1; +} + + +/* +================ += += R_TextureNumForName += +================ +*/ + +int R_TextureNumForName (char *name) +{ + int i; + //char namet[9]; + + i = R_CheckTextureNumForName (name); + if (i==-1) + I_Error ("R_TextureNumForName: %s not found",name); + + return i; +} + + +/* +================= += += R_PrecacheLevel += += Preloads all relevent graphics for the level +================= +*/ + +int flatmemory, texturememory, spritememory; + +void R_PrecacheLevel (void) +{ + char *flatpresent; + char *texturepresent; + char *spritepresent; + int i,j,k, lump; + texture_t *texture; + thinker_t *th; + spriteframe_t *sf; + + if (demoplayback) + return; + +// +// precache flats +// + flatpresent = alloca(numflats); + memset (flatpresent,0,numflats); + for (i=0 ; i<numsectors ; i++) + { + flatpresent[sectors[i].floorpic] = 1; + flatpresent[sectors[i].ceilingpic] = 1; + } + + flatmemory = 0; + for (i=0 ; i<numflats ; i++) + if (flatpresent[i]) + { + lump = firstflat + i; + flatmemory += lumpinfo[lump].size; + W_CacheLumpNum(lump, PU_CACHE); + } + +// +// precache textures +// + texturepresent = alloca(numtextures); + memset (texturepresent,0, numtextures); + + for (i=0 ; i<numsides ; i++) + { + texturepresent[sides[i].toptexture] = 1; + texturepresent[sides[i].midtexture] = 1; + texturepresent[sides[i].bottomtexture] = 1; + } + + texturepresent[skytexture] = 1; + + texturememory = 0; + for (i=0 ; i<numtextures ; i++) + { + if (!texturepresent[i]) + continue; + texture = textures[i]; + for (j=0 ; j<texture->patchcount ; j++) + { + lump = texture->patches[j].patch; + texturememory += lumpinfo[lump].size; + W_CacheLumpNum(lump , PU_CACHE); + } + } + +// +// precache sprites +// + spritepresent = alloca(numsprites); + memset (spritepresent,0, numsprites); + + for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + { + if (th->function == P_MobjThinker) + spritepresent[((mobj_t *)th)->sprite] = 1; + } + + spritememory = 0; + for (i=0 ; i<numsprites ; i++) + { + if (!spritepresent[i]) + continue; + for (j=0 ; j<sprites[i].numframes ; j++) + { + sf = &sprites[i].spriteframes[j]; + for (k=0 ; k<8 ; k++) + { + lump = firstspritelump + sf->lump[k]; + spritememory += lumpinfo[lump].size; + W_CacheLumpNum(lump , PU_CACHE); + } + } + } +} + + + + |