diff --git a/src/p_setup.c b/src/p_setup.c index 1061dbd0c..97bace860 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -564,8 +564,11 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) // store the flat lump number levelflat->lumpnum = R_GetFlatNumForName(flatname); - // Lactozilla levelflat->texturenum = R_CheckTextureNumForName(flatname); + levelflat->lasttexturenum = levelflat->texturenum; + + levelflat->baselumpnum = LUMPERROR; + levelflat->basetexturenum = -1; #ifndef ZDEBUG CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); diff --git a/src/p_setup.h b/src/p_setup.h index eda6066d3..824584be7 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -36,20 +36,22 @@ typedef struct { char name[9]; // resource name from wad lumpnum_t lumpnum; // lump number of the flat + INT32 texturenum, lasttexturenum; // texture number of the flat + UINT16 width, height; + fixed_t topoffset, leftoffset; // for flat animation lumpnum_t baselumpnum; + INT32 basetexturenum; INT32 animseq; // start pos. in the anim sequence INT32 numpics; INT32 speed; - // Lactozilla + // for patchflats UINT8 *flatpatch; - UINT16 width, height; - fixed_t topoffset, leftoffset; - INT32 texturenum; #ifdef ESLOPE + // rescaled version of the above UINT8 *resizedflat; UINT16 resizedwidth, resizedheight; #endif diff --git a/src/p_spec.c b/src/p_spec.c index 60d784324..7fe18eec1 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -584,7 +584,19 @@ static inline void P_FindAnimatedFlat(INT32 animnum) for (i = 0; i < numlevelflats; i++, foundflats++) { // is that levelflat from the flat anim sequence ? - if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum) + if ((anims[animnum].istexture) && (foundflats->texturenum != 0 && foundflats->texturenum != -1) + && ((UINT16)foundflats->texturenum >= startflatnum && (UINT16)foundflats->texturenum <= endflatnum)) + { + foundflats->basetexturenum = startflatnum; + foundflats->animseq = foundflats->texturenum - startflatnum; + foundflats->numpics = endflatnum - startflatnum + 1; + foundflats->speed = anims[animnum].speed; + + CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n", + atoi(sizeu1(i)), foundflats->name, foundflats->animseq, + foundflats->numpics,foundflats->speed); + } + else if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum) { foundflats->baselumpnum = startflatnum; foundflats->animseq = foundflats->lumpnum - startflatnum; @@ -608,10 +620,7 @@ void P_SetupLevelFlatAnims(void) // the original game flat anim sequences for (i = 0; anims[i].istexture != -1; i++) - { - if (!anims[i].istexture) - P_FindAnimatedFlat(i); - } + P_FindAnimatedFlat(i); } // @@ -4794,9 +4803,12 @@ void P_UpdateSpecials(void) { if (foundflats->speed) // it is an animated flat { + // update the levelflat texture number + if (foundflats->basetexturenum != -1) + foundflats->texturenum = foundflats->basetexturenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); // update the levelflat lump number - foundflats->lumpnum = foundflats->baselumpnum + - ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); + else if (foundflats->baselumpnum != LUMPERROR) + foundflats->lumpnum = foundflats->baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); } } } diff --git a/src/r_data.c b/src/r_data.c index 00d8de629..4157a8850 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -98,6 +98,7 @@ INT32 numtextures = 0; // total number of textures found, // size of following tables texture_t **textures = NULL; +textureflat_t *texflats = NULL; static UINT32 **texturecolumnofs; // column offset lookup table for each texture static UINT8 **texturecache; // graphics data for each generated full-size texture @@ -395,6 +396,7 @@ void R_LoadTextures(void) } Z_Free(texturetranslation); Z_Free(textures); + Z_Free(texflats); } // Load patches and textures. @@ -440,6 +442,7 @@ void R_LoadTextures(void) // Allocate memory and initialize to 0 for all the textures we are initialising. // There are actually 5 buffers allocated in one for convenience. textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL); + texflats = Z_Calloc((numtextures * sizeof(*texflats)), PU_STATIC, NULL); // Allocate texture column offset table. texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *))); @@ -1015,10 +1018,10 @@ lumpnum_t R_GetFlatNumForName(const char *name) lump = LUMPERROR; } - // Lactozilla + // Detect textures if (lump == LUMPERROR) { - // Scan wad files backwards so patched flats take preference. + // Scan wad files backwards so patched textures take preference. for (i = numwadfiles - 1; i >= 0; i--) { switch (wadfiles[i]->type) @@ -1683,7 +1686,6 @@ boolean R_CheckIfPatch(lumpnum_t lump) return result; } -// Lactozilla void R_FlatPatch(patch_t *patch, UINT8 *flat) { fixed_t col, ofs; diff --git a/src/r_data.h b/src/r_data.h index 8cb41cd2f..855daa06d 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -48,8 +48,20 @@ typedef struct texpatch_t patches[0]; } texture_t; +typedef struct +{ + UINT8 *flat; + INT16 width, height; + +#ifdef ESLOPE + UINT8 *resizedflat; + INT16 resizedwidth, resizedheight; +#endif +} textureflat_t; + // all loaded and prepared textures from the start of the game extern texture_t **textures; +extern textureflat_t *texflats; extern INT32 *texturewidth; extern fixed_t *textureheight; // needed for texture pegging @@ -94,7 +106,6 @@ const char *R_ColormapNameForNum(INT32 num); boolean R_CheckIfPatch(lumpnum_t lump); -// Lactozilla void R_FlatPatch(patch_t *patch, UINT8 *flat); void R_FlatTexture(size_t tex, UINT8 *flat); void R_CropFlat(UINT8 *srcflat, UINT8 *destflat, diff --git a/src/r_plane.c b/src/r_plane.c index 91b4f5f2c..01d0fdd37 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -653,96 +653,191 @@ void R_DrawPlanes(void) #endif } -// Lactozilla +boolean R_CheckPowersOfTwo(void) +{ + return (ds_powersoftwo = ((!((ds_flatwidth & (ds_flatwidth - 1)) || (ds_flatheight & (ds_flatheight - 1)))) && (ds_flatwidth == ds_flatheight))); +} + +void R_CheckFlatLength(size_t size) +{ + switch (size) + { + case 4194304: // 2048x2048 lump + nflatmask = 0x3FF800; + nflatxshift = 21; + nflatyshift = 10; + nflatshiftup = 5; + ds_flatwidth = ds_flatheight = 2048; + break; + case 1048576: // 1024x1024 lump + nflatmask = 0xFFC00; + nflatxshift = 22; + nflatyshift = 12; + nflatshiftup = 6; + ds_flatwidth = ds_flatheight = 1024; + break; + case 262144:// 512x512 lump + nflatmask = 0x3FE00; + nflatxshift = 23; + nflatyshift = 14; + nflatshiftup = 7; + ds_flatwidth = ds_flatheight = 512; + break; + case 65536: // 256x256 lump + nflatmask = 0xFF00; + nflatxshift = 24; + nflatyshift = 16; + nflatshiftup = 8; + ds_flatwidth = ds_flatheight = 256; + break; + case 16384: // 128x128 lump + nflatmask = 0x3F80; + nflatxshift = 25; + nflatyshift = 18; + nflatshiftup = 9; + ds_flatwidth = ds_flatheight = 128; + break; + case 1024: // 32x32 lump + nflatmask = 0x3E0; + nflatxshift = 27; + nflatyshift = 22; + nflatshiftup = 11; + ds_flatwidth = ds_flatheight = 32; + break; + default: // 64x64 lump + nflatmask = 0xFC0; + nflatxshift = 26; + nflatyshift = 20; + nflatshiftup = 10; + ds_flatwidth = ds_flatheight = 64; + break; + } +} + static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture) { + textureflat_t *texflat = &texflats[levelflat->texturenum]; patch_t *patch = NULL; + UINT8 *tex; + boolean texturechanged = (leveltexture ? (levelflat->texturenum != levelflat->lasttexturenum) : false); - if (levelflat->flatpatch == NULL) + // Check if the texture changed. + if (leveltexture && (!texturechanged)) + { + if (texflat != NULL && texflat->flat) + { + ds_source = texflat->flat; + ds_flatwidth = texflat->width; + ds_flatheight = texflat->height; + texturechanged = false; + } + else + texturechanged = true; + } + + // If the texture changed, or the patch doesn't exist, convert either of them to a flat. + if (levelflat->flatpatch == NULL || texturechanged) { #ifdef ESLOPE INT32 resizewidth, resizeheight, newresize; INT32 checkresizewidth, checkresizeheight; #endif // ESLOPE - if (!leveltexture) + if (leveltexture) + { + texture_t *texture = textures[levelflat->texturenum]; + texflat->width = ds_flatwidth = texture->width; + texflat->height = ds_flatheight = texture->height; + + texflat->flat = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL); + memset(texflat->flat, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight); + R_FlatTexture(levelflat->texturenum, texflat->flat); + + ds_source = texflat->flat; + } + else { patch = (patch_t *)ds_source; levelflat->width = ds_flatwidth = patch->width; levelflat->height = ds_flatheight = patch->height; + levelflat->topoffset = patch->topoffset * FRACUNIT; + levelflat->leftoffset = patch->leftoffset * FRACUNIT; + levelflat->flatpatch = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL); memset(levelflat->flatpatch, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight); R_FlatPatch(patch, levelflat->flatpatch); - levelflat->topoffset = patch->topoffset * FRACUNIT; - levelflat->leftoffset = patch->leftoffset * FRACUNIT; + ds_source = levelflat->flatpatch; } - else - { - texture_t *texture = textures[levelflat->texturenum]; - levelflat->width = ds_flatwidth = texture->width; - levelflat->height = ds_flatheight = texture->height; - levelflat->flatpatch = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL); - memset(levelflat->flatpatch, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight); - R_FlatTexture(levelflat->texturenum, levelflat->flatpatch); - - levelflat->topoffset = levelflat->leftoffset = 0; - } - ds_source = levelflat->flatpatch; - - // If GZDoom has the same limitation then I'm not even going to bother. - // Crop the texture. #ifdef ESLOPE - // Scale up to nearest power of 2 - resizewidth = resizeheight = 1; - while (resizewidth < levelflat->width) - resizewidth <<= 1; - while (resizeheight < levelflat->height) - resizeheight <<= 1; - - // Scale down to fit in 2048x2048 - if (resizewidth > 2048) - resizewidth = 2048; - if (resizeheight > 2048) - resizeheight = 2048; - - // A single pixel difference is negligible. - checkresizewidth = levelflat->width - 1; - if (checkresizewidth & (checkresizewidth - 1)) + // Crop the flat, if necessary. + if (!R_CheckPowersOfTwo()) { - checkresizewidth += 2; + // Scale up to nearest power of 2 + resizewidth = resizeheight = 1; + while (resizewidth < ds_flatwidth) + resizewidth <<= 1; + while (resizeheight < ds_flatheight) + resizeheight <<= 1; + + // Scale down to fit in 2048x2048 + if (resizewidth > 2048) + resizewidth = 2048; + if (resizeheight > 2048) + resizeheight = 2048; + + // A single pixel difference is negligible. + checkresizewidth = ds_flatwidth - 1; if (checkresizewidth & (checkresizewidth - 1)) { - while (resizewidth > levelflat->width) - resizewidth >>= 1; + checkresizewidth += 2; + if (checkresizewidth & (checkresizewidth - 1)) + { + while (resizewidth > ds_flatwidth) + resizewidth >>= 1; + } + else + resizewidth = checkresizewidth; } else resizewidth = checkresizewidth; - } - else - resizewidth = checkresizewidth; - checkresizeheight = levelflat->height - 1; - if (checkresizeheight & (checkresizeheight - 1)) - { - checkresizeheight += 2; + checkresizeheight = ds_flatheight - 1; if (checkresizeheight & (checkresizeheight - 1)) { - while (resizeheight > levelflat->height) - resizeheight >>= 1; + checkresizeheight += 2; + if (checkresizeheight & (checkresizeheight - 1)) + { + while (resizeheight > ds_flatheight) + resizeheight >>= 1; + } + else + resizeheight = checkresizeheight; } else resizeheight = checkresizeheight; - } - else - resizeheight = checkresizeheight; - levelflat->resizedwidth = levelflat->resizedheight = (newresize = min(resizewidth, resizeheight)); - levelflat->resizedflat = Z_Malloc(newresize * newresize, PU_LEVEL, NULL); - memset(levelflat->resizedflat, TRANSPARENTPIXEL, newresize * newresize); - R_CropFlat(levelflat->flatpatch, levelflat->resizedflat, levelflat->width, levelflat->height, min(resizewidth, newresize), min(resizeheight, newresize), newresize, newresize); + // Find smallest size. + newresize = min(resizewidth, resizeheight); + + // Allocate texture. + tex = Z_Malloc(newresize * newresize, PU_LEVEL, NULL); + memset(tex, TRANSPARENTPIXEL, newresize * newresize); + R_CropFlat(ds_source, tex, ds_flatwidth, ds_flatheight, min(resizewidth, newresize), min(resizeheight, newresize), newresize, newresize); + + if (leveltexture) + { + texflat->resizedflat = tex; + texflat->resizedwidth = texflat->resizedheight = newresize; + } + else + { + levelflat->resizedflat = tex; + levelflat->resizedwidth = levelflat->resizedheight = newresize; + } + } #endif // ESLOPE } else @@ -758,58 +853,26 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture) #ifdef ESLOPE if (currentplane->slope) { - ds_source = levelflat->resizedflat; - ds_flatwidth = levelflat->resizedwidth; - ds_flatheight = levelflat->resizedheight; - - // uuuuuuuhhhhhhhh....................... - switch (ds_flatwidth * ds_flatheight) + if (R_CheckPowersOfTwo()) { - case 4194304: // 2048x2048 lump - nflatmask = 0x3FF800; - nflatxshift = 21; - nflatyshift = 10; - nflatshiftup = 5; - break; - case 1048576: // 1024x1024 lump - nflatmask = 0xFFC00; - nflatxshift = 22; - nflatyshift = 12; - nflatshiftup = 6; - break; - case 262144:// 512x512 lump - nflatmask = 0x3FE00; - nflatxshift = 23; - nflatyshift = 14; - nflatshiftup = 7; - break; - case 65536: // 256x256 lump - nflatmask = 0xFF00; - nflatxshift = 24; - nflatyshift = 16; - nflatshiftup = 8; - break; - case 16384: // 128x128 lump - nflatmask = 0x3F80; - nflatxshift = 25; - nflatyshift = 18; - nflatshiftup = 9; - break; - case 1024: // 32x32 lump - nflatmask = 0x3E0; - nflatxshift = 27; - nflatyshift = 22; - nflatshiftup = 11; - break; - default: // 64x64 lump - nflatmask = 0xFC0; - nflatxshift = 26; - nflatyshift = 20; - nflatshiftup = 10; - break; + if (leveltexture) + { + ds_source = texflat->resizedflat; + ds_flatwidth = texflat->resizedwidth; + ds_flatheight = texflat->resizedheight; + } + else + { + ds_source = levelflat->resizedflat; + ds_flatwidth = levelflat->resizedwidth; + ds_flatheight = levelflat->resizedheight; + } } + R_CheckFlatLength(ds_flatwidth * ds_flatheight); } #endif // ESLOPE + + levelflat->lasttexturenum = levelflat->texturenum; } void R_DrawSinglePlane(visplane_t *pl) @@ -966,71 +1029,24 @@ void R_DrawSinglePlane(visplane_t *pl) currentplane = pl; levelflat = &levelflats[pl->picnum]; + size = W_LumpLength(levelflat->lumpnum); + // Check if the flat is actually a texture. if (levelflat->texturenum != 0 && levelflat->texturenum != -1) R_GetPatchFlat(levelflat, true); + // Check if the flat is actually a patch. + else if (R_CheckIfPatch(levelflat->lumpnum)) + R_GetPatchFlat(levelflat, false); + // Raw flat. else { ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag - size = W_LumpLength(levelflat->lumpnum); - - switch (size) - { - case 4194304: // 2048x2048 lump - nflatmask = 0x3FF800; - nflatxshift = 21; - nflatyshift = 10; - nflatshiftup = 5; - ds_flatwidth = ds_flatheight = 2048; - break; - case 1048576: // 1024x1024 lump - nflatmask = 0xFFC00; - nflatxshift = 22; - nflatyshift = 12; - nflatshiftup = 6; - ds_flatwidth = ds_flatheight = 1024; - break; - case 262144:// 512x512 lump - nflatmask = 0x3FE00; - nflatxshift = 23; - nflatyshift = 14; - nflatshiftup = 7; - ds_flatwidth = ds_flatheight = 512; - break; - case 65536: // 256x256 lump - nflatmask = 0xFF00; - nflatxshift = 24; - nflatyshift = 16; - nflatshiftup = 8; - ds_flatwidth = ds_flatheight = 256; - break; - case 16384: // 128x128 lump - nflatmask = 0x3F80; - nflatxshift = 25; - nflatyshift = 18; - nflatshiftup = 9; - ds_flatwidth = ds_flatheight = 128; - break; - case 1024: // 32x32 lump - nflatmask = 0x3E0; - nflatxshift = 27; - nflatyshift = 22; - nflatshiftup = 11; - ds_flatwidth = ds_flatheight = 32; - break; - default: // 64x64 lump - nflatmask = 0xFC0; - nflatxshift = 26; - nflatyshift = 20; - nflatshiftup = 10; - ds_flatwidth = ds_flatheight = 64; - break; - } + R_CheckFlatLength(size); } - if (R_CheckIfPatch(levelflat->lumpnum)) - R_GetPatchFlat(levelflat, false); - ds_powersoftwo = (!((ds_flatwidth & (ds_flatwidth - 1)) || (ds_flatheight & (ds_flatheight - 1)))); + // Check if the flat has dimensions that are powers-of-two numbers. + if (R_CheckPowersOfTwo()) + R_CheckFlatLength(ds_flatwidth * ds_flatheight); if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; diff --git a/src/r_plane.h b/src/r_plane.h index 6e6a6d49d..78aae3fa1 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -94,6 +94,8 @@ void R_PlaneBounds(visplane_t *plane); // Draws a single visplane. void R_DrawSinglePlane(visplane_t *pl); +void R_CheckFlatLength(size_t size); +boolean R_CheckPowersOfTwo(void); typedef struct planemgr_s {