From 714c997aace85b7f873fa0c1a97224cec691baeb Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 21 May 2019 00:28:52 -0300 Subject: [PATCH 001/133] Support for patches and textures to be used in place of sector flats Still a work in progress. --- src/dehacked.c | 9 +- src/hardware/hw_cache.c | 81 ++++++- src/hardware/hw_glob.h | 3 + src/hardware/hw_main.c | 178 ++++++++------ src/p_setup.c | 4 + src/p_setup.h | 11 + src/p_spec.c | 4 +- src/r_data.c | 204 ++++++++++++++-- src/r_data.h | 12 +- src/r_draw.c | 2 + src/r_draw.h | 13 +- src/r_draw8.c | 499 ++++++++++++++++++---------------------- src/r_plane.c | 354 ++++++++++++++++------------ src/screen.c | 2 +- 14 files changed, 841 insertions(+), 535 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index a726ecbc1..bdef5f1be 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2699,7 +2699,7 @@ static void readtexture(MYFILE *f, const char *name) char *word; char *word2; char *tmp; - INT32 i, j, value; + INT32 i, value; UINT16 width = 0, height = 0; INT16 patchcount = 0; texture_t *texture; @@ -2783,13 +2783,8 @@ static void readtexture(MYFILE *f, const char *name) while (textures[i]) i++; - // Fill the global texture buffer entries. - j = 1; - while (j << 1 <= texture->width) - j <<= 1; - textures[i] = texture; - texturewidthmask[i] = j - 1; + texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; // Clean up. diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 78fc31afc..4ae7a43b9 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -30,6 +30,7 @@ #include "../z_zone.h" #include "../v_video.h" #include "../r_draw.h" +#include "../p_setup.h" //Hurdler: 25/04/2000: used for new colormap code in hardware mode //static UINT8 *gr_colormap = NULL; // by default it must be NULL ! (because colormap tables are not initialized) @@ -551,11 +552,13 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm static size_t gr_numtextures; static GLTexture_t *gr_textures; // for ALL Doom textures +static GLTexture_t *gr_textures2; void HWR_InitTextureCache(void) { gr_numtextures = 0; gr_textures = NULL; + gr_textures2 = NULL; } @@ -594,7 +597,10 @@ void HWR_FreeTextureCache(void) // texturecache info, we can free it if (gr_textures) free(gr_textures); + if (gr_textures2) + free(gr_textures2); gr_textures = NULL; + gr_textures2 = NULL; gr_numtextures = 0; } @@ -612,6 +618,9 @@ void HWR_PrepLevelCache(size_t pnumtextures) gr_textures = calloc(pnumtextures, sizeof (*gr_textures)); if (gr_textures == NULL) I_Error("3D can't alloc gr_textures"); + gr_textures2 = calloc(pnumtextures, sizeof (*gr_textures2)); + if (gr_textures2 == NULL) + I_Error("3D can't alloc gr_textures2"); } void HWR_SetPalette(RGBA_t *palette) @@ -642,7 +651,7 @@ GLTexture_t *HWR_GetTexture(INT32 tex) GLTexture_t *grtex; #ifdef PARANOIA if ((unsigned)tex >= gr_numtextures) - I_Error(" HWR_GetTexture: tex >= numtextures\n"); + I_Error("HWR_GetTexture: tex >= numtextures\n"); #endif grtex = &gr_textures[tex]; @@ -657,6 +666,35 @@ GLTexture_t *HWR_GetTexture(INT32 tex) return grtex; } +// Lactozilla +lumpnum_t gr_patchflat; + +static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) +{ + patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC); + + grMipmap->width = (UINT16)SHORT(patch->width); + grMipmap->height = (UINT16)SHORT(patch->height); + + R_FlatPatch(patch, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); + + Z_Free(patch); +} + +static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) +{ + // setup the texture info + grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; + grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; + grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; + grMipmap->grInfo.format = GR_TEXFMT_P_8; + grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; + + grMipmap->width = (UINT16)textures[texturenum]->width; + grMipmap->height = (UINT16)textures[texturenum]->height; + + R_FlatTexture(texturenum, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); +} static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { @@ -695,15 +733,20 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) pflatsize = 64; break; } - grMipmap->width = (UINT16)pflatsize; - grMipmap->height = (UINT16)pflatsize; - // the flat raw data needn't be converted with palettized textures - W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), - PU_HWRCACHE, &grMipmap->grInfo.data)); + if (R_CheckIfPatch(flatlumpnum)) + HWR_LoadPatchFlat(grMipmap, flatlumpnum); + else + { + grMipmap->width = (UINT16)pflatsize; + grMipmap->height = (UINT16)pflatsize; + + // the flat raw data needn't be converted with palettized textures + W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), + PU_HWRCACHE, &grMipmap->grInfo.data)); + } } - // Download a Doom 'flat' to the hardware cache and make it ready for use void HWR_GetFlat(lumpnum_t flatlumpnum) { @@ -718,6 +761,30 @@ void HWR_GetFlat(lumpnum_t flatlumpnum) // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); + + gr_patchflat = 0; + if (R_CheckIfPatch(flatlumpnum)) + gr_patchflat = flatlumpnum; +} + +void HWR_GetTextureFlat(INT32 texturenum) +{ + GLTexture_t *grtex; +#ifdef PARANOIA + if ((unsigned)texturenum >= gr_numtextures) + I_Error("HWR_GetTextureFlat: texturenum >= numtextures\n"); +#endif + if (texturenum == 0 || texturenum == -1) + return; + grtex = &gr_textures2[texturenum]; + + if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) + HWR_LoadTextureFlat(&grtex->mipmap, texturenum); + + HWD.pfnSetTexture(&grtex->mipmap); + + // The system-memory data can be purged now. + Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); } // diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index bdf219464..2085f7050 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -101,6 +101,7 @@ void HWR_FreeTextureCache(void); void HWR_FreeExtraSubsectors(void); void HWR_GetFlat(lumpnum_t flatlumpnum); +void HWR_GetTextureFlat(INT32 texturenum); GLTexture_t *HWR_GetTexture(INT32 tex); void HWR_GetPatch(GLPatch_t *gpatch); void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap); @@ -114,6 +115,8 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum); // -------- // hw_draw.c // -------- +extern lumpnum_t gr_patchflat; + extern float gr_patch_scalex; extern float gr_patch_scaley; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 7e0b369eb..7d0e7e490 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -70,9 +70,9 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); #endif #ifdef SORTING -void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, +void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, +void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); #else static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight, @@ -522,7 +522,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c // HWR_RenderPlane : Render a floor or ceiling convex polygon // -----------------+ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, - FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) + FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) { polyvertex_t * pv; float height; //constant y for all points on the convex flat polygon @@ -530,8 +530,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is INT32 nrPlaneVerts; //verts original define of convex flat polygon INT32 i; float flatxref,flatyref; - float fflatsize; - INT32 flatflag; + float fflatwidth, fflatheight; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; @@ -540,6 +539,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is #ifdef ESLOPE pslope_t *slope = NULL; #endif + patch_t *patch; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; @@ -599,38 +599,44 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is switch (len) { case 4194304: // 2048x2048 lump - fflatsize = 2048.0f; - flatflag = 2047; + fflatwidth = fflatheight = 2048.0f; break; case 1048576: // 1024x1024 lump - fflatsize = 1024.0f; - flatflag = 1023; + fflatwidth = fflatheight = 1024.0f; break; case 262144:// 512x512 lump - fflatsize = 512.0f; - flatflag = 511; + fflatwidth = fflatheight = 512.0f; break; case 65536: // 256x256 lump - fflatsize = 256.0f; - flatflag = 255; + fflatwidth = fflatheight = 256.0f; break; case 16384: // 128x128 lump - fflatsize = 128.0f; - flatflag = 127; + fflatwidth = fflatheight = 128.0f; break; case 1024: // 32x32 lump - fflatsize = 32.0f; - flatflag = 31; + fflatwidth = fflatheight = 32.0f; break; default: // 64x64 lump - fflatsize = 64.0f; - flatflag = 63; + fflatwidth = fflatheight = 64.0f; break; } + if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? + { + patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); + fflatwidth = patch->width; + fflatheight = patch->height; + } + + if (texturenum != 0 && texturenum != -1) + { + fflatwidth = textures[texturenum]->width; + fflatheight = textures[texturenum]->height; + } + // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatsize); - flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatsize); + flatxref = (float)((FLOAT_TO_FIXED(pv->x) % llrint(fflatwidth)) / fflatwidth); + flatyref = (float)((FLOAT_TO_FIXED(pv->y) % llrint(fflatheight)) / fflatheight); // transform v3d = planeVerts; @@ -639,14 +645,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT; } } @@ -654,14 +660,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight; angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight; angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT; } } @@ -686,8 +692,8 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) { // Hurdler: add scrolling texture on floor/ceiling - v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx); - v3d->tow = (float)(flatyref - (pv->y / fflatsize) + scrolly); + v3d->sow = (float)((pv->x / fflatwidth) - flatxref + scrollx); + v3d->tow = (float)(flatyref - (pv->y / fflatheight) + scrolly); //v3d->sow = (float)(pv->x / fflatsize); //v3d->tow = (float)(pv->y / fflatsize); @@ -3145,21 +3151,21 @@ static inline void HWR_AddPolyObjectSegs(void) #ifdef POLYOBJECTS_PLANES static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, - FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, + FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) { float height; //constant y for all points on the convex flat polygon FOutVector *v3d; INT32 i; float flatxref,flatyref; - float fflatsize; - INT32 flatflag; + float fflatwidth, fflatheight; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; FSurfaceInfo Surf; fixed_t tempxsow, tempytow; size_t nrPlaneVerts; + patch_t *patch; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; @@ -3190,38 +3196,44 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, switch (len) { case 4194304: // 2048x2048 lump - fflatsize = 2048.0f; - flatflag = 2047; + fflatwidth = fflatheight = 2048.0f; break; case 1048576: // 1024x1024 lump - fflatsize = 1024.0f; - flatflag = 1023; + fflatwidth = fflatheight = 1024.0f; break; case 262144:// 512x512 lump - fflatsize = 512.0f; - flatflag = 511; + fflatwidth = fflatheight = 512.0f; break; case 65536: // 256x256 lump - fflatsize = 256.0f; - flatflag = 255; + fflatwidth = fflatheight = 256.0f; break; case 16384: // 128x128 lump - fflatsize = 128.0f; - flatflag = 127; + fflatwidth = fflatheight = 128.0f; break; case 1024: // 32x32 lump - fflatsize = 32.0f; - flatflag = 31; + fflatwidth = fflatheight = 32.0f; break; default: // 64x64 lump - fflatsize = 64.0f; - flatflag = 63; + fflatwidth = fflatheight = 64.0f; break; } + if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? + { + patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); + fflatwidth = patch->width; + fflatheight = patch->height; + } + + if (texturenum != 0 && texturenum != -1) + { + fflatwidth = textures[texturenum]->width; + fflatheight = textures[texturenum]->height; + } + // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].x) & (~flatflag)) / fflatsize); - flatyref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].y) & (~flatflag)) / fflatsize); + flatxref = (float)((polysector->origVerts[0].x % llrint(fflatwidth)) / fflatwidth); + flatyref = (float)((polysector->origVerts[0].y % llrint(fflatheight)) / fflatheight); // transform v3d = planeVerts; @@ -3230,14 +3242,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT; } } @@ -3245,14 +3257,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight; angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight; angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT; } } @@ -3276,8 +3288,8 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++) { // Hurdler: add scrolling texture on floor/ceiling - v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatsize) - flatxref + scrollx); // Go from the polysector's original vertex locations - v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatsize) + scrolly); // Means the flat is offset based on the original vertex locations + v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx); // Go from the polysector's original vertex locations + v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly); // Means the flat is offset based on the original vertex locations // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle @@ -3336,14 +3348,15 @@ static void HWR_AddPolyObjectPlanes(void) { FSurfaceInfo Surf; FBITFIELD blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); - HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, po_ptrs[i], false, polyobjsector->floorheight, + HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], false, polyobjsector->floorheight, polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL); } else { HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum); + HWR_GetTextureFlat(levelflats[polyobjsector->floorpic].texturenum); HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, - polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, + polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, polyobjsector, 255, NULL); } } @@ -3358,14 +3371,15 @@ static void HWR_AddPolyObjectPlanes(void) FBITFIELD blendmode; memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); - HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, po_ptrs[i], true, polyobjsector->ceilingheight, + HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, levelflats[polyobjsector->ceilingpic].texturenum, po_ptrs[i], true, polyobjsector->ceilingheight, polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL); } else { HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum); + HWR_GetTextureFlat(levelflats[polyobjsector->ceilingpic].texturenum); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, - polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, + polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, polyobjsector, 255, NULL); } } @@ -3517,11 +3531,12 @@ static void HWR_Subsector(size_t num) if (sub->validcount != validcount) { HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum); + HWR_GetTextureFlat(levelflats[gr_frontsector->floorpic].texturenum); HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false, // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap); + PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, levelflats[gr_frontsector->floorpic].texturenum, NULL, 255, false, floorcolormap); } } else @@ -3539,11 +3554,12 @@ static void HWR_Subsector(size_t num) if (sub->validcount != validcount) { HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum); + HWR_GetTextureFlat(levelflats[gr_frontsector->ceilingpic].texturenum); HWR_RenderPlane(NULL, &extrasubsectors[num], true, // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap); + PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum, levelflats[gr_frontsector->ceilingpic].texturenum, NULL, 255, false, ceilingcolormap); } } else @@ -3602,7 +3618,7 @@ static void HWR_Subsector(size_t num) else alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - HWR_AddTransparentFloor(0, + HWR_AddTransparentFloor(0, 0, &extrasubsectors[num], false, *rover->bottomheight, @@ -3621,6 +3637,7 @@ static void HWR_Subsector(size_t num) rover->alpha-1, rover->master->frontsector); #else HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum, + levelflats[*rover->bottompic].texturenum, &extrasubsectors[num], false, *rover->bottomheight, @@ -3632,8 +3649,9 @@ static void HWR_Subsector(size_t num) else { HWR_GetFlat(levelflats[*rover->bottompic].lumpnum); + HWR_GetTextureFlat(levelflats[*rover->bottompic].texturenum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, + HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, levelflats[*rover->bottompic].texturenum, rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); } } @@ -3665,7 +3683,7 @@ static void HWR_Subsector(size_t num) else alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - HWR_AddTransparentFloor(0, + HWR_AddTransparentFloor(0, 0, &extrasubsectors[num], true, *rover->topheight, @@ -3684,6 +3702,7 @@ static void HWR_Subsector(size_t num) rover->alpha-1, rover->master->frontsector); #else HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum, + levelflats[*rover->bottompic].texturenum, &extrasubsectors[num], true, *rover->topheight, @@ -3696,8 +3715,9 @@ static void HWR_Subsector(size_t num) else { HWR_GetFlat(levelflats[*rover->toppic].lumpnum); + HWR_GetTextureFlat(levelflats[*rover->toppic].texturenum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, + HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, levelflats[*rover->toppic].texturenum, rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); } } @@ -5021,6 +5041,7 @@ typedef struct fixed_t fixedheight; INT32 lightlevel; lumpnum_t lumpnum; + INT32 texturenum; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -5039,6 +5060,7 @@ typedef struct fixed_t fixedheight; INT32 lightlevel; lumpnum_t lumpnum; + INT32 texturenum; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -5071,7 +5093,7 @@ static INT32 drawcount = 0; #define MAX_TRANSPARENTFLOOR 512 // This will likely turn into a copy of HWR_Add3DWater and replace it. -void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, +void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) { static size_t allocedplanes = 0; @@ -5090,6 +5112,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean planeinfo[numplanes].fixedheight = fixedheight; planeinfo[numplanes].lightlevel = lightlevel; planeinfo[numplanes].lumpnum = lumpnum; + planeinfo[numplanes].texturenum = texturenum; planeinfo[numplanes].xsub = xsub; planeinfo[numplanes].alpha = alpha; planeinfo[numplanes].FOFSector = FOFSector; @@ -5103,7 +5126,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean // Adding this for now until I can create extrasubsector info for polyobjects // When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, +void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) { static size_t allocedpolyplanes = 0; @@ -5122,6 +5145,7 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, polyplaneinfo[numpolyplanes].fixedheight = fixedheight; polyplaneinfo[numpolyplanes].lightlevel = lightlevel; polyplaneinfo[numpolyplanes].lumpnum = lumpnum; + polyplaneinfo[numpolyplanes].texturenum = texturenum; polyplaneinfo[numpolyplanes].polysector = polysector; polyplaneinfo[numpolyplanes].alpha = alpha; polyplaneinfo[numpolyplanes].FOFSector = FOFSector; @@ -5283,9 +5307,12 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) + { HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum); + HWR_GetTextureFlat(sortnode[sortindex[i]].plane->texturenum); + } HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, - sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); + sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->texturenum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); } else if (sortnode[sortindex[i]].polyplane) { @@ -5293,9 +5320,12 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture)) + { HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum); + HWR_GetTextureFlat(sortnode[sortindex[i]].polyplane->texturenum); + } HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, - sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); + sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->texturenum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); } else if (sortnode[sortindex[i]].wall) { diff --git a/src/p_setup.c b/src/p_setup.c index 5e1355981..1061dbd0c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -564,6 +564,8 @@ 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); #ifndef ZDEBUG CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); @@ -608,6 +610,8 @@ INT32 P_AddLevelFlatRuntime(const char *flatname) // store the flat lump number levelflat->lumpnum = R_GetFlatNumForName(flatname); + // Lactozilla + levelflat->texturenum = R_CheckTextureNumForName(flatname); #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 41c2bf133..6f54bceae 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -42,6 +42,17 @@ typedef struct INT32 animseq; // start pos. in the anim sequence INT32 numpics; INT32 speed; + + // Lactozilla + UINT8 *flatpatch; + UINT16 width, height; + fixed_t topoffset, leftoffset; + size_t texturenum; + +#ifdef ESLOPE + UINT8 *resizedflat; + UINT16 resizedwidth, resizedheight; +#endif } levelflat_t; extern size_t numlevelflats; diff --git a/src/p_spec.c b/src/p_spec.c index 50b8aec9d..60d784324 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -322,8 +322,8 @@ void P_InitPicAnims(void) if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR) continue; - lastanim->picnum = R_FlatNumForName(animdefs[i].endname); - lastanim->basepic = R_FlatNumForName(animdefs[i].startname); + lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname); + lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname); } lastanim->istexture = animdefs[i].istexture; diff --git a/src/r_data.c b/src/r_data.c index a21ba49ae..496a0f944 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -101,9 +101,7 @@ texture_t **textures = NULL; static UINT32 **texturecolumnofs; // column offset lookup table for each texture static UINT8 **texturecache; // graphics data for each generated full-size texture -// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask -INT32 *texturewidthmask; - +INT32 *texturewidth; fixed_t *textureheight; // needed for texture pegging INT32 *texturetranslation; @@ -335,10 +333,14 @@ void R_CheckTextureCache(INT32 tex) UINT8 *R_GetColumn(fixed_t tex, INT32 col) { UINT8 *data; + INT32 width = texturewidth[tex]; + + if (width & (width - 1)) + col = (UINT32)col % width; + else + col &= (width - 1); - col &= texturewidthmask[tex]; data = texturecache[tex]; - if (!data) data = R_GenerateTexture(tex); @@ -376,7 +378,7 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index); #define TX_END "TX_END" void R_LoadTextures(void) { - INT32 i, k, w; + INT32 i, w; UINT16 j; UINT16 texstart, texend, texturesLumpPos; patch_t *patchlump; @@ -443,9 +445,9 @@ void R_LoadTextures(void) texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *))); // Allocate texture referencing cache. texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); - // Allocate texture width mask table. - texturewidthmask = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); - // Allocate texture height mask table. + // Allocate texture width table. + texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); + // Allocate texture height table. textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); // Create translation table for global animation. texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); @@ -513,11 +515,7 @@ void R_LoadTextures(void) Z_Unlock(patchlump); - k = 1; - while (k << 1 <= texture->width) - k <<= 1; - - texturewidthmask[i] = k - 1; + texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; } } @@ -905,7 +903,7 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) newTexture = R_ParseTexture(true); // Store the new texture textures[*texindex] = newTexture; - texturewidthmask[*texindex] = newTexture->width - 1; + texturewidth[*texindex] = newTexture->width; textureheight[*texindex] = newTexture->height << FRACBITS; // Increment i back in R_LoadTextures() (*texindex)++; @@ -1017,6 +1015,41 @@ lumpnum_t R_GetFlatNumForName(const char *name) lump = LUMPERROR; } + // Lactozilla + if (lump == LUMPERROR) + { + // Scan wad files backwards so patched flats take preference. + for (i = numwadfiles - 1; i >= 0; i--) + { + switch (wadfiles[i]->type) + { + case RET_WAD: + if ((start = W_CheckNumForNamePwad("TX_START", (UINT16)i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX) + continue; + break; + case RET_PK3: + if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX) + continue; + break; + default: + continue; + } + + // Now find lump with specified name in that range. + lump = W_CheckNumForNamePwad(name, (UINT16)i, start); + if (lump < end) + { + lump += (i<<16); // found it, in our constraints + break; + } + lump = LUMPERROR; + } + } + if (lump == LUMPERROR) { if (strcmp(name, SKYFLATNAME)) @@ -1603,3 +1636,144 @@ void R_PrecacheLevel(void) "texturememory: %s k\n" "spritememory: %s k\n", sizeu1(flatmemory>>10), sizeu2(texturememory>>10), sizeu3(spritememory>>10)); } + +// https://github.com/coelckers/prboom-plus/blob/master/prboom2/src/r_patch.c#L350 +boolean R_CheckIfPatch(lumpnum_t lump) +{ + size_t size; + INT16 width, height; + patch_t *patch; + boolean result; + + size = W_LumpLength(lump); + + // minimum length of a valid Doom patch + if (size < 13) + return false; + + patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC); + + width = SHORT(patch->width); + height = SHORT(patch->height); + + result = (height > 0 && height <= 16384 && width > 0 && width <= 16384 && width < size / 4); + + if (result) + { + // The dimensions seem like they might be valid for a patch, so + // check the column directory for extra security. All columns + // must begin after the column directory, and none of them must + // point past the end of the patch. + INT16 x; + + for (x = 0; x < width; x++) + { + UINT32 ofs = LONG(patch->columnofs[x]); + + // Need one byte for an empty column (but there's patches that don't know that!) + if (ofs < (UINT32)width * 4 + 8 || ofs >= (UINT32)size) + { + result = false; + break; + + } + } + } + + Z_Free(patch); + return result; +} + +// Lactozilla +void R_FlatPatch(patch_t *patch, UINT8 *flat) +{ + fixed_t col, ofs; + column_t *column; + UINT8 *desttop, *dest, *deststop; + UINT8 *source; + + desttop = flat; + deststop = desttop + (patch->width * patch->height); + + for (col = 0; col < SHORT(patch->width); col++, desttop++) + { + INT32 topdelta, prevdelta = -1; + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[col])); + + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + + dest = desttop + (topdelta * patch->width); + source = (UINT8 *)(column) + 3; + for (ofs = 0; dest < deststop && ofs < column->length; ofs++) + { + if (source[ofs] != TRANSPARENTPIXEL) + *dest = source[ofs]; + dest += patch->width; + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } +} + +void R_FlatTexture(size_t tex, UINT8 *flat) +{ + texture_t *texture = textures[tex]; + + fixed_t col, ofs; + column_t *column; + UINT8 *desttop, *dest, *deststop; + UINT8 *source; + + desttop = flat; + deststop = desttop + (texture->width * texture->height); + + for (col = 0; col < SHORT(texture->width); col++, desttop++) + { + INT32 topdelta, prevdelta = -1; + column = (column_t *)R_GetColumn(tex, col); + if (!texture->holes) + { + dest = desttop; + source = (UINT8 *)(column); + for (ofs = 0; dest < deststop && ofs < texture->height; ofs++) + { + if (source[ofs] != TRANSPARENTPIXEL) + *dest = source[ofs]; + dest += texture->width; + } + } + else + { + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + + dest = desttop + (topdelta * texture->width); + source = (UINT8 *)(column) + 3; + for (ofs = 0; dest < deststop && ofs < column->length; ofs++) + { + if (source[ofs] != TRANSPARENTPIXEL) + *dest = source[ofs]; + dest += texture->width; + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } + } +} + +void R_CropFlat(UINT8 *origflat, UINT8 *cropflat, UINT16 origwidth, UINT16 origheight, UINT16 cropwidth, UINT16 cropheight) +{ + UINT16 x, y; + for (y = 0; y < cropheight; y++) + for (x = 0; x < cropwidth; x++) + cropflat[(y * cropwidth) + x] = origflat[(y * origwidth) + x]; +} diff --git a/src/r_data.h b/src/r_data.h index 5de51ccd4..a1e7cd127 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -51,9 +51,7 @@ typedef struct // all loaded and prepared textures from the start of the game extern texture_t **textures; -// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask -extern INT32 *texturewidthmask; - +extern INT32 *texturewidth; extern fixed_t *textureheight; // needed for texture pegging extern INT16 color8to16[256]; // remap color index to highcolor @@ -81,7 +79,6 @@ void R_PrecacheLevel(void); // Floor/ceiling opaque texture tiles, // lookup by name. For animation? lumpnum_t R_GetFlatNumForName(const char *name); -#define R_FlatNumForName(x) R_GetFlatNumForName(x) // Called by P_Ticker for switches and animations, // returns the texture number for the texture name. @@ -95,6 +92,13 @@ INT32 R_ColormapNumForName(char *name); INT32 R_CreateColormap(char *p1, char *p2, char *p3); 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 *origflat, UINT8 *cropflat, UINT16 origwidth, UINT16 origheight, UINT16 cropwidth, UINT16 cropheight); + extern INT32 numtextures; #endif diff --git a/src/r_draw.c b/src/r_draw.c index bbc9a79b0..babcbef08 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -99,6 +99,8 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight; INT32 ds_y, ds_x1, ds_x2; lighttable_t *ds_colormap; fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; +UINT16 ds_flatwidth, ds_flatheight; +boolean ds_powersoftwo; UINT8 *ds_source; // start of a 64*64 tile image UINT8 *ds_transmap; // one of the translucency tables diff --git a/src/r_draw.h b/src/r_draw.h index 12f556b7a..e82f60839 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -57,7 +57,9 @@ extern INT32 dc_texheight; extern INT32 ds_y, ds_x1, ds_x2; extern lighttable_t *ds_colormap; extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; -extern UINT8 *ds_source; // start of a 64*64 tile image +extern UINT16 ds_flatwidth, ds_flatheight; +extern boolean ds_powersoftwo; +extern UINT8 *ds_source; extern UINT8 *ds_transmap; #ifdef ESLOPE @@ -125,6 +127,8 @@ void R_FillBackScreen(void); void R_DrawViewBorder(void); #endif +#define TRANSPARENTPIXEL 247 + // ----------------- // 8bpp DRAWING CODE // ----------------- @@ -166,6 +170,13 @@ void R_DrawFogSpan_8(void); void R_DrawFogColumn_8(void); void R_DrawColumnShadowed_8(void); +#ifndef NOWATER +void R_DrawTranslucentWaterSpan_8(void); + +extern INT32 ds_bgofs; +extern INT32 ds_waterofs; +#endif + // ------------------ // 16bpp DRAWING CODE // ------------------ diff --git a/src/r_draw8.c b/src/r_draw8.c index 886b72dae..f829707d3 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -105,8 +105,6 @@ void R_DrawColumn_8(void) } } -#define TRANSPARENTPIXEL 247 - void R_Draw2sMultiPatchColumn_8(void) { INT32 count; @@ -543,80 +541,60 @@ void R_DrawTranslatedColumn_8(void) */ void R_DrawSpan_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; + UINT32 flatsize = ds_flatwidth * ds_flatheight; + size_t count = (ds_x2 - ds_x1 + 1); - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - if (dest+8 > deststop) + if (dest > deststop) return; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - dest[1] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - dest[2] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[3] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + *dest++ = colormap[source[((y * ds_flatwidth) + x) % flatsize]]; + xposition += xstep; + yposition += ystep; + } } - while (count-- && dest <= deststop) + else { - *dest++ = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + *dest++ = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + } } } @@ -1065,117 +1043,64 @@ void R_DrawTiltedSplat_8(void) */ void R_DrawSplat_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; + UINT32 flatsize = ds_flatwidth * ds_flatheight; + size_t count = (ds_x2 - ds_x1 + 1); UINT32 val; - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - // - // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[0] = colormap[val]; - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[1] = colormap[val]; - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[2] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[3] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[4] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[5] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[6] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[7] = colormap[val]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + val = source[((y * ds_flatwidth) + x) % flatsize]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest++; + xposition += xstep; + yposition += ystep; + } } - while (count--) + else { - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; - - dest++; - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest++; + xposition += xstep; + yposition += ystep; + } } } @@ -1184,97 +1109,64 @@ void R_DrawSplat_8 (void) */ void R_DrawTranslucentSplat_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; - UINT8 val; + UINT32 flatsize = ds_flatwidth * ds_flatheight; + size_t count = (ds_x2 - ds_x1 + 1); + UINT32 val; - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + val = source[((y * ds_flatwidth) + x) % flatsize]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } - while (count--) + else { - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - *dest = *(ds_transmap + (colormap[val] << 8) + *dest); - - dest++; - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } } @@ -1283,80 +1175,125 @@ void R_DrawTranslucentSplat_8 (void) */ void R_DrawTranslucentSpan_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; + UINT32 flatsize = ds_flatwidth * ds_flatheight; + size_t count = (ds_x2 - ds_x1 + 1); + UINT32 val; - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - dest[1] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - dest[2] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - dest[3] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - dest[4] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - dest[5] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - dest[6] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - dest[7] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + val = ((y * ds_flatwidth) + x) % flatsize; + *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } - while (count--) + else { - *dest = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + *dest); - dest++; - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } } +#ifndef NOWATER +void R_DrawTranslucentWaterSpan_8(void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + UINT8 *dsrc; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + + UINT32 flatsize = ds_flatwidth * ds_flatheight; + size_t count = (ds_x2 - ds_x1 + 1); + + xposition = ds_xfrac; yposition = (ds_yfrac + ds_waterofs); + xstep = ds_xstep; ystep = ds_ystep; + + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; + + if (!ds_powersoftwo) + { + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + *dest++ = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x) % flatsize] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + } + } + else + { + while (count-- && dest <= deststop) + { + *dest++ = colormap[*(ds_transmap + (source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + } + } +} +#endif + /** \brief The R_DrawFogSpan_8 function Draws the actual span with fogging. */ diff --git a/src/r_plane.c b/src/r_plane.c index 5cb53a530..39f1d220a 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -173,91 +173,13 @@ void R_PortalRestoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor // viewheight #ifndef NOWATER -static INT32 bgofs; +INT32 ds_bgofs; +INT32 ds_waterofs; + static INT32 wtofs=0; -static INT32 waterofs; static boolean itswater; #endif -#ifndef NOWATER -static void R_DrawTranslucentWaterSpan_8(void) -{ - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; - - UINT8 *source; - UINT8 *colormap; - UINT8 *dest; - UINT8 *dsrc; - - size_t count; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = (ds_yfrac + waterofs) << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; - - source = ds_source; - colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; - dsrc = screens[1] + (ds_y+bgofs)*vid.width + ds_x1; - count = ds_x2 - ds_x1 + 1; - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[1] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[2] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[3] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count--) - { - *dest++ = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - } -} -#endif - void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { angle_t angle, planecos, planesin; @@ -304,17 +226,17 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { const INT32 yay = (wtofs + (distance>>9) ) & 8191; // ripples da water texture - bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; + ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; angle = (currentplane->viewangle + currentplane->plangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; angle = (angle + 2048) & 8191; // 90 degrees - ds_xfrac += FixedMul(FINECOSINE(angle), (bgofs<=viewheight) - bgofs = viewheight-y-1; - if (y+bgofs<0) - bgofs = -y; + if (y+ds_bgofs>=viewheight) + ds_bgofs = viewheight-y-1; + if (y+ds_bgofs<0) + ds_bgofs = -y; } #endif @@ -726,11 +648,142 @@ void R_DrawPlanes(void) } } #ifndef NOWATER - waterofs = (leveltime & 1)*16384; + ds_waterofs = (leveltime & 1)*16384; wtofs = leveltime * 140; #endif } +// Lactozilla +static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture) +{ + patch_t *patch = NULL; + + if (levelflat->flatpatch == NULL) + { +#ifdef ESLOPE + INT32 resizewidth, resizeheight, newresize; +#endif // ESLOPE + + if (!leveltexture) + { + patch = (patch_t *)ds_source; + levelflat->width = ds_flatwidth = patch->width; + levelflat->height = ds_flatheight = patch->height; + + 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; + } + 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; + // Then scale down to fit the actual flat dimensions + while (resizewidth > levelflat->width) + resizewidth >>= 1; + while (resizeheight > levelflat->height) + resizeheight >>= 1; + + 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, newresize, newresize); +#endif // ESLOPE + } + else + { + ds_source = levelflat->flatpatch; + ds_flatwidth = levelflat->width; + ds_flatheight = levelflat->height; + + xoffs += levelflat->leftoffset; + yoffs += levelflat->topoffset; + } + +#ifdef ESLOPE + if (currentplane->slope) + { + ds_source = levelflat->resizedflat; + ds_flatwidth = levelflat->resizedwidth; + ds_flatheight = levelflat->resizedheight; + + // uuuuuuuhhhhhhhh....................... + switch (ds_flatwidth * ds_flatheight) + { + 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; + } + } +#endif // ESLOPE +} + void R_DrawSinglePlane(visplane_t *pl) { INT32 light = 0; @@ -738,6 +791,7 @@ void R_DrawSinglePlane(visplane_t *pl) INT32 stop, angle; size_t size; ffloor_t *rover; + levelflat_t *levelflat; if (!(pl->minx <= pl->maxx)) return; @@ -878,64 +932,78 @@ void R_DrawSinglePlane(visplane_t *pl) viewangle = pl->viewangle+pl->plangle; } - currentplane = pl; - - ds_source = (UINT8 *) - W_CacheLumpNum(levelflats[pl->picnum].lumpnum, - PU_STATIC); // Stay here until Z_ChangeTag - - size = W_LumpLength(levelflats[pl->picnum].lumpnum); - - switch (size) - { - 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; - } - xoffs = pl->xoffs; yoffs = pl->yoffs; planeheight = abs(pl->height - pl->viewz); + currentplane = pl; + levelflat = &levelflats[pl->picnum]; + + if (levelflat->texturenum != 0 && levelflat->texturenum != -1) + R_GetPatchFlat(levelflat, true); + 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; + } + } + + if (R_CheckIfPatch(levelflat->lumpnum)) + R_GetPatchFlat(levelflat, false); + ds_powersoftwo = (!((ds_flatwidth & (ds_flatwidth - 1)) || (ds_flatheight & (ds_flatheight - 1)))); + if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; diff --git a/src/screen.c b/src/screen.c index af6aed03c..893fb851f 100644 --- a/src/screen.c +++ b/src/screen.c @@ -135,7 +135,7 @@ void SCR_SetMode(void) //fuzzcolfunc = R_DrawTranslucentColumn_8_ASM; walldrawerfunc = R_DrawWallColumn_8_MMX; twosmultipatchfunc = R_Draw2sMultiPatchColumn_8_MMX; - spanfunc = basespanfunc = R_DrawSpan_8_MMX; + //spanfunc = basespanfunc = R_DrawSpan_8_MMX; } else { From 35d6da159d91428060bf1a0c47242d9a53aa17d9 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 21 May 2019 09:50:39 -0300 Subject: [PATCH 002/133] HOLD UP --- src/hardware/hw_cache.c | 2 -- src/r_data.c | 1 - 2 files changed, 3 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 4ae7a43b9..84ad4c55b 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -677,8 +677,6 @@ static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) grMipmap->height = (UINT16)SHORT(patch->height); R_FlatPatch(patch, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); - - Z_Free(patch); } static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) diff --git a/src/r_data.c b/src/r_data.c index 496a0f944..8ceb59dd4 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1680,7 +1680,6 @@ boolean R_CheckIfPatch(lumpnum_t lump) } } - Z_Free(patch); return result; } From 869f1e4e8d18a6c02d4c9df095f0ff99e268e210 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 21 May 2019 11:03:53 -0300 Subject: [PATCH 003/133] Fix warnings --- src/hardware/hw_main.c | 5 +++-- src/p_setup.h | 2 +- src/r_data.c | 37 +++++++++++++++++++++++++++++++------ src/r_data.h | 5 ++++- src/r_plane.c | 40 ++++++++++++++++++++++++++++++++++------ 5 files changed, 73 insertions(+), 16 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 7d0e7e490..793050aa2 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -580,9 +580,10 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is if (nrPlaneVerts < 3) //not even a triangle ? return; - if (nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size + // This check is so inconsistent between functions, it hurts. + if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size { - CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX); + CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, INT16_MAX); return; } diff --git a/src/p_setup.h b/src/p_setup.h index 6f54bceae..eda6066d3 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -47,7 +47,7 @@ typedef struct UINT8 *flatpatch; UINT16 width, height; fixed_t topoffset, leftoffset; - size_t texturenum; + INT32 texturenum; #ifdef ESLOPE UINT8 *resizedflat; diff --git a/src/r_data.c b/src/r_data.c index 8ceb59dd4..00d8de629 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1656,7 +1656,7 @@ boolean R_CheckIfPatch(lumpnum_t lump) width = SHORT(patch->width); height = SHORT(patch->height); - result = (height > 0 && height <= 16384 && width > 0 && width <= 16384 && width < size / 4); + result = (height > 0 && height <= 16384 && width > 0 && width <= 16384 && width < (INT16)(size / 4)); if (result) { @@ -1769,10 +1769,35 @@ void R_FlatTexture(size_t tex, UINT8 *flat) } } -void R_CropFlat(UINT8 *origflat, UINT8 *cropflat, UINT16 origwidth, UINT16 origheight, UINT16 cropwidth, UINT16 cropheight) +void R_CropFlat(UINT8 *srcflat, UINT8 *destflat, + UINT16 srcwidth, UINT16 srcheight, + UINT16 resizewidth, UINT16 resizeheight, + UINT16 destwidth, UINT16 destheight) { - UINT16 x, y; - for (y = 0; y < cropheight; y++) - for (x = 0; x < cropwidth; x++) - cropflat[(y * cropwidth) + x] = origflat[(y * origwidth) + x]; + UINT16 y; + UINT16 position = 0; + for (y = 0; y < destheight; y++) + { + if (position > (srcwidth * srcheight)) + break; + if (srcwidth != resizewidth) + { + if (resizewidth > srcwidth) + { + UINT8 *pos2 = srcflat+position; + UINT8 lastpixel = *(pos2-1); + M_Memcpy(destflat, srcflat+position, destwidth); + memset(pos2, lastpixel, resizewidth-srcwidth); + } + else + M_Memcpy(destflat, srcflat+position, resizewidth); + } + else + M_Memcpy(destflat, srcflat+position, destwidth); + destflat += destwidth; + position += srcwidth; + } + + while (y++ < min(resizeheight, srcheight)) + memset(destflat + (y * destwidth), *(destflat - 1), destwidth); } diff --git a/src/r_data.h b/src/r_data.h index a1e7cd127..8cb41cd2f 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -97,7 +97,10 @@ 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 *origflat, UINT8 *cropflat, UINT16 origwidth, UINT16 origheight, UINT16 cropwidth, UINT16 cropheight); +void R_CropFlat(UINT8 *srcflat, UINT8 *destflat, + UINT16 srcwidth, UINT16 srcheight, + UINT16 resizewidth, UINT16 resizeheight, + UINT16 destwidth, UINT16 destheight); extern INT32 numtextures; diff --git a/src/r_plane.c b/src/r_plane.c index 39f1d220a..91b4f5f2c 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -662,6 +662,7 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture) { #ifdef ESLOPE INT32 resizewidth, resizeheight, newresize; + INT32 checkresizewidth, checkresizeheight; #endif // ESLOPE if (!leveltexture) @@ -700,21 +701,48 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture) resizewidth <<= 1; while (resizeheight < levelflat->height) resizeheight <<= 1; + // Scale down to fit in 2048x2048 if (resizewidth > 2048) resizewidth = 2048; if (resizeheight > 2048) resizeheight = 2048; - // Then scale down to fit the actual flat dimensions - while (resizewidth > levelflat->width) - resizewidth >>= 1; - while (resizeheight > levelflat->height) - resizeheight >>= 1; + + // A single pixel difference is negligible. + checkresizewidth = levelflat->width - 1; + if (checkresizewidth & (checkresizewidth - 1)) + { + checkresizewidth += 2; + if (checkresizewidth & (checkresizewidth - 1)) + { + while (resizewidth > levelflat->width) + resizewidth >>= 1; + } + else + resizewidth = checkresizewidth; + } + else + resizewidth = checkresizewidth; + + checkresizeheight = levelflat->height - 1; + if (checkresizeheight & (checkresizeheight - 1)) + { + checkresizeheight += 2; + if (checkresizeheight & (checkresizeheight - 1)) + { + while (resizeheight > levelflat->height) + resizeheight >>= 1; + } + 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, newresize, newresize); + R_CropFlat(levelflat->flatpatch, levelflat->resizedflat, levelflat->width, levelflat->height, min(resizewidth, newresize), min(resizeheight, newresize), newresize, newresize); #endif // ESLOPE } else From dbb1575a6da394d95dcaaae108db991c8d2b8619 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 21 May 2019 15:24:26 -0300 Subject: [PATCH 004/133] Animations, better flat management. --- src/p_setup.c | 5 +- src/p_setup.h | 10 +- src/p_spec.c | 26 ++-- src/r_data.c | 8 +- src/r_data.h | 13 +- src/r_plane.c | 336 ++++++++++++++++++++++++++------------------------ src/r_plane.h | 2 + 7 files changed, 224 insertions(+), 176 deletions(-) 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 { From 36036b6cfdeeacc1ded8d869dfb5dc2777e95e27 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 26 May 2019 12:02:43 +0200 Subject: [PATCH 005/133] Permit textures to use the "TEXTURE" tag in addition to "WALLTEXTURE". It's pointless to make any distinctions anymore IMO, given flats can load them just fine now. --- src/r_data.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 4157a8850..738fc0727 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -850,7 +850,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) texturesToken = M_GetToken(texturesText); while (texturesToken != NULL) { - if (stricmp(texturesToken, "WALLTEXTURE")==0) + if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0) { numTexturesInLump++; Z_Free(texturesToken); @@ -858,7 +858,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) } else { - I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); + I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken); } texturesToken = M_GetToken(NULL); } @@ -899,7 +899,7 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) texturesToken = M_GetToken(texturesText); while (texturesToken != NULL) { - if (stricmp(texturesToken, "WALLTEXTURE")==0) + if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0) { Z_Free(texturesToken); // Get the new texture @@ -913,7 +913,7 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) } else { - I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); + I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken); } texturesToken = M_GetToken(NULL); } From 93f60267c1bd3842cdc961977b22163761f70c26 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sun, 26 May 2019 16:22:33 -0300 Subject: [PATCH 006/133] Minor fixes --- src/hardware/hw_cache.c | 30 ++--- src/hardware/hw_main.c | 38 ++++-- src/r_data.c | 10 +- src/r_draw8.c | 277 ++++++++++++++++++++++++++++++++++++++-- src/r_plane.c | 10 +- 5 files changed, 316 insertions(+), 49 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 84ad4c55b..504ded35b 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -679,21 +679,6 @@ static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) R_FlatPatch(patch, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); } -static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) -{ - // setup the texture info - grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; - grMipmap->grInfo.format = GR_TEXFMT_P_8; - grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; - - grMipmap->width = (UINT16)textures[texturenum]->width; - grMipmap->height = (UINT16)textures[texturenum]->height; - - R_FlatTexture(texturenum, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); -} - static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { size_t size, pflatsize; @@ -765,6 +750,21 @@ void HWR_GetFlat(lumpnum_t flatlumpnum) gr_patchflat = flatlumpnum; } +static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) +{ + // setup the texture info + grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; + grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; + grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; + grMipmap->grInfo.format = GR_TEXFMT_P_8; + grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; + + grMipmap->width = (UINT16)textures[texturenum]->width; + grMipmap->height = (UINT16)textures[texturenum]->height; + + R_FlatTexture(texturenum, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); +} + void HWR_GetTextureFlat(INT32 texturenum) { GLTexture_t *grtex; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 793050aa2..02e731164 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -531,6 +531,8 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is INT32 i; float flatxref,flatyref; float fflatwidth, fflatheight; + INT32 flatflag; + boolean texflat = true; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; @@ -622,22 +624,25 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is break; } - if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? - { - patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); - fflatwidth = patch->width; - fflatheight = patch->height; - } + flatflag = ((INT32)fflatwidth)-1; if (texturenum != 0 && texturenum != -1) { fflatwidth = textures[texturenum]->width; fflatheight = textures[texturenum]->height; } + else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? + { + patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); + fflatwidth = SHORT(patch->width); + fflatheight = SHORT(patch->height); + } + else + texflat = false; // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)((FLOAT_TO_FIXED(pv->x) % llrint(fflatwidth)) / fflatwidth); - flatyref = (float)((FLOAT_TO_FIXED(pv->y) % llrint(fflatheight)) / fflatheight); + flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth); + flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatheight); // transform v3d = planeVerts; @@ -693,17 +698,24 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) { // Hurdler: add scrolling texture on floor/ceiling - v3d->sow = (float)((pv->x / fflatwidth) - flatxref + scrollx); - v3d->tow = (float)(flatyref - (pv->y / fflatheight) + scrolly); - - //v3d->sow = (float)(pv->x / fflatsize); - //v3d->tow = (float)(pv->y / fflatsize); + if (texflat) + { + v3d->sow = (float)(pv->x / fflatwidth) + scrollx; + v3d->tow = -(float)(pv->y / fflatheight) + scrolly; + } + else + { + v3d->sow = (float)((pv->x / fflatwidth) - flatxref + scrollx); + v3d->tow = (float)(flatyref - (pv->y / fflatheight) + scrolly); + } // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { tempxsow = FLOAT_TO_FIXED(v3d->sow); tempytow = FLOAT_TO_FIXED(v3d->tow); + if (texflat) + tempytow = -tempytow; v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle)))); } diff --git a/src/r_data.c b/src/r_data.c index 4157a8850..092dc069a 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1694,7 +1694,7 @@ void R_FlatPatch(patch_t *patch, UINT8 *flat) UINT8 *source; desttop = flat; - deststop = desttop + (patch->width * patch->height); + deststop = desttop + (SHORT(patch->width) * SHORT(patch->height)); for (col = 0; col < SHORT(patch->width); col++, desttop++) { @@ -1708,13 +1708,13 @@ void R_FlatPatch(patch_t *patch, UINT8 *flat) topdelta += prevdelta; prevdelta = topdelta; - dest = desttop + (topdelta * patch->width); + dest = desttop + (topdelta * SHORT(patch->width)); source = (UINT8 *)(column) + 3; for (ofs = 0; dest < deststop && ofs < column->length; ofs++) { if (source[ofs] != TRANSPARENTPIXEL) *dest = source[ofs]; - dest += patch->width; + dest += SHORT(patch->width); } column = (column_t *)((UINT8 *)column + column->length + 4); } @@ -1733,9 +1733,8 @@ void R_FlatTexture(size_t tex, UINT8 *flat) desttop = flat; deststop = desttop + (texture->width * texture->height); - for (col = 0; col < SHORT(texture->width); col++, desttop++) + for (col = 0; col < texture->width; col++, desttop++) { - INT32 topdelta, prevdelta = -1; column = (column_t *)R_GetColumn(tex, col); if (!texture->holes) { @@ -1750,6 +1749,7 @@ void R_FlatTexture(size_t tex, UINT8 *flat) } else { + INT32 topdelta, prevdelta = -1; while (column->topdelta != 0xff) { topdelta = column->topdelta; diff --git a/src/r_draw8.c b/src/r_draw8.c index f829707d3..542572707 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -550,12 +550,18 @@ void R_DrawSpan_8 (void) UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - UINT32 flatsize = ds_flatwidth * ds_flatheight; size_t count = (ds_x2 - ds_x1 + 1); xposition = ds_xfrac; yposition = ds_yfrac; xstep = ds_xstep; ystep = ds_ystep; + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? if (ds_powersoftwo) { xposition <<= nflatshiftup; yposition <<= nflatshiftup; @@ -566,7 +572,7 @@ void R_DrawSpan_8 (void) colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - if (dest > deststop) + if (dest+8 > deststop) return; if (!ds_powersoftwo) @@ -582,13 +588,56 @@ void R_DrawSpan_8 (void) if (y < 0) y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - *dest++ = colormap[source[((y * ds_flatwidth) + x) % flatsize]]; + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest++ = colormap[source[((y * ds_flatwidth) + x)]]; xposition += xstep; yposition += ystep; } } else { + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + dest[0] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[1] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[2] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[3] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[4] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[5] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[6] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[7] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } while (count-- && dest <= deststop) { *dest++ = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; @@ -1052,13 +1101,19 @@ void R_DrawSplat_8 (void) UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - UINT32 flatsize = ds_flatwidth * ds_flatheight; size_t count = (ds_x2 - ds_x1 + 1); UINT32 val; xposition = ds_xfrac; yposition = ds_yfrac; xstep = ds_xstep; ystep = ds_ystep; + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? if (ds_powersoftwo) { xposition <<= nflatshiftup; yposition <<= nflatshiftup; @@ -1082,7 +1137,10 @@ void R_DrawSplat_8 (void) if (y < 0) y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - val = source[((y * ds_flatwidth) + x) % flatsize]; + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; dest++; @@ -1092,6 +1150,80 @@ void R_DrawSplat_8 (void) } else { + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + // + // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[0] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[1] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[2] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[3] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[4] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[5] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[6] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[7] = colormap[val]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } while (count-- && dest <= deststop) { val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; @@ -1118,13 +1250,19 @@ void R_DrawTranslucentSplat_8 (void) UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - UINT32 flatsize = ds_flatwidth * ds_flatheight; size_t count = (ds_x2 - ds_x1 + 1); UINT32 val; xposition = ds_xfrac; yposition = ds_yfrac; xstep = ds_xstep; ystep = ds_ystep; + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? if (ds_powersoftwo) { xposition <<= nflatshiftup; yposition <<= nflatshiftup; @@ -1148,7 +1286,10 @@ void R_DrawTranslucentSplat_8 (void) if (y < 0) y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - val = source[((y * ds_flatwidth) + x) % flatsize]; + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; if (val != TRANSPARENTPIXEL) *dest = *(ds_transmap + (colormap[val] << 8) + *dest); dest++; @@ -1158,6 +1299,62 @@ void R_DrawTranslucentSplat_8 (void) } else { + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } while (count-- && dest <= deststop) { val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; @@ -1184,13 +1381,19 @@ void R_DrawTranslucentSpan_8 (void) UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - UINT32 flatsize = ds_flatwidth * ds_flatheight; size_t count = (ds_x2 - ds_x1 + 1); UINT32 val; xposition = ds_xfrac; yposition = ds_yfrac; xstep = ds_xstep; ystep = ds_ystep; + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? if (ds_powersoftwo) { xposition <<= nflatshiftup; yposition <<= nflatshiftup; @@ -1214,7 +1417,10 @@ void R_DrawTranslucentSpan_8 (void) if (y < 0) y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - val = ((y * ds_flatwidth) + x) % flatsize; + x %= ds_flatwidth; + y %= ds_flatheight; + + val = ((y * ds_flatwidth) + x); *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); dest++; xposition += xstep; @@ -1223,6 +1429,46 @@ void R_DrawTranslucentSpan_8 (void) } else { + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + dest[0] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; + + dest[1] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; + + dest[2] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; + + dest[3] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + dest[4] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + dest[5] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + dest[6] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + dest[7] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } while (count-- && dest <= deststop) { val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); @@ -1247,12 +1493,18 @@ void R_DrawTranslucentWaterSpan_8(void) UINT8 *dsrc; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - UINT32 flatsize = ds_flatwidth * ds_flatheight; size_t count = (ds_x2 - ds_x1 + 1); xposition = ds_xfrac; yposition = (ds_yfrac + ds_waterofs); xstep = ds_xstep; ystep = ds_ystep; + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? if (ds_powersoftwo) { xposition <<= nflatshiftup; yposition <<= nflatshiftup; @@ -1277,7 +1529,10 @@ void R_DrawTranslucentWaterSpan_8(void) if (y < 0) y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - *dest++ = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x) % flatsize] << 8) + *dsrc++)]; + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest++ = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x)] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; } diff --git a/src/r_plane.c b/src/r_plane.c index 01d0fdd37..37a76e2cd 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -758,8 +758,8 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture) else { patch = (patch_t *)ds_source; - levelflat->width = ds_flatwidth = patch->width; - levelflat->height = ds_flatheight = patch->height; + levelflat->width = ds_flatwidth = SHORT(patch->width); + levelflat->height = ds_flatheight = SHORT(patch->height); levelflat->topoffset = patch->topoffset * FRACUNIT; levelflat->leftoffset = patch->leftoffset * FRACUNIT; @@ -1031,13 +1031,13 @@ void R_DrawSinglePlane(visplane_t *pl) levelflat = &levelflats[pl->picnum]; size = W_LumpLength(levelflat->lumpnum); - // Check if the flat is actually a texture. + // Check if the flat is actually a wall texture. if (levelflat->texturenum != 0 && levelflat->texturenum != -1) R_GetPatchFlat(levelflat, true); - // Check if the flat is actually a patch. + // Maybe it's just a patch, then? else if (R_CheckIfPatch(levelflat->lumpnum)) R_GetPatchFlat(levelflat, false); - // Raw flat. + // It's a raw flat. else { ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag From a4a529bdb5af0a9bd2cc5d8dfef1a2d0d08c48b6 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sun, 26 May 2019 17:41:10 -0300 Subject: [PATCH 007/133] Hardware renderer: Disable Glide-specific texture handling --- src/hardware/hw_cache.c | 15 +++++++++++++++ src/hardware/hw_glide.h | 2 ++ src/hardware/hw_light.c | 2 ++ src/hardware/hw_md2.c | 4 ++++ 4 files changed, 23 insertions(+) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 504ded35b..72b78a985 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -190,6 +190,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, GrTexInfo *grInfo) { +#ifdef GLIDE_API_COMPATIBILITY // Build the full textures from patches. static const GrLOD_t gr_lods[9] = { @@ -226,6 +227,9 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, INT32 j,k; INT32 max,min; +#else + (void)grInfo; +#endif // find a power of 2 width/height if (cv_grrounddown.value) @@ -281,6 +285,7 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, } else { +#ifdef GLIDE_API_COMPATIBILITY //size up to nearest power of 2 blockwidth = 1; while (blockwidth < originalwidth) @@ -298,9 +303,14 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, if (blockheight > 2048) blockheight = 2048; //I_Error("3D GenerateTexture : too big"); +#else + blockwidth = originalwidth; + blockheight = originalheight; +#endif } // do the boring LOD stuff.. blech! +#ifdef GLIDE_API_COMPATIBILITY if (blockwidth >= blockheight) { max = blockwidth; @@ -332,6 +342,7 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, if (blockwidth < blockheight) j += 4; grInfo->aspectRatioLog2 = gr_aspects[j].aspect; +#endif blocksize = blockwidth * blockheight; @@ -684,9 +695,11 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) size_t size, pflatsize; // setup the texture info +#ifdef GLIDE_API_COMPATIBILITY grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif grMipmap->grInfo.format = GR_TEXFMT_P_8; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; @@ -753,9 +766,11 @@ void HWR_GetFlat(lumpnum_t flatlumpnum) static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) { // setup the texture info +#ifdef GLIDE_API_COMPATIBILITY grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif grMipmap->grInfo.format = GR_TEXFMT_P_8; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; diff --git a/src/hardware/hw_glide.h b/src/hardware/hw_glide.h index 2625d5864..bf91229ef 100644 --- a/src/hardware/hw_glide.h +++ b/src/hardware/hw_glide.h @@ -59,9 +59,11 @@ typedef FxI32 GrTextureFormat_t; typedef struct { +#ifdef GLIDE_API_COMPATIBILITY GrLOD_t smallLodLog2; GrLOD_t largeLodLog2; GrAspectRatio_t aspectRatioLog2; +#endif GrTextureFormat_t format; void *data; } GrTexInfo; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index a93e96dc3..23e8a3431 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1112,9 +1112,11 @@ static void HWR_SetLight(void) lightmappatch.height = 128; lightmappatch.mipmap.width = 128; lightmappatch.mipmap.height = 128; +#ifdef GLIDE_API_COMPATIBILITY lightmappatch.mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_128; lightmappatch.mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_128; lightmappatch.mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif lightmappatch.mipmap.flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw ! } HWD.pfnSetTexture(&lightmappatch.mipmap); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index cb33562d8..e3ac82fa8 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -716,10 +716,12 @@ static void md2_loadTexture(md2_t *model) grpatch->mipmap.width = (UINT16)w; grpatch->mipmap.height = (UINT16)h; +#ifdef GLIDE_API_COMPATIBILITY // not correct! grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif } HWD.pfnSetTexture(&grpatch->mipmap); HWR_UnlockCachedPatch(grpatch); @@ -767,10 +769,12 @@ static void md2_loadBlendTexture(md2_t *model) grpatch->mipmap.width = (UINT16)w; grpatch->mipmap.height = (UINT16)h; +#ifdef GLIDE_API_COMPATIBILITY // not correct! grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif } HWD.pfnSetTexture(&grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary HWR_UnlockCachedPatch(grpatch); From 0bcf89679e7fa52d04c184475b0da67164e30f14 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sun, 26 May 2019 18:16:13 -0300 Subject: [PATCH 008/133] Hardware renderer: Fix polyobjects --- src/hardware/hw_cache.c | 2 +- src/hardware/hw_main.c | 38 +++++++++++++++++++++++++++----------- src/p_setup.c | 5 ++++- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 72b78a985..54a1f6695 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -677,7 +677,7 @@ GLTexture_t *HWR_GetTexture(INT32 tex) return grtex; } -// Lactozilla +// HWR_RenderPlane and HWR_RenderPolyObjectPlane need this to get the flat dimensions from a patch. lumpnum_t gr_patchflat; static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 02e731164..de273cfed 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3172,6 +3172,8 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, INT32 i; float flatxref,flatyref; float fflatwidth, fflatheight; + INT32 flatflag; + boolean texflat = true; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; @@ -3231,22 +3233,25 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, break; } - if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? - { - patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); - fflatwidth = patch->width; - fflatheight = patch->height; - } + flatflag = ((INT32)fflatwidth)-1; if (texturenum != 0 && texturenum != -1) { fflatwidth = textures[texturenum]->width; fflatheight = textures[texturenum]->height; } + else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? + { + patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); + fflatwidth = SHORT(patch->width); + fflatheight = SHORT(patch->height); + } + else + texflat = false; // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)((polysector->origVerts[0].x % llrint(fflatwidth)) / fflatwidth); - flatyref = (float)((polysector->origVerts[0].y % llrint(fflatheight)) / fflatheight); + flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth); + flatyref = (float)((polysector->origVerts[0].y & (~flatflag)) / fflatheight); // transform v3d = planeVerts; @@ -3300,15 +3305,26 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++) { - // Hurdler: add scrolling texture on floor/ceiling - v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx); // Go from the polysector's original vertex locations - v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly); // Means the flat is offset based on the original vertex locations + // Go from the polysector's original vertex locations + // Means the flat is offset based on the original vertex locations + if (texflat) + { + v3d->sow = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx; + v3d->tow = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly; + } + else + { + v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx); + v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly); + } // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { tempxsow = FLOAT_TO_FIXED(v3d->sow); tempytow = FLOAT_TO_FIXED(v3d->tow); + if (texflat) + tempytow = -tempytow; v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle)))); } diff --git a/src/p_setup.c b/src/p_setup.c index 97bace860..c1ba4c67a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -613,8 +613,11 @@ INT32 P_AddLevelFlatRuntime(const char *flatname) // 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); From 39857a846a47af5bad63992542636dae956e8fd3 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sun, 26 May 2019 23:37:23 -0300 Subject: [PATCH 009/133] PNG support --- src/doomdef.h | 2 + src/hardware/hw_cache.c | 10 +- src/r_data.c | 459 ++++++++++++++++++++++++++++++++++++++-- src/r_data.h | 14 +- src/r_plane.c | 54 +++-- src/w_wad.c | 2 - 6 files changed, 508 insertions(+), 33 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 527cdf05f..2bf9efa68 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -536,4 +536,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2CB itself ported this from PrBoom+ #define NEWCLIP +//#define NO_PNG_LUMPS + #endif // __DOOMDEF__ diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 54a1f6695..457f628d0 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -451,7 +451,10 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { + size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); + if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); HWR_DrawPatchInCache(&grtex->mipmap, blockwidth, blockheight, blockwidth*format2bpp[grtex->mipmap.grInfo.format], @@ -683,11 +686,14 @@ lumpnum_t gr_patchflat; static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC); + size_t lumplength = W_LumpLength(flatlumpnum); + if (R_IsLumpPNG((UINT8 *)patch, lumplength)) + patch = R_PNGToPatch((UINT8 *)patch, lumplength); grMipmap->width = (UINT16)SHORT(patch->width); grMipmap->height = (UINT16)SHORT(patch->height); - R_FlatPatch(patch, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); + R_PatchToFlat(patch, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); } static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) @@ -777,7 +783,7 @@ static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) grMipmap->width = (UINT16)textures[texturenum]->width; grMipmap->height = (UINT16)textures[texturenum]->height; - R_FlatTexture(texturenum, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); + R_TextureToFlat(texturenum, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); } void HWR_GetTextureFlat(INT32 texturenum) diff --git a/src/r_data.c b/src/r_data.c index db92c11fe..ea8785afb 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -40,6 +40,28 @@ #include #endif +#ifdef HAVE_PNG + +#ifndef _MSC_VER +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#endif + +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif + +#include "png.h" +#ifndef PNG_READ_SUPPORTED +#undef HAVE_PNG +#endif +#endif + // // Texture definition. // Each texture is composed of one or more patches, @@ -178,7 +200,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig // Allocate space for full size texture, either single patch or 'composite' // Build the full textures from patches. // The texture caching system is a little more hungry of memory, but has -// been simplified for the sake of highcolor, dynamic ligthing, & speed. +// been simplified for the sake of highcolor (lol), dynamic ligthing, & speed. // // This is not optimised, but it's supposed to be executed only once // per level, when enough memory is available. @@ -195,6 +217,10 @@ static UINT8 *R_GenerateTexture(size_t texnum) column_t *patchcol; UINT32 *colofs; + UINT16 wadnum; + lumpnum_t lumpnum; + size_t lumplength; + I_Assert(texnum <= (size_t)numtextures); texture = textures[texnum]; I_Assert(texture != NULL); @@ -209,7 +235,13 @@ static UINT8 *R_GenerateTexture(size_t texnum) { boolean holey = false; patch = texture->patches; - realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); + + wadnum = patch->wad; + lumpnum = patch->lump; + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) @@ -238,7 +270,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) if (holey) { texture->holes = true; - blocksize = W_LumpLengthPwad(patch->wad, patch->lump); + blocksize = lumplength; block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function &texturecache[texnum]); M_Memcpy(block, realpatch, blocksize); @@ -274,7 +306,13 @@ static UINT8 *R_GenerateTexture(size_t texnum) // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { - realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); + wadnum = patch->wad; + lumpnum = patch->lump; + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); + x1 = patch->originx; x2 = x1 + SHORT(realpatch->width); @@ -487,7 +525,10 @@ void R_LoadTextures(void) // Work through each lump between the markers in the WAD. for (j = 0; j < (texend - texstart); i++, j++) { - patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE); + UINT16 wadnum = (UINT16)w; + lumpnum_t lumpnum = texstart + j; + size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum); + patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); // Then, check the lump directly to see if it's a texture SOC, // and if it is, load it using dehacked instead. @@ -503,9 +544,19 @@ void R_LoadTextures(void) texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); // Set texture properties. - M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name)); - texture->width = SHORT(patchlump->width); - texture->height = SHORT(patchlump->height); + M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + if (R_IsLumpPNG((UINT8 *)patchlump, lumplength)) + { + INT16 width, height; + R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength); + texture->width = width; + texture->height = height; + } + else + { + texture->width = SHORT(patchlump->width); + texture->height = SHORT(patchlump->height); + } texture->patchcount = 1; texture->holes = false; @@ -1178,7 +1229,6 @@ INT32 R_ColormapNumForName(char *name) // static double deltas[256][3], map[256][3]; -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); static int RoundUp(double number); INT32 R_CreateColormap(char *p1, char *p2, char *p3) @@ -1358,7 +1408,7 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) // Thanks to quake2 source! // utils3/qdata/images.c -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) { int dr, dg, db; int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i; @@ -1686,7 +1736,7 @@ boolean R_CheckIfPatch(lumpnum_t lump) return result; } -void R_FlatPatch(patch_t *patch, UINT8 *flat) +void R_PatchToFlat(patch_t *patch, UINT8 *flat) { fixed_t col, ofs; column_t *column; @@ -1721,7 +1771,392 @@ void R_FlatPatch(patch_t *patch, UINT8 *flat) } } -void R_FlatTexture(size_t tex, UINT8 *flat) +#ifndef NO_PNG_LUMPS +boolean R_IsLumpPNG(UINT8 *d, size_t s) +{ + if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/ + return false; + // Check for PNG file signature using memcmp + // As it may be faster on CPUs with slow unaligned memory access + // Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature + return (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0); +} + +#ifdef HAVE_PNG +typedef struct { + png_bytep buffer; + png_uint_32 bufsize; + png_uint_32 current_pos; +} png_ioread; + +static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_ioread *f = png_get_io_ptr(png_ptr); + if (length > (f->bufsize - f->current_pos)) + png_error(png_ptr, "read error in read_data_memory (loadpng)"); + memcpy(data, f->buffer + f->current_pos, length); + f->current_pos += length; +} + +static void PNG_error(png_structp PNG, png_const_charp pngtext) +{ + CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext); + //I_Error("libpng error at %p: %s", PNG, pngtext); +} + +static void PNG_warn(png_structp PNG, png_const_charp pngtext) +{ + CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext); +} + +static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) +{ + png_structp png_ptr; + png_infop png_info_ptr; + png_uint_32 width, height; + int bit_depth, color_type; + png_uint_32 y; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + png_ioread png_io; + png_bytep *row_pointers; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, + PNG_error, PNG_warn); + if (!png_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n"); + return NULL; + } + + png_info_ptr = png_create_info_struct(png_ptr); + if (!png_info_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n"); + png_destroy_read_struct(&png_ptr, NULL, NULL); + return NULL; + } + +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) +#endif + { + //CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename); + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + return NULL; + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); +#endif + + // png_source is array which have png data + png_io.buffer = (png_bytep)png; + png_io.bufsize = size; + png_io.current_pos = 0; + // set our own read_function + png_set_read_fn(png_ptr, &png_io, PNG_IOReader); + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_set_user_limits(png_ptr, 2048, 2048); +#endif + + png_read_info(png_ptr, png_info_ptr); + + png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type, + NULL, NULL, NULL); + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + else if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + else if (color_type != PNG_COLOR_TYPE_RGB_ALPHA && color_type != PNG_COLOR_TYPE_GRAY_ALPHA) + { +#if PNG_LIBPNG_VER < 10207 + png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); +#else + png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER); +#endif + } + + png_read_update_info(png_ptr, png_info_ptr); + + // Read the image + row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); + for (y = 0; y < height; y++) + row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, png_info_ptr)); + png_read_image(png_ptr, row_pointers); + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + + *w = (INT32)width; + *h = (INT32)height; + return row_pointers; +} + +// Convert a PNG to a raw image. +static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) +{ + UINT8 *flat; + png_uint_32 x, y; + png_bytep *row_pointers = PNG_Read(png, w, h, size); + png_uint_32 width = *w, height = *h; + + if (!row_pointers) + return NULL; + + // Convert the image to 8bpp + flat = Z_Malloc(width * height, PU_STATIC, NULL); + memset(flat, TRANSPARENTPIXEL, width * height); + for (y = 0; y < height; y++) + { + png_bytep row = row_pointers[y]; + for (x = 0; x < width; x++) + { + png_bytep px = &(row[x * 4]); + flat[((y * width) + x)] = NearestColor((UINT8)px[0], (UINT8)px[1], (UINT8)px[2]); + } + } + free(row_pointers); + + return flat; +} + +// Get the alpha mask of the image. +static UINT8 *PNG_GetAlphaMask(UINT8 *png, size_t size) +{ + UINT8 *mask; + png_uint_32 x, y; + UINT16 width, height; + png_bytep *row_pointers = PNG_Read(png, &width, &height, size); + + if (!row_pointers) + return NULL; + + // Convert the image to 8bpp + mask = Z_Malloc(width * height, PU_STATIC, NULL); + memset(mask, 0, width * height); + for (y = 0; y < height; y++) + { + png_bytep row = row_pointers[y]; + for (x = 0; x < width; x++) + { + png_bytep px = &(row[x * 4]); + mask[((y * width) + x)] = (UINT8)px[3]; + } + } + free(row_pointers); + + return mask; +} + +// Convert a PNG to a flat. +UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size) +{ + return PNG_RawConvert(png, &levelflat->width, &levelflat->height, size); +} + +// Convert a PNG to a patch. +// This is adapted from the "kartmaker" utility +static unsigned char imgbuf[1<<26]; +patch_t *R_PNGToPatch(UINT8 *png, size_t size) +{ + UINT16 width, height; + UINT8 *raw = PNG_RawConvert(png, &width, &height, size); + UINT8 *alphamask = PNG_GetAlphaMask(png, size); + + UINT32 x, y; + UINT8 *img; + UINT8 *imgptr = imgbuf; + UINT8 *colpointers, *startofspan; + + #define WRITE8(buf, a) ({*buf = (a); buf++;}) + #define WRITE16(buf, a) ({*buf = (a)&255; buf++; *buf = (a)>>8; buf++;}) + #define WRITE32(buf, a) ({WRITE16(buf, (a)&65535); WRITE16(buf, (a)>>16);}) + + if (!raw) + return NULL; + + // Write image size and offset + WRITE16(imgptr, width); + WRITE16(imgptr, height); + // no offsets + WRITE16(imgptr, 0); + WRITE16(imgptr, 0); + + // Leave placeholder to column pointers + colpointers = imgptr; + imgptr += width*4; + + // Write columns + for (x = 0; x < width; x++) + { + int lastStartY = 0; + int spanSize = 0; + startofspan = NULL; + + //printf("%d ", x); + // Write column pointer (@TODO may be wrong) + WRITE32(colpointers, imgptr - imgbuf); + + // Write pixels + for (y = 0; y < height; y++) + { + UINT8 paletteIndex = raw[((y * width) + x)]; + UINT8 opaque = alphamask[((y * width) + x)]; // If 1, we have a pixel + + // End span if we have a transparent pixel + if (!opaque) + { + if (startofspan) + WRITE8(imgptr, 0); + startofspan = NULL; + continue; + } + + // Start new column if we need to + if (!startofspan || spanSize == 255) + { + int writeY = y; + + // If we reached the span size limit, finish the previous span + if (startofspan) + WRITE8(imgptr, 0); + + if (y > 254) + { + // Make sure we're aligned to 254 + if (lastStartY < 254) + { + WRITE8(imgptr, 254); + WRITE8(imgptr, 0); + imgptr += 2; + lastStartY = 254; + } + + // Write stopgap empty spans if needed + writeY = y - lastStartY; + + while (writeY > 254) + { + WRITE8(imgptr, 254); + WRITE8(imgptr, 0); + imgptr += 2; + writeY -= 254; + } + } + + startofspan = imgptr; + WRITE8(imgptr, writeY);///@TODO calculate starting y pos + imgptr += 2; + spanSize = 0; + + lastStartY = y; + } + + // Write the pixel + WRITE8(imgptr, paletteIndex); + spanSize++; + startofspan[1] = spanSize; + } + + if (startofspan) + WRITE8(imgptr, 0); + + WRITE8(imgptr, 0xFF); + } + + #undef WRITE8 + #undef WRITE16 + #undef WRITE32 + + size = imgptr-imgbuf; + img = malloc(size); + memcpy(img, imgbuf, size); + return (patch_t *)img; +} + +boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size) +{ + png_structp png_ptr; + png_infop png_info_ptr; + png_uint_32 w, h; + int bit_depth, color_type; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + png_ioread png_io; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, + PNG_error, PNG_warn); + if (!png_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n"); + return false; + } + + png_info_ptr = png_create_info_struct(png_ptr); + if (!png_info_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n"); + png_destroy_read_struct(&png_ptr, NULL, NULL); + return false; + } + +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) +#endif + { + //CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename); + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + return false; + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); +#endif + + // png_source is array which have png data + png_io.buffer = (png_bytep)png; + png_io.bufsize = size; + png_io.current_pos = 0; + // set our own read_function + png_set_read_fn(png_ptr, &png_io, PNG_IOReader); + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_set_user_limits(png_ptr, 2048, 2048); +#endif + + png_read_info(png_ptr, png_info_ptr); + + png_get_IHDR(png_ptr, png_info_ptr, &w, &h, &bit_depth, &color_type, + NULL, NULL, NULL); + + // okay done. stop. + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + + *width = (INT32)w; + *height = (INT32)h; + return true; +} +#endif +#endif + +void R_TextureToFlat(size_t tex, UINT8 *flat) { texture_t *texture = textures[tex]; diff --git a/src/r_data.h b/src/r_data.h index 855daa06d..5f3f10d59 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -16,6 +16,7 @@ #include "r_defs.h" #include "r_state.h" +#include "p_setup.h" // levelflats #ifdef __GNUG__ #pragma interface @@ -105,14 +106,23 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3); const char *R_ColormapNameForNum(INT32 num); boolean R_CheckIfPatch(lumpnum_t lump); +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); -void R_FlatPatch(patch_t *patch, UINT8 *flat); -void R_FlatTexture(size_t tex, UINT8 *flat); +void R_PatchToFlat(patch_t *patch, UINT8 *flat); +void R_TextureToFlat(size_t tex, UINT8 *flat); void R_CropFlat(UINT8 *srcflat, UINT8 *destflat, UINT16 srcwidth, UINT16 srcheight, UINT16 resizewidth, UINT16 resizeheight, UINT16 destwidth, UINT16 destheight); +#ifndef NO_PNG_LUMPS +boolean R_IsLumpPNG(UINT8 *d, size_t s); + +UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size); +patch_t *R_PNGToPatch(UINT8 *png, size_t size); +boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size); +#endif + extern INT32 numtextures; #endif diff --git a/src/r_plane.c b/src/r_plane.c index 37a76e2cd..d07a68759 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -714,7 +714,7 @@ void R_CheckFlatLength(size_t size) } } -static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture) +static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng) { textureflat_t *texflat = &texflats[levelflat->texturenum]; patch_t *patch = NULL; @@ -751,23 +751,46 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture) 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); + R_TextureToFlat(levelflat->texturenum, texflat->flat); ds_source = texflat->flat; } else { patch = (patch_t *)ds_source; - levelflat->width = ds_flatwidth = SHORT(patch->width); - levelflat->height = ds_flatheight = SHORT(patch->height); +#ifndef NO_PNG_LUMPS +#ifdef HAVE_PNG + if (ispng) + { + levelflat->flatpatch = R_PNGToFlat(levelflat, ds_source, W_LumpLength(levelflat->lumpnum)); + levelflat->topoffset = levelflat->leftoffset = 0; + if (levelflat->flatpatch == NULL) + { + lumpnum_t redflr = W_CheckNumForName("REDFLR"); + levelflat->flatpatch = (UINT8 *)W_CacheLumpNum(redflr, PU_STATIC); + R_CheckFlatLength(W_LumpLength(redflr)); + R_CheckPowersOfTwo(); + } + else + { + ds_flatwidth = levelflat->width; + ds_flatheight = levelflat->height; + } + } + else +#endif +#endif + { + levelflat->width = ds_flatwidth = SHORT(patch->width); + levelflat->height = ds_flatheight = SHORT(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; + levelflat->flatpatch = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL); + memset(levelflat->flatpatch, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight); + R_PatchToFlat(patch, levelflat->flatpatch); + } ds_source = levelflat->flatpatch; } @@ -1030,19 +1053,20 @@ void R_DrawSinglePlane(visplane_t *pl) currentplane = pl; levelflat = &levelflats[pl->picnum]; size = W_LumpLength(levelflat->lumpnum); + ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag // Check if the flat is actually a wall texture. if (levelflat->texturenum != 0 && levelflat->texturenum != -1) - R_GetPatchFlat(levelflat, true); + R_GetPatchFlat(levelflat, true, false); // Maybe it's just a patch, then? else if (R_CheckIfPatch(levelflat->lumpnum)) - R_GetPatchFlat(levelflat, false); + R_GetPatchFlat(levelflat, false, false); + // Maybe it's a PNG?! + else if (R_IsLumpPNG(ds_source, size)) + R_GetPatchFlat(levelflat, false, true); // It's a raw flat. else - { - ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag R_CheckFlatLength(size); - } // Check if the flat has dimensions that are powers-of-two numbers. if (R_CheckPowersOfTwo()) diff --git a/src/w_wad.c b/src/w_wad.c index c4f9ceca8..5e25dea97 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1179,8 +1179,6 @@ void zerr(int ret) } #endif -#define NO_PNG_LUMPS - #ifdef NO_PNG_LUMPS static void ErrorIfPNG(UINT8 *d, size_t s, char *f, char *l) { From 0e162f8f6118f3fd22311ac2cb9930dead33e0a1 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Thu, 20 Jun 2019 13:33:31 +0200 Subject: [PATCH 010/133] Add Sryder's orbital camera thing as an option. --- src/m_menu.c | 22 ++++++++++++---------- src/p_local.h | 4 ++-- src/p_user.c | 25 ++++++++++++++++++++----- src/r_main.c | 2 ++ 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 4f78d0adc..538e2ebf1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1000,12 +1000,13 @@ static menuitem_t OP_P1ControlsMenu[] = {IT_SUBMENU | IT_STRING, NULL, "Gamepad Options...", &OP_Joystick1Def , 30}, {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam , 50}, - {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam , 60}, - {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 70}, + {IT_STRING | IT_CVAR, NULL, "Third-person Orbital" , &cv_cam_orbit , 60}, + {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam , 70}, + {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 80}, - //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog, 90}, - {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar, 90}, - {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake, 100}, + //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog, 100}, + {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar, 100}, + {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake, 110}, }; static menuitem_t OP_P2ControlsMenu[] = @@ -1015,12 +1016,13 @@ static menuitem_t OP_P2ControlsMenu[] = {IT_SUBMENU | IT_STRING, NULL, "Second Gamepad Options...", &OP_Joystick2Def , 30}, {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam2 , 50}, - {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam2 , 60}, - {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 70}, + {IT_STRING | IT_CVAR, NULL, "Third-person Orbital" , &cv_cam2_orbit , 60}, + {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam2 , 70}, + {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 80}, - //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog2, 90}, - {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar2, 90}, - {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake2, 100}, + //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog2, 100}, + {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar2, 100}, + {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake2, 110}, }; static menuitem_t OP_ChangeControlsMenu[] = diff --git a/src/p_local.h b/src/p_local.h index b686b9f09..d094b6399 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -109,10 +109,10 @@ typedef struct camera_s extern camera_t camera, camera2; extern consvar_t cv_cam_dist, cv_cam_still, cv_cam_height; -extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed; +extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed, cv_cam_orbit; extern consvar_t cv_cam2_dist, cv_cam2_still, cv_cam2_height; -extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed; +extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed, cv_cam2_orbit; extern fixed_t t_cam_dist, t_cam_height, t_cam_rotate; extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate; diff --git a/src/p_user.c b/src/p_user.c index ca14c64d4..c38514db9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8898,12 +8898,14 @@ consvar_t cv_cam_still = {"cam_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_orbit = {"cam_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_height = {"cam2_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam2_orbit = {"cam2_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; fixed_t t_cam_dist = -42; fixed_t t_cam_height = -42; @@ -8957,7 +8959,7 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled) { angle_t angle = 0, focusangle = 0, focusaiming = 0; - fixed_t x, y, z, dist, checkdist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight; + fixed_t x, y, z, dist, distxy, distz, checkdist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight; INT32 camrotate; boolean camstill, cameranoclip; mobj_t *mo; @@ -9165,13 +9167,26 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall dist <<= 1; } + + checkdist = (dist = FixedMul(dist, player->camerascale)); if (checkdist < 128*FRACUNIT) checkdist = 128*FRACUNIT; - x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); - y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); + if ((thiscam == &camera && cv_cam_orbit.value) || (thiscam == &camera2 && cv_cam2_orbit.value)) + { + distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); + distz = -FixedMul(dist, FINESINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); + } + else + { + distxy = dist; + distz = 0; + } + + x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), distxy); + y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), distxy); #if 0 if (twodlevel || (mo->flags2 & MF2_TWOD)) @@ -9208,9 +9223,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall pviewheight = FixedMul(41*player->height/48, mo->scale); if (mo->eflags & MFE_VERTICALFLIP) - z = mo->z + mo->height - pviewheight - camheight; + z = mo->z + mo->height - pviewheight - camheight + distz; else - z = mo->z + pviewheight + camheight; + z = mo->z + pviewheight + camheight + distz; // move camera down to move under lower ceilings newsubsec = R_IsPointInSubsector(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1)); diff --git a/src/r_main.c b/src/r_main.c index 273d13a56..5ed411046 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1176,6 +1176,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_cam_speed); CV_RegisterVar(&cv_cam_rotate); CV_RegisterVar(&cv_cam_rotspeed); + CV_RegisterVar(&cv_cam_orbit); CV_RegisterVar(&cv_cam2_dist); CV_RegisterVar(&cv_cam2_still); @@ -1183,6 +1184,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_cam2_speed); CV_RegisterVar(&cv_cam2_rotate); CV_RegisterVar(&cv_cam2_rotspeed); + CV_RegisterVar(&cv_cam2_orbit); CV_RegisterVar(&cv_showhud); CV_RegisterVar(&cv_translucenthud); From 02c3710211b408e103ce78d1d6cb3dbd93e43042 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 25 Jun 2019 14:40:00 -0300 Subject: [PATCH 011/133] hHA --- src/p_setup.h | 6 -- src/r_data.h | 5 -- src/r_draw8.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++--- src/r_plane.c | 164 ++++++++++-------------------------- 4 files changed, 264 insertions(+), 140 deletions(-) diff --git a/src/p_setup.h b/src/p_setup.h index 824584be7..a123f757a 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -49,12 +49,6 @@ typedef struct // for patchflats UINT8 *flatpatch; - -#ifdef ESLOPE - // rescaled version of the above - UINT8 *resizedflat; - UINT16 resizedwidth, resizedheight; -#endif } levelflat_t; extern size_t numlevelflats; diff --git a/src/r_data.h b/src/r_data.h index 855daa06d..c528fcfe1 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -52,11 +52,6 @@ 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 diff --git a/src/r_draw8.c b/src/r_draw8.c index 542572707..1c4527a8e 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -724,7 +724,24 @@ void R_DrawTiltedSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; iz += ds_sz.x; uz += ds_su.x; @@ -761,7 +778,24 @@ void R_DrawTiltedSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; u += stepu; v += stepv; @@ -777,7 +811,24 @@ void R_DrawTiltedSpan_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; } else { @@ -798,7 +849,24 @@ void R_DrawTiltedSpan_8(void) for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; u += stepu; v += stepv; @@ -859,7 +927,24 @@ void R_DrawTiltedTranslucentSpan_8(void) v = (INT64)(vz*z) + viewy; colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; iz += ds_sz.x; uz += ds_su.x; @@ -896,7 +981,24 @@ void R_DrawTiltedTranslucentSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; u += stepu; v += stepv; @@ -912,7 +1014,24 @@ void R_DrawTiltedTranslucentSpan_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); } else { @@ -933,7 +1052,24 @@ void R_DrawTiltedTranslucentSpan_8(void) for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; u += stepu; v += stepv; @@ -994,9 +1130,28 @@ void R_DrawTiltedSplat_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) *dest = colormap[val]; + dest++; iz += ds_sz.x; uz += ds_su.x; @@ -1033,7 +1188,24 @@ void R_DrawTiltedSplat_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; dest++; @@ -1051,7 +1223,24 @@ void R_DrawTiltedSplat_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; } @@ -1075,6 +1264,24 @@ void R_DrawTiltedSplat_8(void) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = ((u-viewx) >> FRACBITS); + fixed_t y = ((v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; dest++; diff --git a/src/r_plane.c b/src/r_plane.c index 37a76e2cd..f79a5f90a 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -718,7 +718,6 @@ 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); // Check if the texture changed. @@ -738,11 +737,6 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture) // 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) { texture_t *texture = textures[levelflat->texturenum]; @@ -770,75 +764,6 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture) ds_source = levelflat->flatpatch; } - -#ifdef ESLOPE - // Crop the flat, if necessary. - if (!R_CheckPowersOfTwo()) - { - // 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)) - { - checkresizewidth += 2; - if (checkresizewidth & (checkresizewidth - 1)) - { - while (resizewidth > ds_flatwidth) - resizewidth >>= 1; - } - else - resizewidth = checkresizewidth; - } - else - resizewidth = checkresizewidth; - - checkresizeheight = ds_flatheight - 1; - if (checkresizeheight & (checkresizeheight - 1)) - { - checkresizeheight += 2; - if (checkresizeheight & (checkresizeheight - 1)) - { - while (resizeheight > ds_flatheight) - resizeheight >>= 1; - } - else - resizeheight = checkresizeheight; - } - else - resizeheight = checkresizeheight; - - // 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 { @@ -850,28 +775,6 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture) yoffs += levelflat->topoffset; } -#ifdef ESLOPE - if (currentplane->slope) - { - if (R_CheckPowersOfTwo()) - { - 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; } @@ -1061,22 +964,32 @@ void R_DrawSinglePlane(visplane_t *pl) floatv3_t p, m, n; float ang; float vx, vy, vz; - float fudge; + float fudge = 0; // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly // use this as a temp var to store P_GetZAt's return value each time fixed_t temp; - xoffs &= ((1 << (32-nflatshiftup))-1); - yoffs &= ((1 << (32-nflatshiftup))-1); + if (ds_powersoftwo) + { + // But xoffs and yoffs are zero..... ???!?!?!???!?!?! + xoffs &= ((1 << (32-nflatshiftup))-1); + yoffs &= ((1 << (32-nflatshiftup))-1); - xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red - fudge = ((1<slope->o.x; + yoffs = pl->slope->o.y; + } vx = FIXED_TO_FLOAT(pl->viewx+xoffs); vy = FIXED_TO_FLOAT(pl->viewy-yoffs); @@ -1111,13 +1024,16 @@ void R_DrawSinglePlane(visplane_t *pl) temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang))); n.y = FIXED_TO_FLOAT(temp) - zeroheight; - m.x /= fudge; - m.y /= fudge; - m.z /= fudge; + if (ds_powersoftwo) + { + m.x /= fudge; + m.y /= fudge; + m.z /= fudge; - n.x *= fudge; - n.y *= fudge; - n.z *= fudge; + n.x *= fudge; + n.y *= fudge; + n.z *= fudge; + } // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. #define CROSS(d, v1, v2) \ @@ -1134,14 +1050,26 @@ void R_DrawSinglePlane(visplane_t *pl) ds_sz.z *= focallengthf; // Premultiply the texture vectors with the scale factors + if (ds_powersoftwo) + { #define SFMULT 65536.f*(1< Date: Tue, 25 Jun 2019 14:41:07 -0300 Subject: [PATCH 012/133] Delete R_CropFlat --- src/r_data.c | 33 --------------------------------- src/r_data.h | 4 ---- 2 files changed, 37 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index db92c11fe..0e44ec8c7 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1770,36 +1770,3 @@ void R_FlatTexture(size_t tex, UINT8 *flat) } } } - -void R_CropFlat(UINT8 *srcflat, UINT8 *destflat, - UINT16 srcwidth, UINT16 srcheight, - UINT16 resizewidth, UINT16 resizeheight, - UINT16 destwidth, UINT16 destheight) -{ - UINT16 y; - UINT16 position = 0; - for (y = 0; y < destheight; y++) - { - if (position > (srcwidth * srcheight)) - break; - if (srcwidth != resizewidth) - { - if (resizewidth > srcwidth) - { - UINT8 *pos2 = srcflat+position; - UINT8 lastpixel = *(pos2-1); - M_Memcpy(destflat, srcflat+position, destwidth); - memset(pos2, lastpixel, resizewidth-srcwidth); - } - else - M_Memcpy(destflat, srcflat+position, resizewidth); - } - else - M_Memcpy(destflat, srcflat+position, destwidth); - destflat += destwidth; - position += srcwidth; - } - - while (y++ < min(resizeheight, srcheight)) - memset(destflat + (y * destwidth), *(destflat - 1), destwidth); -} diff --git a/src/r_data.h b/src/r_data.h index c528fcfe1..9af621142 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -103,10 +103,6 @@ boolean R_CheckIfPatch(lumpnum_t lump); void R_FlatPatch(patch_t *patch, UINT8 *flat); void R_FlatTexture(size_t tex, UINT8 *flat); -void R_CropFlat(UINT8 *srcflat, UINT8 *destflat, - UINT16 srcwidth, UINT16 srcheight, - UINT16 resizewidth, UINT16 resizeheight, - UINT16 destwidth, UINT16 destheight); extern INT32 numtextures; From 5047f4e7f08f10410f970ea50de745be7a73edb2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 25 Jun 2019 14:58:34 -0300 Subject: [PATCH 013/133] Fix slope flat offsets --- src/r_plane.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index f79a5f90a..e982f41d6 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -972,6 +972,7 @@ void R_DrawSinglePlane(visplane_t *pl) if (ds_powersoftwo) { // But xoffs and yoffs are zero..... ???!?!?!???!?!?! + // (Except when flat alignment is involved) xoffs &= ((1 << (32-nflatshiftup))-1); yoffs &= ((1 << (32-nflatshiftup))-1); @@ -986,9 +987,10 @@ void R_DrawSinglePlane(visplane_t *pl) } else { - // The origin vector is a vertex from whatever linedef defined this slope - xoffs = -pl->slope->o.x; - yoffs = pl->slope->o.y; + // Whoops, this is actually incorrect behaviour. + // Keep xoffs and yoffs as they are if this flat has offsets + //xoffs = -pl->slope->o.x; + //yoffs = pl->slope->o.y; } vx = FIXED_TO_FLOAT(pl->viewx+xoffs); From afa6afa593d8aa721928c044e1c4f6f200649210 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 28 Jun 2019 19:43:37 -0300 Subject: [PATCH 014/133] something something memory leaks --- src/r_data.c | 4 ++-- src/r_plane.c | 35 ++++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 9e9e70bc3..0e15c4689 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1916,7 +1916,7 @@ static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) return NULL; // Convert the image to 8bpp - flat = Z_Malloc(width * height, PU_STATIC, NULL); + flat = Z_Malloc(width * height, PU_LEVEL, NULL); memset(flat, TRANSPARENTPIXEL, width * height); for (y = 0; y < height; y++) { @@ -1944,7 +1944,7 @@ static UINT8 *PNG_GetAlphaMask(UINT8 *png, size_t size) return NULL; // Convert the image to 8bpp - mask = Z_Malloc(width * height, PU_STATIC, NULL); + mask = Z_Malloc(width * height, PU_LEVEL, NULL); memset(mask, 0, width * height); for (y = 0; y < height; y++) { diff --git a/src/r_plane.c b/src/r_plane.c index 1cbdc4b8b..4cfa4a49c 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -714,8 +714,9 @@ void R_CheckFlatLength(size_t size) } } -static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng) +static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng) { + UINT8 *flat; textureflat_t *texflat = &texflats[levelflat->texturenum]; patch_t *patch = NULL; boolean texturechanged = (leveltexture ? (levelflat->texturenum != levelflat->lasttexturenum) : false); @@ -725,7 +726,7 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean { if (texflat != NULL && texflat->flat) { - ds_source = texflat->flat; + flat = texflat->flat; ds_flatwidth = texflat->width; ds_flatheight = texflat->height; texturechanged = false; @@ -746,8 +747,11 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean texflat->flat = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL); memset(texflat->flat, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight); R_TextureToFlat(levelflat->texturenum, texflat->flat); + flat = texflat->flat; - ds_source = texflat->flat; + levelflat->flatpatch = flat; + levelflat->width = ds_flatwidth; + levelflat->height = ds_flatheight; } else { @@ -761,7 +765,7 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean if (levelflat->flatpatch == NULL) { lumpnum_t redflr = W_CheckNumForName("REDFLR"); - levelflat->flatpatch = (UINT8 *)W_CacheLumpNum(redflr, PU_STATIC); + levelflat->flatpatch = (UINT8 *)W_CacheLumpNum(redflr, PU_CACHE); R_CheckFlatLength(W_LumpLength(redflr)); R_CheckPowersOfTwo(); } @@ -785,12 +789,12 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean memset(levelflat->flatpatch, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight); R_PatchToFlat(patch, levelflat->flatpatch); } - ds_source = levelflat->flatpatch; + flat = levelflat->flatpatch; } } else { - ds_source = levelflat->flatpatch; + flat = levelflat->flatpatch; ds_flatwidth = levelflat->width; ds_flatheight = levelflat->height; @@ -799,10 +803,12 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean } levelflat->lasttexturenum = levelflat->texturenum; + return flat; } void R_DrawSinglePlane(visplane_t *pl) { + UINT8 *flat; INT32 light = 0; INT32 x; INT32 stop, angle; @@ -960,16 +966,25 @@ void R_DrawSinglePlane(visplane_t *pl) // Check if the flat is actually a wall texture. if (levelflat->texturenum != 0 && levelflat->texturenum != -1) - R_GetPatchFlat(levelflat, true, false); + flat = R_GetPatchFlat(levelflat, true, false); // Maybe it's just a patch, then? else if (R_CheckIfPatch(levelflat->lumpnum)) - R_GetPatchFlat(levelflat, false, false); + flat = R_GetPatchFlat(levelflat, false, false); // Maybe it's a PNG?! else if (R_IsLumpPNG(ds_source, size)) - R_GetPatchFlat(levelflat, false, true); + flat = R_GetPatchFlat(levelflat, false, true); // It's a raw flat. else + { R_CheckFlatLength(size); + flat = ds_source; + } + + Z_ChangeTag(ds_source, PU_CACHE); + ds_source = flat; + + if (ds_source == NULL) + return; // Check if the flat has dimensions that are powers-of-two numbers. if (R_CheckPowersOfTwo()) @@ -1202,8 +1217,6 @@ using the palette colors. } } #endif - - Z_ChangeTag(ds_source, PU_CACHE); } void R_PlaneBounds(visplane_t *plane) From 3ffb7b619241c950f4b1fab9f250d4f31a9a763a Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 16 Jul 2019 19:18:13 -0400 Subject: [PATCH 015/133] New icons Also update IMG_xpm.c --- src/sdl/IMG_xpm.c | 64 +++++++---- src/sdl/SDL_icon.xpm | 240 ++++++++++++++---------------------------- src/sdl/Srb2SDL.ico | Bin 372798 -> 63946 bytes src/win32/Srb2win.ico | Bin 372798 -> 63946 bytes 4 files changed, 122 insertions(+), 182 deletions(-) diff --git a/src/sdl/IMG_xpm.c b/src/sdl/IMG_xpm.c index af76ec1dd..59cca934d 100644 --- a/src/sdl/IMG_xpm.c +++ b/src/sdl/IMG_xpm.c @@ -1,6 +1,6 @@ /* SDL_image: An example image loading library for use with SDL - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -48,7 +48,7 @@ // SDLCALL terms removed from original SDL_image declarations int IMG_isXPM(SDL_RWops *src); SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src); -SDL_Surface *IMG_ReadXPMFromArray(const char **xpm); +SDL_Surface *IMG_ReadXPMFromArray(char **xpm); #define IMG_SetError SDL_SetError #define IMG_GetError SDL_GetError #endif @@ -79,7 +79,7 @@ int IMG_isXPM(SDL_RWops *src) #define STARTING_HASH_SIZE 256 struct hash_entry { - const char *key; + char *key; Uint32 color; struct hash_entry *next; }; @@ -110,7 +110,7 @@ static struct color_hash *create_colorhash(int maxnum) /* we know how many entries we need, so we can allocate everything here */ - hash = (struct color_hash *)SDL_malloc(sizeof *hash); + hash = (struct color_hash *)SDL_calloc(1, sizeof(*hash)); if (!hash) return NULL; @@ -119,15 +119,29 @@ static struct color_hash *create_colorhash(int maxnum) ; hash->size = s; hash->maxnum = maxnum; + bytes = hash->size * sizeof(struct hash_entry **); - hash->entries = NULL; /* in case malloc fails */ - hash->table = (struct hash_entry **)SDL_malloc(bytes); + /* Check for overflow */ + if ((bytes / sizeof(struct hash_entry **)) != hash->size) { + IMG_SetError("memory allocation overflow"); + SDL_free(hash); + return NULL; + } + hash->table = (struct hash_entry **)SDL_calloc(1, bytes); if (!hash->table) { SDL_free(hash); return NULL; } - SDL_memset(hash->table, 0, bytes); - hash->entries = (struct hash_entry *)SDL_malloc(maxnum * sizeof(struct hash_entry)); + + bytes = maxnum * sizeof(struct hash_entry); + /* Check for overflow */ + if ((bytes / sizeof(struct hash_entry)) != maxnum) { + IMG_SetError("memory allocation overflow"); + SDL_free(hash->table); + SDL_free(hash); + return NULL; + } + hash->entries = (struct hash_entry *)SDL_calloc(1, bytes); if (!hash->entries) { SDL_free(hash->table); SDL_free(hash); @@ -150,7 +164,7 @@ static int add_colorhash(struct color_hash *hash, } /* fast lookup that works if cpp == 1 */ -#define QUICK_COLORHASH(hash, key) ((hash)->table[*(const Uint8 *)(key)]->color) +#define QUICK_COLORHASH(hash, key) ((hash)->table[*(Uint8 *)(key)]->color) static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp) { @@ -174,14 +188,16 @@ static void free_colorhash(struct color_hash *hash) } } +#define EXTENDED_XPM_COLORS + /* * convert colour spec to RGB (in 0xrrggbb format). * return 1 if successful. */ -static int color_to_rgb(const char *spec, int speclen, Uint32 *rgb) +static int color_to_rgb(char *spec, int speclen, Uint32 *rgb) { /* poor man's rgb.txt */ - static struct { const char *name; Uint32 rgb; } known[] = { + static struct { char *name; Uint32 rgb; } known[] = { { "none", 0xFFFFFFFF }, { "black", 0x000000 }, { "white", 0xFFFFFF }, @@ -895,7 +911,7 @@ static int color_to_rgb(const char *spec, int speclen, Uint32 *rgb) *rgb = (Uint32)SDL_strtol(buf, NULL, 16); return 1; } else { - size_t i; + int i; for (i = 0; i < SDL_arraysize(known); i++) { if (SDL_strncasecmp(known[i].name, spec, speclen) == 0) { *rgb = known[i].rgb; @@ -912,14 +928,14 @@ static int color_to_rgb(const char *spec, int speclen, Uint32 *rgb) static char *linebuf; static int buflen; -static const char *error; +static char *error; /* * Read next line from the source. * If len > 0, it's assumed to be at least len chars (for efficiency). * Return NULL and set error upon EOF or parse error. */ -static const char *get_next_line(const char ***lines, SDL_RWops *src, int len) +static char *get_next_line(char ***lines, SDL_RWops *src, int len) { char *linebufnew; @@ -991,7 +1007,7 @@ do { \ } while (0) /* read XPM from either array or RWops */ -static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) +static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src) { Sint64 start = 0; SDL_Surface *image = NULL; @@ -1003,8 +1019,8 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) struct color_hash *colors = NULL; SDL_Color *im_colors = NULL; char *keystrings = NULL, *nextkey; - const char *line; - const char ***xpmlines = NULL; + char *line; + char ***xpmlines = NULL; int pixels_len; error = NULL; @@ -1035,6 +1051,11 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) goto done; } + /* Check for allocation overflow */ + if ((size_t)(ncolors * cpp)/cpp != ncolors) { + error = "Invalid color specification"; + goto done; + } keystrings = (char *)SDL_malloc(ncolors * cpp); if (!keystrings) { error = "Out of memory"; @@ -1066,7 +1087,7 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) goto done; } for (index = 0; index < ncolors; ++index ) { - const char *p; + char *p; line = get_next_line(xpmlines, src, 0); if (!line) goto done; @@ -1076,7 +1097,7 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) /* parse a colour definition */ for (;;) { char nametype; - const char *colname; + char *colname; Uint32 rgb, pixel; SKIPSPACE(p); @@ -1102,8 +1123,9 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) c->g = (Uint8)(rgb >> 8); c->b = (Uint8)(rgb); pixel = index; - } else + } else { pixel = rgb; + } add_colorhash(colors, nextkey, cpp, pixel); nextkey += cpp; if (rgb == 0xffffffff) @@ -1168,7 +1190,7 @@ SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) return load_xpm(NULL, src); } -SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) +SDL_Surface *IMG_ReadXPMFromArray(char **xpm) { if (!xpm) { IMG_SetError("array is NULL"); diff --git a/src/sdl/SDL_icon.xpm b/src/sdl/SDL_icon.xpm index 1d0f9d314..ccd39f12c 100644 --- a/src/sdl/SDL_icon.xpm +++ b/src/sdl/SDL_icon.xpm @@ -1,163 +1,81 @@ /* XPM */ -const char * SDL_icon_xpm[] = { -"96 96 64 1", +static char * SDL_icon_xpm[] = { +"32 32 46 1", " c None", -". c #040656", -"+ c #0100B2", -"@ c #04056E", -"# c #0000BD", -"$ c #0B0C09", -"% c #0B0D26", -"& c #090C42", -"* c #060AA7", -"= c #1604DA", -"- c #020CD5", -"; c #100F8D", -"> c #040DE4", -", c #11129B", -"' c #1D1A83", -") c #2A10FD", -"! c #1318FA", -"~ c #25225B", -"{ c #252271", -"] c #312E2B", -"^ c #33334D", -"/ c #363775", -"( c #3D3B69", -"_ c #3A3B8B", -": c #373AFF", -"< c #4142AA", -"[ c #4B4864", -"} c #4D4B4A", -"| c #60492F", -"1 c #4F4C57", -"2 c #4A4A9E", -"3 c #4F4E85", -"4 c #474ADE", -"5 c #4E4FFE", -"6 c #5D5CB3", -"7 c #686663", -"8 c #666682", -"9 c #676875", -"0 c #66659E", -"a c #8B6538", -"b c #6465D5", -"c c #7F694F", -"d c #6767FF", -"e c #7272FF", -"f c #91795C", -"g c #7677FD", -"h c #828396", -"i c #A78153", -"j c #888989", -"k c #8D897E", -"l c #9190FD", -"m c #CA9048", -"n c #C09968", -"o c #A9A8A1", -"p c #A6A8B0", -"q c #B0B1FB", -"r c #EEAC61", -"s c #E3B478", -"t c #C3C4BE", -"u c #FFC68C", -"v c #FCCD90", -"w c #D4D7D3", -"x c #E3E5E0", -"y c #FCFFFB", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ttj7777777joot ", -" 9hh8830000088hh9 ", -" 9888(//__-*{^kt ", -" &,5b60^ (02*{} ", -" tp,-)!5egb3} ~_<4dgggeeeeeeeeeeeeeegb6/_2[amusf'#!<_'>))))))))))))!)>+{~ ", -" p;-))!5gb2^^'#5eggeeeeeeeeeeeeeeegg6/_23amrusi{#!+;;>))))))))))))))!!-'8p ", -" tp'#!)):d6(@*>5egeeeeeeeeeeeeeeeegg6_/<(amrrvvn{+)-,;>))))))!!!!!!)))!!>,~j ", -" p;#!))-'{'+-5eggeeeeeeeeeeeeeeeegb222(cmrruvvn{+)>,@>!)!!)!!>>>>======>-,/8 ", -" ;#)!-*.;-!5eggeeeeeeeeeeeeeeeegb2_<6|mrrsvvvn{+)!,.-!!!!>>=--######+++-#@(k ", -" h@-)+@.*>!5egeeeeeeeeeeeeeeeeeegb_>--###++++++###+;@{(9j ", -" kh,#+@@,>!:dggeeeeeeeeeeeeeeeeeeebbb_]mrruuvvsf'#)!*.+-###+++++++##+*;'3(&^9 ", -" 8*,@@*)):dggeeeeeeeeeeeeeeeeeeeeggg<(|iruvvvsc,=!!*.;*++++++++###+,@&1o ", -" 8@@@-!)!5eeeeeeeeeeeeeeeeeeeeeeeeeggb2[csvvvn^#)!!+@;*#+++++###*@~[ ", -" 9&@*!)):5geeeeeeeeeeeeeeeeeeeeeeeeegge637nsvf{>))!+;;*-######*;{.^ ", -" 9%;!!)):dgeeeeeeeeeeeeeeeeeeeeeeeeeeeggb_1ir7;>))!+;;,++++++*'(} ", -" 9{+!))!5egeeeeeeeeeeeeeeeeeddddeeeeeeeege2}|~#!))!#;@...@@@.^hp ", -" 8,=!))):dggeeeeeeeeeeeeeeeeggggeeeeeeeeggb_~,>!))!+@@@;;;;@&^o ", -" }(-)))))!:eegeeeeeeeeeeeeeegllllgeeeeeeeegd5+=))))!+;,#>--#,'/hj ", -" o8.>))))))!:dgggeeeeeeeeeeellqqqqlgeeeeggg5:!!!)))))-*+>)!:55db631 ", -" p8<*!)))))))!:5deggggggeeeegqqqqqqqqlggged5:!))))))))>->!!:5ddeegb3/ ", -" oh'#!))))))))))!:ddeeeeeeeeglqqqqqqqqlgedd:!)))))))))))))!:dggggeggg239 ", -" ^*>!))!)))))))))!::55dddeegglll600333_4:!!)))))))))))))):dggeeeeeeggb6(9o ", -" ~+=-+#>))))))))))!!!:::::5554<3889988[/,=)))))))))))))):5gggeeeeeeeggb6087 ", -" ~**@~'+>!))))))))))))))))!!>*{1kkooook7(,-!)))))))))))!:5deeeeeeeeeeeggb289 ", -" ~,'1o7(*>!))))))))))))))))=,[jtttwxxxwto^;>!))))))))))!!!::5deggeeeeeeegbb3] ", -" ~@/oxt7'#))))))))))))))))=,3ktwxxyyyyyyxk/+!))))))))))))))!:::5degggeeegggb3^ ", -" ^&8xyyt^,)))))))))))))))>,3otwxyyyyyyyyyxh'>)))))))))))))))))):5ddeeeeeeeggb3^ ", -" 771pyyyx7'=!)))))))))))!!#(jtxxyyyyyyyyyyyt3-)))))))))))))))))))!!::degggeeegb2[o ", -" 77tyyyxk/+!!)))))))))))-;9owxyyyyyyyyyyyywh*>)))))))))))))))))))))!::5ddgggggb68j ", -" owyyyyt8;>))))))))))))*(otwyyyyyyyyyyyyyxp'-)))))))))))))))))))))))!!:5deeeggg_8j ", -" jtxyyyyxh'>)))))))))!!#_ktxyyyyyyyyyyyyyyyt_+))))))))))))))))))))))))))!!:5deggg63j ", -" 7jwyyyyyyp/=))))))))))>,3owxyyyyyyyyyyyyyyyw/+))))))))))))))))))))))))))))!::5degb689 ", -" 7xyyyyyyo[#))))))))))-/jtwyyyyyyyyyyyyyyyyw/*)))))))))))))))))))))))))))))))!:5dgg_/ ", -" }xyyyyyyt9*=))))))))=*9owyyyyyyyyyyyyyyyyyw/*)))))))))))))))))))))))))))))))))!!:5d3} ", -" }xyyyyyywj'#!))))))!#@7oxyyyyyyyyyyyyyyyyyw/*)))))))))))))))))))))))))))))))))))!!:4/7 ", -" 7xyyyyyyxj&,!!))))!!,%}oyyyyyyyyyyyyyyyyyyw/*))))))))))))))))))))))))))))))))))))))>487 ", -" 7xyyyyyywk$@!!)))!!-.$]oyyyyyyyyyyyyyyyyyyw/+))))))))))))))))))))))))))))))!!!!))))!>' ", -" }xyyyyyywj$&+!!)!)>;%$]jyyyyyyyyyyyyyyyyyyt{#)))))))))))))))))))))!!!!!!))!)!!!!!!))!#' ", -" 7xyyyyyyt7$%@-!)!>*[]$$jyyyyyyyyyyyyyyyyyxp;-))))))))))))))))))!!!!!!!!!!!!>>>>>>>>>>!,^ ", -" 7xyyyyyyt}$][;-)=,(o7$$7yyyyyyyyyyyyyyyyyxp,-)))))))))))!!!!)!!!!>>>>=-----########--=+'9 ", -" jwyyyyyyo}$}o(';@~7wj$$7yyyyyyyyyyyyyyyyywh*>)))))))))))!>>>=>=---#####+########+++***;@17 ", -" otxyyyyyt}$7t7}1}7kw7$$7yyyyyyyyyyyyyyyyyt0-)))))))))!!!>--####+++++++++++++##+***,;''.&] ", -" ooowyyyyyt}$}j7owwojo}$$jyyyyyyyyyyyyyyyyyp2>)))))))!!!=##++++++++++++++###+*;@.~[8[9hph ", -" ojtyyyyywj$$}jwyyxo}$$]jyyyyyyyyyyyyyyyyyp'>))))))!>>-#++++++++++++####+,;'_3/&^}77kot ", -" 7tyyyyyxo]$$oxyyyt]$$}tyyyyyyyyyyyyyyyyx0*!)))!!!>-#++++++++++++#+##+*;.&1ko ", -" 7tyyyyyyx7]}xyyyyxj}]oxyyyyyyyyyyyyyyyyp<=)!!!!>-#++++++++++++####*;.(8h ", -" owxyxxyytooywptwwtppxyyyyyyyyyyyyyyyxp3,-=!)!>-#++++++++++###+*,'_{&1k ", -" jtwwttwtwwtj7kjowxyyyyyyyyyyyyyyyyxt7~'',+>=#+++++++++++###*;@&^j ", -" ]joojj7}]}]|innfc7jtwyyyyyyyyyyyxtjcfnnnf[@*#+++++++++###+@.&%% ", -" ]$}77}}$$$$]fsssnnifkkotwwwwwwwtpjkfinvvvsi}@*#++++++###*;@.@@&[ ", -" o7$]]]]]$$]|isvvvvvusifckopppopok7cisvvvvvvvn(,#++++++#+*@.&@*#;3o ", -" }}$]|||fnnsvvvuvvvuuvvsniffffffnnsvvvvuuuvvvc{*+#++##*@&.@*+#--<7 ", -" }]cninsuvvvvuuuuuuvvvvusnnnnnssuvvvvvuuuuvvc~*+#+++*@.@;*##=>>,^ ", -" 7fvvvvvvuuuuuuuuuuuuvvvvvvvvvvvuuuuuuuuuvvc~*+#+#+,.@*###->!!*~ ", -" pkivvvvuuuuuuuuuuuuuuuvvvvvvvvuuuvsnsuuuvvf~*+#++++*+++->!!)!#. ", -" kfsuvvuuuuuuuuuuuuuuuuuuuuuuuuuvvnfsuvuvvc{++#++++###->!!))!-;h ", -" kisvvvuuuuuuuuuuuuuuuuuuuuuuuvvvicsvvvvs1@##+++++++#>!!))))=,ho ", -" 7imuvvvuuuuuuuuuuuuuuuuuuuuvusfcivvuvvn~;##+++++++#>!!))))!#8k ", -" cimruuuuuvuuuuuuuuuuuuuuuuvsnfisuvvvsc@*#+++++++++#>!!))))-3} ", -" 7amrruuuuuuuuuuuuuuuuuuuuvsnnsvvuvvi^,##++++++++++#>!!)))>/^ ", -" kfamrruuuuvvvuuuuuuuuuuuuuvvvvvvvn1@+#++++++++++++#>!)))>{~ ", -" 7|iimrrruuuuuuuuuuuuuuuuvvvvuusn1'+#########++++++->!))>; ", -" 7cammrrrrruuuuuuvvvvvuuuuurrm|.*-#+#######+###+++->!!!*' ", -" ookcaimmrrrrrruuuuurrrrrmi|]%.@@@@@;,*,*+########->!!*6o ", -" p7}|ainiimmmmmmmmmmminnia|$%.....{3322_{''',,**+#=!!#6k ", -" j7||aaiiiiiaa||7j ookok711^&.';,*+=!>> c #1E1AED", +", c #1B1CFE", +"' c #272576", +") c #313179", +"! c #3A3AB1", +"~ c #3A3AFF", +"{ c #434497", +"] c #4F4AAE", +"^ c #4748FE", +"/ c #494DE8", +"( c #7A5137", +"_ c #5E57A7", +": c #5957C4", +"< c #616360", +"[ c #855E93", +"} c #796979", +"| c #9C6473", +"1 c #6D6EF4", +"2 c #7171FF", +"3 c #817F9D", +"4 c #B37C5A", +"5 c #898A8D", +"6 c #A28572", +"7 c #A3829B", +"8 c #8988FF", +"9 c #C39D82", +"0 c #ABADAB", +"a c #DCA57C", +"b c #ABAAFE", +"c c #C1C3C0", +"d c #F7C095", +"e c #CFD1CE", +"f c #DDE0DD", +"g c #FAFCF9", +" ", +" {]]]]]]) ", +" {:1222222221::) ", +" :1222222222^^>,,>% ", +" ' ]122222222:]>,,;=%$& ", +" @~] :222222221://-=%%%#. ", +" #>^{122222222:1][~&%%%@ ", +" #>=122221221:/|a4,&%$& ", +" #-!22228bb12/4ad9,&$+ ", +" ##^2221bbb2~,!ad7,@'{ ", +" )!,/22281^,,,,:d_,-221:) ", +" /,;,,>,,-_!;,,,[=>=~2222: ", +" {=,,,,;3fgg0;,,,,;,,,~^221{ ", +" 3_,,,>5ggggg3,,,,,,,,,,,>^2] ", +" 05,,,_fgg0egc>,,,,,,,,,,,,,~! ", +" 00>,>0ggf00gf;,,,,,,,,,,,,,,,- ", +" 5e%,!fggf55gf=,,,,,,,,,,>>>>,, ", +" ==-%%%%%%$$#", +" f*@cgggg*5g0>,>-%%%%%%$@@+ ", +"5e< ", +" 4ddddda9a6$#%%%%=,,- ", +" 4addddda*#%%%%%%>,; ", +" (444 +@$%%%-,, ", +" &$%%=,$ ", +" &$%>- ", +" +#-= ", +" @- ", +" & ", +" "}; diff --git a/src/sdl/Srb2SDL.ico b/src/sdl/Srb2SDL.ico index 700276fd4b9ac2810a6981eb054921f3708c702b..3b37433dbd0aeb1315eaae48e5a2831de7e305e7 100644 GIT binary patch literal 63946 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 literal 372798 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 G1OE?SzcGja diff --git a/src/win32/Srb2win.ico b/src/win32/Srb2win.ico index 700276fd4b9ac2810a6981eb054921f3708c702b..3b37433dbd0aeb1315eaae48e5a2831de7e305e7 100644 GIT binary patch literal 63946 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 literal 372798 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 G1OE?SzcGja From 181ecee202dca4d8a24ec27f38e4b30e61c7f1f5 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 16 Jul 2019 19:26:16 -0400 Subject: [PATCH 016/133] Let's not use this --- src/sdl/IMG_xpm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sdl/IMG_xpm.c b/src/sdl/IMG_xpm.c index 59cca934d..51cedfd6d 100644 --- a/src/sdl/IMG_xpm.c +++ b/src/sdl/IMG_xpm.c @@ -188,8 +188,6 @@ static void free_colorhash(struct color_hash *hash) } } -#define EXTENDED_XPM_COLORS - /* * convert colour spec to RGB (in 0xrrggbb format). * return 1 if successful. From 64bb70bef4d2f02c3bc12533b8364d2f89a8d9d1 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 14 Jul 2019 14:55:04 -0400 Subject: [PATCH 017/133] Fix crash with GME sounds when being freed --- src/sdl/mixer_sound.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 004c60605..6d485179a 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -390,7 +390,7 @@ void *I_GetSfx(sfxinfo_t *sfx) gme_track_info(emu, &info, 0); len = (info->play_length * 441 / 10) << 2; - mem = malloc(len); + mem = Z_Malloc(len, PU_SOUND, 0); gme_play(emu, len >> 1, mem); gme_free_info(info); gme_delete(emu); @@ -463,7 +463,7 @@ void *I_GetSfx(sfxinfo_t *sfx) gme_track_info(emu, &info, 0); len = (info->play_length * 441 / 10) << 2; - mem = malloc(len); + mem = Z_Malloc(len, PU_SOUND, 0); gme_play(emu, len >> 1, mem); gme_free_info(info); gme_delete(emu); From 9813cbc8577991e232655468608ce73fe86b91e2 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 27 Jul 2019 01:13:35 -0400 Subject: [PATCH 018/133] More icon stuff --- srb2.png | Bin 6208 -> 25245 bytes src/sdl/SDL_icon.xpm | 174 ++++++++++++++++++++++++------------------- src/sdl/i_video.c | 2 +- src/sdl/srb2icon.png | Bin 11668 -> 0 bytes src/win32/Srb2win.rc | 13 ++-- 5 files changed, 105 insertions(+), 84 deletions(-) delete mode 100644 src/sdl/srb2icon.png diff --git a/srb2.png b/srb2.png index 72a08f6648b8c8849d5804889977a412b35e6deb..3bbe2c3e66af543be6de806d8d893735e10e4062 100644 GIT binary patch literal 25245 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 AS^xk5 literal 6208 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 diff --git a/src/sdl/SDL_icon.xpm b/src/sdl/SDL_icon.xpm index ccd39f12c..c5c957468 100644 --- a/src/sdl/SDL_icon.xpm +++ b/src/sdl/SDL_icon.xpm @@ -1,81 +1,99 @@ /* XPM */ static char * SDL_icon_xpm[] = { -"32 32 46 1", +"64 64 32 1", " c None", -". c #000033", -"+ c #000045", -"@ c #00006C", -"# c #01007E", -"$ c #000193", -"% c #00009F", -"& c #060766", -"* c #0F0F10", -"= c #0C11CC", -"- c #0D13B8", -"; c #1415E0", -"> c #1E1AED", -", c #1B1CFE", -"' c #272576", -") c #313179", -"! c #3A3AB1", -"~ c #3A3AFF", -"{ c #434497", -"] c #4F4AAE", -"^ c #4748FE", -"/ c #494DE8", -"( c #7A5137", -"_ c #5E57A7", -": c #5957C4", -"< c #616360", -"[ c #855E93", -"} c #796979", -"| c #9C6473", -"1 c #6D6EF4", -"2 c #7171FF", -"3 c #817F9D", -"4 c #B37C5A", -"5 c #898A8D", -"6 c #A28572", -"7 c #A3829B", -"8 c #8988FF", -"9 c #C39D82", -"0 c #ABADAB", -"a c #DCA57C", -"b c #ABAAFE", -"c c #C1C3C0", -"d c #F7C095", -"e c #CFD1CE", -"f c #DDE0DD", -"g c #FAFCF9", -" ", -" {]]]]]]) ", -" {:1222222221::) ", -" :1222222222^^>,,>% ", -" ' ]122222222:]>,,;=%$& ", -" @~] :222222221://-=%%%#. ", -" #>^{122222222:1][~&%%%@ ", -" #>=122221221:/|a4,&%$& ", -" #-!22228bb12/4ad9,&$+ ", -" ##^2221bbb2~,!ad7,@'{ ", -" )!,/22281^,,,,:d_,-221:) ", -" /,;,,>,,-_!;,,,[=>=~2222: ", -" {=,,,,;3fgg0;,,,,;,,,~^221{ ", -" 3_,,,>5ggggg3,,,,,,,,,,,>^2] ", -" 05,,,_fgg0egc>,,,,,,,,,,,,,~! ", -" 00>,>0ggf00gf;,,,,,,,,,,,,,,,- ", -" 5e%,!fggf55gf=,,,,,,,,,,>>>>,, ", -" ==-%%%%%%$$#", -" f*@cgggg*5g0>,>-%%%%%%$@@+ ", -"5e< ", -" 4ddddda9a6$#%%%%=,,- ", -" 4addddda*#%%%%%%>,; ", -" (444 +@$%%%-,, ", -" &$%%=,$ ", -" &$%>- ", -" +#-= ", -" @- ", -" & ", -" "}; +". c #000271", +"+ c #03035D", +"@ c #00009F", +"# c #0A0A1B", +"$ c #08058E", +"% c #060E4C", +"& c #11110E", +"* c #101339", +"= c #0D11CC", +"- c #1B1CFD", +"; c #342B24", +"> c #2325EC", +", c #3C3883", +"' c #3D3A9E", +") c #5B5170", +"! c #4B4CFF", +"~ c #795339", +"{ c #5E5B5C", +"] c #5F5ED3", +"^ c #5E5EFB", +"/ c #7271FF", +"( c #B37F5D", +"_ c #8F8883", +": c #8887FF", +"< c #D59E76", +"[ c #ABABA9", +"} c #A9AAFF", +"| c #C1C3C1", +"1 c #FAC296", +"2 c #D4D6D3", +"3 c #F9FCF8", +" ", +" ", +" #***,,,**** ", +" *,,]]]]]]]]]]]]]',,** ", +" *,']//////////////////]]',* ", +" *,']/////////////////////////]'% ", +" *,]////////////////////^^!!>>>>>>>$+ ", +" *,]////////////////////!>---------->=@% ", +" * ,]///////////////////]^>------->==@@@$.# ", +" +', *']//////////////////],,,=---->=@@@@@$.% ", +" #.=^'* ,]//////////////////],']^]$--=@@@@@@@$+# ", +" %$=-^'* ,]/////////////////],]/!>-^'=@@@@@@@$.% ", +" +$=->/,*,//////////////////]'/^!,$-!,$@@@@@@$+* ", +" +@=--!''/////////////////]']^!,(()->%$@@@@@$+# ", +" +@=--='/////////////////]']^${(<<)->,$@@@@$% ", +" +@=->']/////////:::////]]/^'(<111)->,$@@@$% ", +" #+@@>$]////////::}}}://///!,(<1111)--%$@@.% ", +" #+@@$$^////////:}}}}}://^>$(<<1111)--+$@.% ", +" +@$.>^///////:}}}}}}:/^>->,(<111<'--+$$*# ", +" +$.=-!///////:}}}}}:^!-----@(111<@--+$,'],,* ", +" %+%=->^///////:}}}:!--------@(11(=--$=^////],* ", +" ,]]'>->^//////^^!!-----------'<1_>--@-!//////]'* ", +" '!->@--->>>>>>--->===>--------)<,-->@->^///////]', ", +" *$--->----------='){__{'>------>'=--=@-->!^///////],* ", +" %$.=---------->$)[22332[)=----------=>----->^^//////], ", +" %$_,--------->'_|3333333['----------=--------->!^////],# ", +" *'[{=--------'_2333333333_=---------------------->!^///,* ", +" #)[_@-------@_|33333333332,------------------------->!^/'* ", +" #)2[$------=)|333332|23333{>--------------------------->^'* ", +" {2|,------$[233333___3333_=----------------------------->$ ", +" ;22)=---->)|333332{2_2333[@-------------------------------$ ", +" &22{@----$_233333|{2||333|'--------------------------------$ ", +" &|3_.----,|333333[;2|[333|'--------------------------------=+ ", +" [3_%=--={2333333[&___333|'-------------------->>>====>>----@ ", +" _3[#$=@.[2333333[&&&_333[$------------->>==@@@@@@@@@@@@@@@==+", +" {3|;+$$)|3333333[&&&[333_=-------->==@@@@@@@@@@@@@@@$$$$.+++%", +" {23{*$${23333333|;&&|332)>----->=@@@@@@@@@@@@@@$$$.++%** ", +";{{;[3{&*)[333333333{&&|332,=---==@@@@@@@@@@@@$$.++%* ", +"{22_{|[;_|2333333333_&;233_$@@@@@@@@@@@@@@@@$$+%* ", +"&_|2{;{{[233333333332_[33[,$@@@@@@@@@@@@@$$+%# ", +" &;{&&&;~(_|3333333333332)$@@@@@@@@@@@@$.+%# ", +" &&&&&;(11([33333333332{$@@@@@@@@@@@$...$@$* ", +" &~((1111<[333333332{%.$@@@@@@@@@$$$$@=--$ ", +" ~<<11111<[33333|[_(<~,$@@@@@@@@@@@@@>-->. ", +" ;(<111111<(____(11111(+@@@@@@@@@@@@=----=% ", +" ~(<11111111<11111<(<<;$@@$$@@@@@@@=-----. ", +" ~(<1111111111111(~<1{$$$.$@@@@@@@=-----= ", +" ~(<1111111<<(((<11<*$+.$@@@@@@@@@>---->+ ", +" ;(<1111111<<1111<~%+$@@@@@@@@@@@=-----$ ", +" ~(<<111111111(~&*+$$$@@@@@@@@@@=----=% ", +" ;~((<<<<(~~; *%+$$@@@@@@@@@>----+ ", +" ;;; #%+$$@@@@@@@----. ", +" *+$$@@@@@=---@ ", +" *+$@@@@@>--= ", +" *.$@@@@-->% ", +" #%.$@@=->+ ", +" *+$@@>-$ ", +" %$@=-$ ", +" %.@>@ ", +" +=@ ", +" .. ", +" * ", +" ", +" "}; diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index b4f1a2a9d..ede7787f7 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -41,7 +41,7 @@ #ifdef HAVE_IMAGE #include "SDL_image.h" -#elif 1 +#elif defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) // Windows doesn't need this, as SDL will do it for us. #define LOAD_XPM //I want XPM! #include "IMG_xpm.c" //Alam: I don't want to add SDL_Image.dll/so #define HAVE_IMAGE //I have SDL_Image, sortof diff --git a/src/sdl/srb2icon.png b/src/sdl/srb2icon.png deleted file mode 100644 index cdee18a8412313410fb4f0f0a132b710c1670c54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11668 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 literal 424760 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

VubN zPF1m>AwaBU1Q4fco^TflS|)OK(AyBF-o4T4#F@*Leij92@l;y)-u|w2?xy z?VM*{v7Bv}uCrd`Hb~eVLfa{{1426@w03yLu|9Iu=nbLA@7me_#Ck&2%+}y7EAQFRG z&h1(N4%Ot~XgRlQS-=dTPUapVLvXvJxgnQ^xD2})8Kq@tUP#M>=JL{kjvRXIo3DU0ZR5t|0B06;h44 zU2_}ir-?)oX{!!zukH|qJPWbkpOGR;~;{{$~$L zhK|3#ufTx*EKak}<+=d-;pkf0-6 zmnjC!!EJGTUe7U7e1_3Zb=7xu4K|eEXRv{IL_>yZZ_8t(A?eY9OEow37>CQh-@(k7 JUG*uY{vX;3zMB95 diff --git a/src/r_data.c b/src/r_data.c index 71c909b88..2c10e0143 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2603,17 +2603,40 @@ typedef struct { png_bytep buffer; png_uint_32 bufsize; png_uint_32 current_pos; -} png_ioread; +} png_io_t; static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length) { - png_ioread *f = png_get_io_ptr(png_ptr); + png_io_t *f = png_get_io_ptr(png_ptr); if (length > (f->bufsize - f->current_pos)) png_error(png_ptr, "PNG_IOReader: buffer overrun"); memcpy(data, f->buffer + f->current_pos, length); f->current_pos += length; } +typedef struct +{ + char name[4]; + void *data; + size_t size; +} png_chunk_t; + +static png_byte *chunkname = NULL; +static png_chunk_t chunk; + +static int PNG_ChunkReader(png_structp png_ptr, png_unknown_chunkp chonk) +{ + if (!memcmp(chonk->name, chunkname, 4)) + { + memcpy(chunk.name, chonk->name, 4); + chunk.size = chonk->size; + chunk.data = Z_Malloc(chunk.size, PU_STATIC, NULL); + memcpy(chunk.data, chonk->data, chunk.size); + return 1; + } + return 0; +} + static void PNG_error(png_structp PNG, png_const_charp pngtext) { CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext); @@ -2638,11 +2661,13 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, I #endif #endif - png_ioread png_io; + png_io_t png_io; png_bytep *row_pointers; - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, - PNG_error, PNG_warn); + png_byte grAb_chunk[5] = {'g', 'r', 'A', 'b', (png_byte)'\0'}; + png_voidp *user_chunk_ptr; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn); if (!png_ptr) { CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n"); @@ -2677,12 +2702,18 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, I png_io.current_pos = 0; png_set_read_fn(png_ptr, &png_io, PNG_IOReader); + memset(&chunk, 0x00, sizeof(png_chunk_t)); + chunkname = grAb_chunk; // I want to read a grAb chunk + + user_chunk_ptr = png_get_user_chunk_ptr(png_ptr); + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, PNG_ChunkReader); + png_set_keep_unknown_chunks(png_ptr, 2, chunkname, 1); + #ifdef PNG_SET_USER_LIMITS_SUPPORTED png_set_user_limits(png_ptr, 2048, 2048); #endif png_read_info(png_ptr, png_info_ptr); - png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); if (bit_depth == 16) @@ -2715,35 +2746,31 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, I // Read grAB chunk if (topoffset || leftoffset) { - UINT8 *header = png; - while (size--) - { - if (!memcmp(header, "grAb", 4)) - { - // The grAb chunk stores offsets as big-endian numbers. - #ifdef SRB2_BIG_ENDIAN - #define ENDIANESS(x) (x) - #else - #define ENDIANESS(x) ((x>>24)&0xff)|((x<<8)&0xff0000)|((x>>8)&0xff00)|((x<<24)&0xff000000) - #endif - // skip name - header += 4; - // read left offset - if (leftoffset != NULL) - *leftoffset = (INT16)ENDIANESS(*(INT32 *)header); - // read top offset - header += 4; - if (topoffset != NULL) - *topoffset = (INT16)ENDIANESS(*(INT32 *)header); - #undef ENDIANESS - break; - } - header++; - } + INT32 *offsets = (INT32 *)chunk.data; + + // The grAb chunk stores offsets as big-endian numbers. + #ifdef SRB2_BIG_ENDIAN + #define ENDIANESS(x) (x) + #else + #define ENDIANESS(x) ((x>>24)&0xff)|((x<<8)&0xff0000)|((x>>8)&0xff00)|((x<<24)&0xff000000) + #endif + + // read left offset + if (leftoffset != NULL) + *leftoffset = (INT16)ENDIANESS(*offsets); + offsets++; + + // read top offset + if (topoffset != NULL) + *topoffset = (INT16)ENDIANESS(*offsets); + + #undef ENDIANESS } // bye png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + if (chunk.data) + Z_Free(chunk.data); *w = (INT32)width; *h = (INT32)height; @@ -2920,7 +2947,7 @@ boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size) #endif #endif - png_ioread png_io; + png_io_t png_io; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn); From e3df9cc6b106566f3aaada857ce36f868ef5db5d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 11 Sep 2019 20:38:15 -0300 Subject: [PATCH 092/133] Crash prevention --- src/r_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_data.c b/src/r_data.c index 2c10e0143..485de3c40 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2744,7 +2744,7 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, I png_read_image(png_ptr, row_pointers); // Read grAB chunk - if (topoffset || leftoffset) + if ((topoffset || leftoffset) && (chunk.data != NULL)) { INT32 *offsets = (INT32 *)chunk.data; From 9006bdd6a3576e217875e365d160645f1fd04481 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 12 Sep 2019 12:52:25 +0100 Subject: [PATCH 093/133] I_Error if no frames are found for a loaded skin's SPR2_STND subspriteset, given this is what everything will default to if nothing else is provided, and I really don't wanna go across the code adding checks for sprite2s not existing (since R_GetSkinSprite2, under all circumstances other than this one, is capable of bouncing back). --- src/r_things.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/r_things.c b/src/r_things.c index bf4b3ca40..ea8b8b73c 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2871,6 +2871,8 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski for (sprite2 = 0; sprite2 < free_spr2; sprite2++) R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[sprite2], wadnum, *lump, *lastlump); + if (skin->sprites[0].numframes == 0) + I_Error("R_LoadSkinSprites: no frames found for sprite SPR2_%s\n", spr2names[0]); } // returns whether found appropriate property From a0ec86ce0159dd6a59921ddb7de6814b0e61ade4 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 12 Sep 2019 14:32:31 -0300 Subject: [PATCH 094/133] Fix powers-of-two checks --- src/r_plane.c | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 51a69336e..db5fb0f24 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -652,12 +652,18 @@ static void R_DrawSkyPlane(visplane_t *pl) boolean R_CheckPowersOfTwo(void) { - if (ds_flatwidth & (ds_flatwidth - 1)) - ds_powersoftwo = false; - else if (ds_flatheight & (ds_flatheight - 1)) - ds_powersoftwo = false; - else if (ds_flatwidth == ds_flatheight) + boolean wpow2 = (!(ds_flatwidth & (ds_flatwidth - 1))); + boolean hpow2 = (!(ds_flatheight & (ds_flatheight - 1))); + + // Initially, the flat isn't powers-of-two-sized. + ds_powersoftwo = false; + + // But if the width and height are powers of two, + // and are EQUAL, then it's okay :] + if ((ds_flatwidth == ds_flatheight) && (wpow2 && hpow2)) ds_powersoftwo = true; + + // Just return ds_powersoftwo. return ds_powersoftwo; } @@ -806,6 +812,7 @@ void R_DrawSinglePlane(visplane_t *pl) size_t size; ffloor_t *rover; levelflat_t *levelflat; + boolean rawflat = false; if (!(pl->minx <= pl->maxx)) return; @@ -968,6 +975,7 @@ void R_DrawSinglePlane(visplane_t *pl) // It's a raw flat. else { + rawflat = true; R_CheckFlatLength(size); flat = ds_source; } @@ -978,8 +986,11 @@ void R_DrawSinglePlane(visplane_t *pl) if (ds_source == NULL) return; - // Check if the flat has dimensions that are powers-of-two numbers. - if (R_CheckPowersOfTwo()) + // Raw flats always have dimensions that are powers-of-two numbers. + if (rawflat) + ds_powersoftwo = true; + // Otherwise, check if this texture or patch has such dimensions. + else if (R_CheckPowersOfTwo()) { R_CheckFlatLength(ds_flatwidth * ds_flatheight); if (spanfunc == basespanfunc) @@ -1116,26 +1127,27 @@ void R_DrawSinglePlane(visplane_t *pl) ds_sz.z *= focallengthf; // Premultiply the texture vectors with the scale factors +#define SFMULT 65536.f if (ds_powersoftwo) { -#define SFMULT 65536.f*(1< Date: Thu, 12 Sep 2019 16:03:44 -0300 Subject: [PATCH 095/133] Moved this macro --- src/m_swap.h | 42 ++++++++++++++++++++++++++---------------- src/r_data.c | 15 ++------------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/m_swap.h b/src/m_swap.h index 2d42f6138..4318ce7be 100644 --- a/src/m_swap.h +++ b/src/m_swap.h @@ -14,29 +14,39 @@ #ifndef __M_SWAP__ #define __M_SWAP__ -#include "endian.h" - // Endianess handling. // WAD files are stored little endian. +#include "endian.h" + +// Little to big endian #ifdef SRB2_BIG_ENDIAN -#define SHORT(x) ((INT16)(\ -(((UINT16)(x) & (UINT16)0x00ffU) << 8) \ -| \ -(((UINT16)(x) & (UINT16)0xff00U) >> 8))) \ + #define SHORT(x) ((INT16)(\ + (((UINT16)(x) & (UINT16)0x00ffU) << 8) \ + | \ + (((UINT16)(x) & (UINT16)0xff00U) >> 8))) \ -#define LONG(x) ((INT32)(\ -(((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \ -| \ -(((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \ -| \ -(((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \ -| \ -(((UINT32)(x) & (UINT32)0xff000000UL) >> 24))) + #define LONG(x) ((INT32)(\ + (((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \ + | \ + (((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \ + | \ + (((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \ + | \ + (((UINT32)(x) & (UINT32)0xff000000UL) >> 24))) #else -#define SHORT(x) ((INT16)(x)) -#define LONG(x) ((INT32)(x)) + #define SHORT(x) ((INT16)(x)) + #define LONG(x) ((INT32)(x)) +#endif + +// Big to little endian +#ifdef SRB2_LITTLE_ENDIAN + #define BIGENDIAN_LONG(x) ((INT32)((x>>24)&0xff)|((x<<8)&0xff0000)|((x>>8)&0xff00)|((x<<24)&0xff000000)) + #define BIGENDIAN_SHORT(x) ((INT16)((x>>8)|(x<<8))) +#else + #define BIGENDIAN_LONG(x) ((INT32)(x)) + #define BIGENDIAN_SHORT(x) ((INT16)(x)) #endif #endif diff --git a/src/r_data.c b/src/r_data.c index 485de3c40..172a61da5 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2747,24 +2747,13 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, I if ((topoffset || leftoffset) && (chunk.data != NULL)) { INT32 *offsets = (INT32 *)chunk.data; - - // The grAb chunk stores offsets as big-endian numbers. - #ifdef SRB2_BIG_ENDIAN - #define ENDIANESS(x) (x) - #else - #define ENDIANESS(x) ((x>>24)&0xff)|((x<<8)&0xff0000)|((x>>8)&0xff00)|((x<<24)&0xff000000) - #endif - // read left offset if (leftoffset != NULL) - *leftoffset = (INT16)ENDIANESS(*offsets); + *leftoffset = (INT16)BIGENDIAN_LONG(*offsets); offsets++; - // read top offset if (topoffset != NULL) - *topoffset = (INT16)ENDIANESS(*offsets); - - #undef ENDIANESS + *topoffset = (INT16)BIGENDIAN_LONG(*offsets); } // bye From 2a04ac69e187b3d8870e372284cb19481ac4b703 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 12 Sep 2019 16:12:31 -0300 Subject: [PATCH 096/133] () --- src/m_swap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_swap.h b/src/m_swap.h index 4318ce7be..3b50dc623 100644 --- a/src/m_swap.h +++ b/src/m_swap.h @@ -42,8 +42,8 @@ // Big to little endian #ifdef SRB2_LITTLE_ENDIAN - #define BIGENDIAN_LONG(x) ((INT32)((x>>24)&0xff)|((x<<8)&0xff0000)|((x>>8)&0xff00)|((x<<24)&0xff000000)) - #define BIGENDIAN_SHORT(x) ((INT16)((x>>8)|(x<<8))) + #define BIGENDIAN_LONG(x) ((INT32)(((x)>>24)&0xff)|(((x)<<8)&0xff0000)|(((x)>>8)&0xff00)|(((x)<<24)&0xff000000)) + #define BIGENDIAN_SHORT(x) ((INT16)(((x)>>8)|((x)<<8))) #else #define BIGENDIAN_LONG(x) ((INT32)(x)) #define BIGENDIAN_SHORT(x) ((INT16)(x)) From 86f96096238cb0b849dcb0524784200ed4b66e58 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 12 Sep 2019 17:06:57 -0700 Subject: [PATCH 097/133] Support W_VerifyFile on PK3 --- src/w_wad.c | 202 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 143 insertions(+), 59 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 2fda8674c..9dd5cb822 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1619,13 +1619,145 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5) #endif } +// Verify versions for different archive +// formats. checklist assumed to be valid. + +static int +W_VerifyName (const char *name, lumpchecklist_t *checklist, boolean status) +{ + size_t j; + for (j = 0; checklist[j].len && checklist[j].name; ++j) + { + if (( strncmp(name, checklist[j].name, + checklist[j].len) != false ) == status) + { + return true; + } + } + return false; +} + +static int +W_VerifyWAD (FILE *fp, lumpchecklist_t *checklist, boolean status) +{ + size_t i; + + // assume wad file + wadinfo_t header; + filelump_t lumpinfo; + + // read the header + if (fread(&header, 1, sizeof header, fp) == sizeof header + && header.numlumps < INT16_MAX + && strncmp(header.identification, "ZWAD", 4) + && strncmp(header.identification, "IWAD", 4) + && strncmp(header.identification, "PWAD", 4) + && strncmp(header.identification, "SDLL", 4)) + { + return true; + } + + header.numlumps = LONG(header.numlumps); + header.infotableofs = LONG(header.infotableofs); + + // let seek to the lumpinfo list + if (fseek(fp, header.infotableofs, SEEK_SET) == -1) + return true; + + for (i = 0; i < header.numlumps; i++) + { + // fill in lumpinfo for this wad file directory + if (fread(&lumpinfo, sizeof (lumpinfo), 1 , fp) != 1) + return true; + + lumpinfo.filepos = LONG(lumpinfo.filepos); + lumpinfo.size = LONG(lumpinfo.size); + + if (lumpinfo.size == 0) + continue; + + if (! W_VerifyName(lumpinfo.name, checklist, status)) + return false; + } + + return true; +} + +static int +W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status) +{ + zend_t zend; + zentry_t zentry; + + UINT16 numlumps; + size_t i; + + char pat_central[] = {0x50, 0x4b, 0x01, 0x02, 0x00}; + char pat_end[] = {0x50, 0x4b, 0x05, 0x06, 0x00}; + + char lumpname[9]; + + // Haha the ResGetLumpsZip function doesn't + // check for file errors, so neither will I. + + // Central directory bullshit + + fseek(fp, 0, SEEK_END); + if (!ResFindSignature(fp, pat_end, max(0, ftell(fp) - (22 + 65536)))) + return true; + + fseek(fp, -4, SEEK_CUR); + if (fread(&zend, 1, sizeof zend, fp) < sizeof zend) + return true; + + numlumps = zend.entries; + + fseek(fp, zend.cdiroffset, SEEK_SET); + for (i = 0; i < numlumps; i++) + { + char* fullname; + char* trimname; + char* dotpos; + + if (fread(&zentry, 1, sizeof(zentry_t), fp) < sizeof(zentry_t)) + return true; + if (memcmp(zentry.signature, pat_central, 4)) + return true; + + fullname = malloc(zentry.namelen + 1); + if (fgets(fullname, zentry.namelen + 1, fp) != fullname) + return true; + + // Strip away file address and extension for the 8char name. + if ((trimname = strrchr(fullname, '/')) != 0) + trimname++; + else + trimname = fullname; // Care taken for root files. + + if (*trimname) // Ignore directories + { + if ((dotpos = strrchr(trimname, '.')) == 0) + dotpos = fullname + strlen(fullname); // Watch for files without extension. + + memset(lumpname, '\0', 9); // Making sure they're initialized to 0. Is it necessary? + strncpy(lumpname, trimname, min(8, dotpos - trimname)); + + if (! W_VerifyName(lumpname, checklist, status)) + return false; + } + + free(fullname); + } + + return true; +} + // Note: This never opens lumps themselves and therefore doesn't have to // deal with compressed lumps. static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, boolean status) { FILE *handle; - size_t i, j; int goodfile = false; if (!checklist) @@ -1634,66 +1766,18 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, if ((handle = W_OpenWadFile(&filename, false)) == NULL) return -1; - // detect wad file by the absence of the other supported extensions - if (stricmp(&filename[strlen(filename) - 4], ".soc") -#ifdef HAVE_BLUA - && stricmp(&filename[strlen(filename) - 4], ".lua") -#endif - && stricmp(&filename[strlen(filename) - 4], ".pk3")) + if (stricmp(&filename[strlen(filename) - 4], ".pk3") == 0) + goodfile = W_VerifyPK3(handle, checklist, status); + else { - // assume wad file - wadinfo_t header; - filelump_t lumpinfo; - - // read the header - if (fread(&header, 1, sizeof header, handle) == sizeof header - && header.numlumps < INT16_MAX - && strncmp(header.identification, "ZWAD", 4) - && strncmp(header.identification, "IWAD", 4) - && strncmp(header.identification, "PWAD", 4) - && strncmp(header.identification, "SDLL", 4)) + // detect wad file by the absence of the other supported extensions + if (stricmp(&filename[strlen(filename) - 4], ".soc") +#ifdef HAVE_BLUA + && stricmp(&filename[strlen(filename) - 4], ".lua") +#endif + ) { - fclose(handle); - return true; - } - - header.numlumps = LONG(header.numlumps); - header.infotableofs = LONG(header.infotableofs); - - // let seek to the lumpinfo list - if (fseek(handle, header.infotableofs, SEEK_SET) == -1) - { - fclose(handle); - return false; - } - - goodfile = true; - for (i = 0; i < header.numlumps; i++) - { - // fill in lumpinfo for this wad file directory - if (fread(&lumpinfo, sizeof (lumpinfo), 1 , handle) != 1) - { - fclose(handle); - return -1; - } - - lumpinfo.filepos = LONG(lumpinfo.filepos); - lumpinfo.size = LONG(lumpinfo.size); - - if (lumpinfo.size == 0) - continue; - - for (j = 0; j < NUMSPRITES; j++) - if (sprnames[j] && !strncmp(lumpinfo.name, sprnames[j], 4)) // Sprites - continue; - - goodfile = false; - for (j = 0; checklist[j].len && checklist[j].name && !goodfile; j++) - if ((strncmp(lumpinfo.name, checklist[j].name, checklist[j].len) != false) == status) - goodfile = true; - - if (!goodfile) - break; + goodfile = W_VerifyWAD(handle, checklist, status); } } fclose(handle); From 3ebb9c2c496a45d13b8470afff7774ed1f745b65 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 12 Sep 2019 21:36:13 -0400 Subject: [PATCH 098/133] More harmful cactus --- src/dehacked.c | 4 ++++ src/info.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/info.h | 4 ++++ 3 files changed, 64 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 37995cc9f..7b0a07a2f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5737,6 +5737,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_CACTI7", "S_CACTI8", "S_CACTI9", + "S_CACTI10", + "S_CACTI11", // Warning signs sprites "S_ARIDSIGN_CAUTION", @@ -7519,6 +7521,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_CACTI7", "MT_CACTI8", "MT_CACTI9", + "MT_CACTI10", + "MT_CACTI11", "MT_ARIDSIGN_CAUTION", "MT_ARIDSIGN_CACTI", "MT_ARIDSIGN_SHARPTURN", diff --git a/src/info.c b/src/info.c index 5baf28943..23bee18a2 100644 --- a/src/info.c +++ b/src/info.c @@ -2321,6 +2321,8 @@ state_t states[NUMSTATES] = {SPR_CACT, 6, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI7 {SPR_CACT, 7, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI8 {SPR_CACT, 8, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI9 + {SPR_CACT, 9, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI10 + {SPR_CACT, 10, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI11 // Warning Signs {SPR_WWSG, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_ARIDSIGN_CAUTION @@ -12294,6 +12296,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_CACTI10 + 1230, // doomednum + S_CACTI10, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 64*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SCENERY|MF_PAIN, // flags + S_NULL // raisestate + }, + + { // MT_CACTI11 + 1231, // doomednum + S_CACTI11, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SCENERY|MF_PAIN, // flags + S_NULL // raisestate + }, + { // MT_FLAMEJET 1300, // doomednum S_FLAMEJETSTND, // spawnstate diff --git a/src/info.h b/src/info.h index a9d4bdde0..f4fd63c81 100644 --- a/src/info.h +++ b/src/info.h @@ -2442,6 +2442,8 @@ typedef enum state S_CACTI7, S_CACTI8, S_CACTI9, + S_CACTI10, + S_CACTI11, // Warning signs sprites S_ARIDSIGN_CAUTION, @@ -4246,6 +4248,8 @@ typedef enum mobj_type MT_CACTI7, // Harmful Cactus 3 MT_CACTI8, // Harmful Cactus 4 MT_CACTI9, // Harmful Cactus 5 + MT_CACTI10, // Harmful Cactus 6 + MT_CACTI11, // Harmful Cactus 7 MT_ARIDSIGN_CAUTION, // Caution Sign MT_ARIDSIGN_CACTI, // Cacti Sign MT_ARIDSIGN_SHARPTURN, // Sharp Turn Sign From 97710875549fa1bd54e5a82b59c46e85b1261330 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 15 Sep 2019 17:43:19 +0200 Subject: [PATCH 099/133] Always force player camera direction for springs with horizontal thrust component. --- src/p_map.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 15fa97c8f..28bfd2806 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -345,17 +345,14 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (horizspeed) { object->player->drawangle = spring->angle; - if (vertispeed || (object->player->cmd.forwardmove == 0 && object->player->cmd.sidemove == 0)) - { - object->angle = spring->angle; + object->angle = spring->angle; - if (!demoplayback || P_AnalogMove(object->player)) - { - if (object->player == &players[consoleplayer]) - localangle = spring->angle; - else if (object->player == &players[secondarydisplayplayer]) - localangle2 = spring->angle; - } + if (!demoplayback || P_AnalogMove(object->player)) + { + if (object->player == &players[consoleplayer]) + localangle = spring->angle; + else if (object->player == &players[secondarydisplayplayer]) + localangle2 = spring->angle; } } From 78075ecd8919052ef83c002673e20b48d354bc2b Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Sep 2019 14:18:27 -0400 Subject: [PATCH 100/133] Fix FALLTHRU for Win32 console interface code --- src/sdl/i_system.c | 2 +- src/win32/win_sys.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index a18443c52..96e3d5b23 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -531,7 +531,7 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co) break; case VK_RETURN: entering_con_command = false; - // Fall through. + /* FALLTHRU */ default: event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char } diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index d10f73b58..93b3ff523 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -327,7 +327,7 @@ static inline VOID I_GetConsoleEvents(VOID) break; case VK_RETURN: entering_con_command = false; - // Fall through. + /* FALLTHRU */ default: ev.data1 = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char } From 2a33ffb7d784d0c5c54ee5fd29fcbd4aeb35fbd7 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Sep 2019 16:18:54 -0400 Subject: [PATCH 101/133] PNG support: use png_const_bytep, so we do not drop const type --- src/hardware/hw_cache.c | 4 ++-- src/r_data.c | 17 +++++++++++------ src/r_data.h | 4 ++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 2574bc011..b1a685ff4 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -727,8 +727,8 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm #ifndef NO_PNG_LUMPS // lump is a png so convert it size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum); - if ((patch != NULL) && R_IsLumpPNG((UINT8 *)patch, len)) - patch = R_PNGToPatch((UINT8 *)patch, len, NULL, true); + if ((patch != NULL) && R_IsLumpPNG((const UINT8 *)patch, len)) + patch = R_PNGToPatch((const UINT8 *)patch, len, NULL, true); #endif // don't do it twice (like a cache) diff --git a/src/r_data.c b/src/r_data.c index 172a61da5..be27fecad 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2588,7 +2588,7 @@ void R_PatchToFlat(patch_t *patch, UINT8 *flat) } #ifndef NO_PNG_LUMPS -boolean R_IsLumpPNG(UINT8 *d, size_t s) +boolean R_IsLumpPNG(const UINT8 *d, size_t s) { if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/ return false; @@ -2599,8 +2599,12 @@ boolean R_IsLumpPNG(UINT8 *d, size_t s) } #ifdef HAVE_PNG + +#if PNG_LIBPNG_VER_DLLNUM < 14 +typedef PNG_CONST png_byte *png_const_bytep; +#endif typedef struct { - png_bytep buffer; + png_const_bytep buffer; png_uint_32 bufsize; png_uint_32 current_pos; } png_io_t; @@ -2626,6 +2630,7 @@ static png_chunk_t chunk; static int PNG_ChunkReader(png_structp png_ptr, png_unknown_chunkp chonk) { + (void)png_ptr; if (!memcmp(chonk->name, chunkname, 4)) { memcpy(chunk.name, chonk->name, 4); @@ -2648,7 +2653,7 @@ static void PNG_warn(png_structp PNG, png_const_charp pngtext) CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext); } -static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size) +static png_bytep *PNG_Read(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size) { png_structp png_ptr; png_infop png_info_ptr; @@ -2697,7 +2702,7 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, I #endif // set our own read_function - png_io.buffer = (png_bytep)png; + png_io.buffer = (png_const_bytep)png; png_io.bufsize = size; png_io.current_pos = 0; png_set_read_fn(png_ptr, &png_io, PNG_IOReader); @@ -2767,7 +2772,7 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, I } // Convert a PNG to a raw image. -static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size) +static UINT8 *PNG_RawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size) { UINT8 *flat; png_uint_32 x, y; @@ -2803,7 +2808,7 @@ UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size) // Convert a PNG to a patch. static unsigned char imgbuf[1<<26]; -patch_t *R_PNGToPatch(UINT8 *png, size_t size, size_t *destsize, boolean transparency) +patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean transparency) { UINT16 width, height; INT16 topoffset = 0, leftoffset = 0; diff --git a/src/r_data.h b/src/r_data.h index 38b7ba0ce..ea48985dc 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -165,10 +165,10 @@ void R_PatchToFlat(patch_t *patch, UINT8 *flat); void R_TextureToFlat(size_t tex, UINT8 *flat); #ifndef NO_PNG_LUMPS -boolean R_IsLumpPNG(UINT8 *d, size_t s); +boolean R_IsLumpPNG(const UINT8 *d, size_t s); UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size); -patch_t *R_PNGToPatch(UINT8 *png, size_t size, size_t *destsize, boolean transparency); +patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean transparency); boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size); #endif From 35e3d9acab3e36ae370ce192bf370d512f375647 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Sep 2019 20:20:09 +0000 Subject: [PATCH 102/133] Revert "Merge branch 'gl_skydome' into 'master'" This reverts merge request !326 --- src/hardware/hw_drv.h | 2 - src/hardware/hw_main.c | 186 ++++++++++--------------- src/hardware/hw_main.h | 1 - src/hardware/r_opengl/r_opengl.c | 226 ------------------------------- src/r_main.c | 1 - src/sdl/hwsym_sdl.c | 1 - src/sdl/i_video.c | 1 - src/v_video.c | 1 - src/win32/win_dll.c | 2 - 9 files changed, 75 insertions(+), 346 deletions(-) diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index e0507bc70..e2fa90eb0 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -47,7 +47,6 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal, RGBA_t *pgamma); EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl); EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color); EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags); -EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform); EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); @@ -90,7 +89,6 @@ struct hwdriver_s FinishUpdate pfnFinishUpdate; Draw2DLine pfnDraw2DLine; DrawPolygon pfnDrawPolygon; - RenderSkyDome pfnRenderSkyDome; SetBlend pfnSetBlend; ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 6d3e6c8ce..4a075d376 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5869,122 +5869,86 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) // ========================================================================== // // ========================================================================== -static void HWR_DrawSkyBackground(player_t *player) +static void HWR_DrawSkyBackground(void) { - if (cv_grskydome.value) + FOutVector v[4]; + angle_t angle; + float dimensionmultiply; + float aspectratio; + float angleturn; + + HWR_GetTexture(texturetranslation[skytexture]); + aspectratio = (float)vid.width/(float)vid.height; + + //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 + // because it's called just after clearing the screen + // and thus, the near clipping plane is set to 3.99 + // Sryder: Just use the near clipping plane value then + + // 3--2 + // | /| + // |/ | + // 0--1 + v[0].x = v[3].x = -ZCLIP_PLANE-1; + v[1].x = v[2].x = ZCLIP_PLANE+1; + v[0].y = v[1].y = -ZCLIP_PLANE-1; + v[2].y = v[3].y = ZCLIP_PLANE+1; + + v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1; + + // X + + // NOTE: This doesn't work right with texture widths greater than 1024 + // software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly + // The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture + + angle = (dup_viewangle + gr_xtoviewangle[0]); + + dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); + + v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left + v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f) + // use +angle and -1.0f above instead if you wanted old backwards behavior + + // Y + angle = aimingangle; + dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio)); + + if (splitscreen) { - FTransform transform; - const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); - postimg_t *type; + dimensionmultiply *= 2; + angle *= 2; + } - if (splitscreen && player == &players[secondarydisplayplayer]) - type = &postimgtype2; - else - type = &postimgtype; - - memset(&transform, 0x00, sizeof(FTransform)); - - //04/01/2000: Hurdler: added for T&L - // It should replace all other gr_viewxxx when finished - transform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - transform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - - if (*type == postimg_flip) - transform.flip = true; - else - transform.flip = false; - - transform.scalex = 1; - transform.scaley = (float)vid.width/vid.height; - transform.scalez = 1; - transform.fovxangle = fpov; // Tails - transform.fovyangle = fpov; // Tails - transform.splitscreen = splitscreen; - - HWR_GetTexture(texturetranslation[skytexture]); - HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, transform); + // Middle of the sky should always be at angle 0 + // need to keep correct aspect ratio with X + if (atransform.flip) + { + // During vertical flip the sky should be flipped and it's y movement should also be flipped obviously + v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top + v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f) } else { - FOutVector v[4]; - angle_t angle; - float dimensionmultiply; - float aspectratio; - float angleturn; - - HWR_GetTexture(texturetranslation[skytexture]); - aspectratio = (float)vid.width/(float)vid.height; - - //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 - // because it's called just after clearing the screen - // and thus, the near clipping plane is set to 3.99 - // Sryder: Just use the near clipping plane value then - - // 3--2 - // | /| - // |/ | - // 0--1 - v[0].x = v[3].x = -ZCLIP_PLANE-1; - v[1].x = v[2].x = ZCLIP_PLANE+1; - v[0].y = v[1].y = -ZCLIP_PLANE-1; - v[2].y = v[3].y = ZCLIP_PLANE+1; - - v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1; - - // X - - // NOTE: This doesn't work right with texture widths greater than 1024 - // software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly - // The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture - - angle = (dup_viewangle + gr_xtoviewangle[0]); - - dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); - - v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left - v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f) - // use +angle and -1.0f above instead if you wanted old backwards behavior - - // Y - angle = aimingangle; - dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio)); - - if (splitscreen) - { - dimensionmultiply *= 2; - angle *= 2; - } - - // Middle of the sky should always be at angle 0 - // need to keep correct aspect ratio with X - if (atransform.flip) - { - // During vertical flip the sky should be flipped and it's y movement should also be flipped obviously - v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top - v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f) - } - else - { - v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom - v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f) - } - - angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; - - if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa - { - angle = InvAngle(angle); - v[3].tow = v[2].tow += ((float) angle / angleturn); - v[0].tow = v[1].tow += ((float) angle / angleturn); - } - else - { - v[3].tow = v[2].tow -= ((float) angle / angleturn); - v[0].tow = v[1].tow -= ((float) angle / angleturn); - } - - HWD.pfnDrawPolygon(NULL, v, 4, 0); + v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom + v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f) } + + angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; + + if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa + { + angle = InvAngle(angle); + v[3].tow = v[2].tow += ((float) angle / angleturn); + v[0].tow = v[1].tow += ((float) angle / angleturn); + } + else + { + v[3].tow = v[2].tow -= ((float) angle / angleturn); + v[0].tow = v[1].tow -= ((float) angle / angleturn); + } + + HWD.pfnDrawPolygon(NULL, v, 4, 0); } @@ -6136,7 +6100,7 @@ if (0) } if (drawsky) - HWR_DrawSkyBackground(player); + HWR_DrawSkyBackground(); //Hurdler: it doesn't work in splitscreen mode drawsky = splitscreen; @@ -6353,7 +6317,7 @@ if (0) } if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox - HWR_DrawSkyBackground(player); + HWR_DrawSkyBackground(); //Hurdler: it doesn't work in splitscreen mode drawsky = splitscreen; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 31e97cc13..f8524990f 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -98,7 +98,6 @@ extern consvar_t cv_voodoocompatibility; extern consvar_t cv_grfovchange; extern consvar_t cv_grsolvetjoin; extern consvar_t cv_grspritebillboarding; -extern consvar_t cv_grskydome; extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 2fe6741e2..dfee19857 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1427,232 +1427,6 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, Clamp2D(GL_TEXTURE_WRAP_T); } -// PRBoom sky dome -typedef struct vbo_vertex_s -{ - float x, y, z; - float u, v; - unsigned char r, g, b, a; -} vbo_vertex_t; - -typedef struct -{ - int mode; - int vertexcount; - int vertexindex; - int use_texture; -} GLSkyLoopDef; - -typedef struct -{ - int id; - int rows, columns; - int loopcount; - GLSkyLoopDef *loops; - vbo_vertex_t *data; -} GLSkyVBO; - -// The texture offset to be applied to the texture coordinates in SkyVertex(). -static int rows, columns; -static boolean yflip; -static int texw, texh; -static float yMult, yAdd; -static boolean foglayer; -static float delta = 0.0f; -static int gl_sky_detail = 16; -static INT32 lasttex = -1; - -static RGBA_t SkyColor; - -#define MAP_COEFF 128.0f -#define MAP_SCALE (MAP_COEFF*(float)FRACUNIT) - -static void SkyVertex(vbo_vertex_t *vbo, int r, int c) -{ - static fixed_t scale = 10000 << FRACBITS; - static angle_t maxSideAngle = ANGLE_180 / 3; - - angle_t topAngle = (angle_t)(c / (float)columns * ANGLE_MAX); - angle_t sideAngle = maxSideAngle * (rows - r) / rows; - fixed_t height = FINESINE(sideAngle>>ANGLETOFINESHIFT); - fixed_t realRadius = FixedMul(scale, FINECOSINE(sideAngle>>ANGLETOFINESHIFT)); - fixed_t x = FixedMul(realRadius, FINECOSINE(topAngle>>ANGLETOFINESHIFT)); - fixed_t y = (!yflip) ? FixedMul(scale, height) : FixedMul(scale, height) * -1; - fixed_t z = FixedMul(realRadius, FINESINE(topAngle>>ANGLETOFINESHIFT)); - float timesRepeat; - - timesRepeat = (short)(4 * (256.0f / texw)); - if (timesRepeat == 0.0f) - timesRepeat = 1.0f; - - if (!foglayer) - { - boolean flip = yflip; - vbo->r = 255; - vbo->g = 255; - vbo->b = 255; - vbo->a = (r == 0 ? 0 : 255); - - // Flip Y coordinate anyway for the top part of the hemisphere - if (r <= 1) - flip = !flip; - - // And the texture coordinates. - vbo->u = (-timesRepeat * c / (float)columns); - if (!flip) // Flipped Y is for the lower hemisphere. - vbo->v = (r / (float)rows) * 1.f * yMult + yAdd; - else - vbo->v = ((rows-r)/(float)rows) * 1.f * yMult + yAdd; - } - - // And finally the vertex. - vbo->x = (float)x/(float)MAP_SCALE; - vbo->y = (float)y/(float)MAP_SCALE + delta; - vbo->z = (float)z/(float)MAP_SCALE; -} - -GLSkyVBO sky_vbo; - -static void gld_BuildSky(int row_count, int col_count) -{ - int c, r; - vbo_vertex_t *vertex_p; - int vertex_count = 2 * row_count * (col_count * 2 + 2) + col_count * 2; - - GLSkyVBO *vbo = &sky_vbo; - - if ((vbo->columns != col_count) || (vbo->rows != row_count)) - { - free(vbo->loops); - free(vbo->data); - memset(vbo, 0, sizeof(&vbo)); - } - - if (!vbo->data) - { - memset(vbo, 0, sizeof(&vbo)); - vbo->loops = malloc((row_count * 2 + 2) * sizeof(vbo->loops[0])); - // create vertex array - vbo->data = malloc(vertex_count * sizeof(vbo->data[0])); - } - - vbo->columns = col_count; - vbo->rows = row_count; - - vertex_p = &vbo->data[0]; - vbo->loopcount = 0; - - memset(&SkyColor, 0xFF, sizeof(SkyColor)); - - // Why not? - for (yflip = false; yflip <= true; yflip++) - { - vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_FAN; - vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0]; - vbo->loops[vbo->loopcount].vertexcount = col_count; - vbo->loops[vbo->loopcount].use_texture = false; - vbo->loopcount++; - - yAdd = 0.5f; - yMult = 1.0f; - /*if (yflip == 0) - SkyColor = &sky->CeilingSkyColor[vbo_idx]; - else - SkyColor = &sky->FloorSkyColor[vbo_idx];*/ - - delta = 0.0f; - foglayer = true; - for (c = 0; c < col_count; c++) - { - SkyVertex(vertex_p, 1, c); - vertex_p->r = SkyColor.s.red; - vertex_p->g = SkyColor.s.green; - vertex_p->b = SkyColor.s.blue; - vertex_p->a = 255; - vertex_p++; - } - foglayer = false; - - delta = (yflip ? 5.0f : -5.0f) / MAP_COEFF; - - for (r = 0; r < row_count; r++) - { - vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_STRIP; - vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0]; - vbo->loops[vbo->loopcount].vertexcount = 2 * col_count + 2; - vbo->loops[vbo->loopcount].use_texture = true; //(r > 1) ? true : false; - vbo->loopcount++; - - for (c = 0; c <= col_count; c++) - { - SkyVertex(vertex_p++, r + (yflip ? 1 : 0), (c ? c : 0)); - SkyVertex(vertex_p++, r + (yflip ? 0 : 1), (c ? c : 0)); - } - } - } -} - -static void RenderDomeForReal(INT32 skytexture) -{ - int i, j; - GLSkyVBO *vbo = &sky_vbo; - - pglRotatef(270.f, 0.f, 1.f, 0.f); - - rows = 4; - columns = 4 * gl_sky_detail; - - if (lasttex != skytexture) - { - lasttex = skytexture; - gld_BuildSky(rows, columns); - } - - pglScalef(1.0f, (float)texh / 230.0f, 1.0f); - - for (j = 0; j < 2; j++) - { - for (i = 0; i < vbo->loopcount; i++) - { - GLSkyLoopDef *loop = &vbo->loops[i]; - - if (j == 0 ? loop->use_texture : !loop->use_texture) - continue; - else - { - int k; - pglBegin(loop->mode); - for (k = loop->vertexindex; k < (loop->vertexindex + loop->vertexcount); k++) - { - vbo_vertex_t *v = &vbo->data[k]; - if (loop->use_texture) - pglTexCoord2f(v->u, v->v); - pglColor4f(v->r, v->g, v->b, v->a); - pglVertex3f(v->x, v->y, v->z); - } - pglEnd(); - } - } - } - - pglScalef(1.0f, 1.0f, 1.0f); - - // current color is undefined after glDrawArrays - pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); -} - -EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform) -{ - SetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated); - SetTransform(&transform); - - texw = texture_width; - texh = texture_height; - RenderDomeForReal(tex); - - // HWR_DrawSkyBackground left no blend flags after rendering the sky - SetBlend(0); -} // ========================================================================== // diff --git a/src/r_main.c b/src/r_main.c index 5135e57ce..db351e991 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1215,7 +1215,6 @@ void R_RegisterEngineStuff(void) #endif CV_RegisterVar(&cv_grmd2); CV_RegisterVar(&cv_grspritebillboarding); - CV_RegisterVar(&cv_grskydome); #endif #ifdef HWRENDER diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 103398405..05ac6450e 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -79,7 +79,6 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(Init); GETFUNC(Draw2DLine); GETFUNC(DrawPolygon); - GETFUNC(RenderSkyDome); GETFUNC(SetBlend); GETFUNC(ClearBuffer); GETFUNC(SetTexture); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 2f8bfb40a..2f5f1f684 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1499,7 +1499,6 @@ void I_StartupGraphics(void) HWD.pfnFinishUpdate = NULL; HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); - HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); HWD.pfnSetBlend = hwSym("SetBlend",NULL); HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); diff --git a/src/v_video.c b/src/v_video.c index 747300114..93fefdd97 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -112,7 +112,6 @@ static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NUL // console variables in development consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif // local copy of the palette for V_GetColor() diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index ce007af25..71eda0437 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -102,7 +102,6 @@ static loadfunc_t hwdFuncTable[] = { {"FinishUpdate@4", &hwdriver.pfnFinishUpdate}, {"Draw2DLine@12", &hwdriver.pfnDraw2DLine}, {"DrawPolygon@16", &hwdriver.pfnDrawPolygon}, - {"RenderSkyDome@16", &hwdriver.pfnRenderDome}, {"SetBlend@4", &hwdriver.pfnSetBlend}, {"ClearBuffer@12", &hwdriver.pfnClearBuffer}, {"SetTexture@4", &hwdriver.pfnSetTexture}, @@ -134,7 +133,6 @@ static loadfunc_t hwdFuncTable[] = { {"FinishUpdate", &hwdriver.pfnFinishUpdate}, {"Draw2DLine", &hwdriver.pfnDraw2DLine}, {"DrawPolygon", &hwdriver.pfnDrawPolygon}, - {"RenderSkyDome", &hwdriver.pfnRenderDome}, {"SetBlend", &hwdriver.pfnSetBlend}, {"ClearBuffer", &hwdriver.pfnClearBuffer}, {"SetTexture", &hwdriver.pfnSetTexture}, From 81d1453dc47e7d6e1aaa16531cecba1eda36e3ac Mon Sep 17 00:00:00 2001 From: sphere Date: Wed, 18 Sep 2019 02:05:19 +0200 Subject: [PATCH 103/133] New animated DSZ kelp. --- src/dehacked.c | 7 ++++++ src/info.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/info.h | 9 ++++++++ 3 files changed, 77 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 7b0a07a2f..b19607d8e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5593,6 +5593,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Kelp, "S_KELP", + // Animated algae + "S_ANIMALGAETOP1", + "S_ANIMALGAETOP2", + "S_ANIMALGAESEG", + // DSZ Stalagmites "S_DSZSTALAGMITE", "S_DSZ2STALAGMITE", @@ -7462,6 +7467,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_CORAL3", // Coral 3 "MT_BLUECRYSTAL", // Blue Crystal "MT_KELP", // Kelp + "MT_ANIMALGAETOP", // Animated algae top + "MT_ANIMALGAESEG", // Animated algae segment "MT_DSZSTALAGMITE", // Deep Sea 1 Stalagmite "MT_DSZ2STALAGMITE", // Deep Sea 2 Stalagmite "MT_LIGHTBEAM", // DSZ Light beam diff --git a/src/info.c b/src/info.c index b6d6d49a7..702466d23 100644 --- a/src/info.c +++ b/src/info.c @@ -217,6 +217,8 @@ char sprnames[NUMSPRITES + 1][5] = "CRL3", // Coral 3 "BCRY", // Blue Crystal "KELP", // Kelp + "ALGA", // Animated algae top + "ALGB", // Animated algae segment "DSTG", // DSZ Stalagmites "LIBE", // DSZ Light beam @@ -2179,6 +2181,11 @@ state_t states[NUMSTATES] = // Kelp {SPR_KELP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KELP + // Animated algae + {SPR_ALGA, 0, 1, {A_ConnectToGround}, MT_ANIMALGAESEG, 0, S_ANIMALGAETOP2}, // S_ANIMALGAETOP1 + {SPR_ALGA, 0|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 11, 4, S_NULL}, // S_ANIMALGAETOP2 + {SPR_ALGB, 0|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 11, 4, S_NULL}, // S_ANIMALGAESEG + // DSZ Stalagmites {SPR_DSTG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_DSZSTALAGMITE {SPR_DSTG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_DSZ2STALAGMITE @@ -10202,6 +10209,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_ANIMALGAETOP + 1013, // doomednum + S_ANIMALGAETOP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 120*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIP|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_ANIMALGAESEG + -1, // doomednum + S_ANIMALGAESEG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 120*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIP|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_DSZSTALAGMITE 1008, // doomednum S_DSZSTALAGMITE, // spawnstate diff --git a/src/info.h b/src/info.h index 46279746e..ae979df31 100644 --- a/src/info.h +++ b/src/info.h @@ -463,6 +463,8 @@ typedef enum sprite SPR_CRL3, // Coral 3 SPR_BCRY, // Blue Crystal SPR_KELP, // Kelp + SPR_ALGA, // Animated algae top + SPR_ALGB, // Animated algae segment SPR_DSTG, // DSZ Stalagmites SPR_LIBE, // DSZ Light beam @@ -2304,6 +2306,11 @@ typedef enum state // Kelp, S_KELP, + // Animated algae + S_ANIMALGAETOP1, + S_ANIMALGAETOP2, + S_ANIMALGAESEG, + // DSZ Stalagmites S_DSZSTALAGMITE, S_DSZ2STALAGMITE, @@ -4195,6 +4202,8 @@ typedef enum mobj_type MT_CORAL3, // Coral 3 MT_BLUECRYSTAL, // Blue Crystal MT_KELP, // Kelp + MT_ANIMALGAETOP, // Animated algae top + MT_ANIMALGAESEG, // Animated algae segment MT_DSZSTALAGMITE, // Deep Sea 1 Stalagmite MT_DSZ2STALAGMITE, // Deep Sea 2 Stalagmite MT_LIGHTBEAM, // DSZ Light beam From a6831aff9ca5a890feb376ea9ba651089e0d1441 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 17 Sep 2019 22:29:53 -0300 Subject: [PATCH 104/133] compile fix --- src/hardware/hw_cache.c | 8 ++++---- src/r_data.c | 16 ++++++++-------- src/r_data.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index b1a685ff4..02df290b8 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -149,7 +149,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; @@ -159,7 +159,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)); break; @@ -263,7 +263,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; @@ -273,7 +273,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)); break; diff --git a/src/r_data.c b/src/r_data.c index be27fecad..496f6bdd7 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -241,7 +241,7 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, tex } } -RGBA_t ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) +UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) { RGBA_t output; if (style == AST_TRANSLUCENT) @@ -298,13 +298,13 @@ RGBA_t ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph } // just copy the pixel else if (style == AST_COPY) - return background; + output.rgba = foreground.rgba; + + output.s.alpha = 0xFF; + return output.rgba; } #undef clamp - // unimplemented blend modes return the background pixel - output = background; - output.s.alpha = 0xFF; - return output; + return 0; } UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha) @@ -321,7 +321,7 @@ UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 al } // just copy the pixel else if (style == AST_COPY) - return background; + return foreground; // use ASTBlendPixel for all other blend modes // and find the nearest colour in the palette else if (style != AST_TRANSLUCENT) @@ -329,7 +329,7 @@ UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 al RGBA_t texel; RGBA_t bg = V_GetColor(background); RGBA_t fg = V_GetColor(foreground); - texel = ASTBlendPixel(bg, fg, style, alpha); + texel.rgba = ASTBlendPixel(bg, fg, style, alpha); return NearestColor(texel.s.red, texel.s.green, texel.s.blue); } // fallback if all above fails, somehow diff --git a/src/r_data.h b/src/r_data.h index ea48985dc..c2fd284ff 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -25,7 +25,7 @@ // Possible alpha types for a patch. enum patchalphastyle {AST_COPY, AST_TRANSLUCENT, AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY}; -RGBA_t ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha); +UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha); UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha); UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); From 45a99ce318f32009eeb0de525db07160f4689ab7 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 12:26:34 +0100 Subject: [PATCH 105/133] Change startchar's default value to 0 (Resolves #222). --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index d05048a9d..d3442fcf9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -118,7 +118,7 @@ const char *quitmsg[NUM_QUITMESSAGES]; // Stuff for customizing the player select screen Tails 09-22-2003 description_t description[MAXSKINS]; -INT16 char_on = -1, startchar = 1; +INT16 char_on = -1, startchar = 0; static char *char_notes = NULL; static fixed_t char_scroll = 0; From e230d7351c379818ab0ae188456fe267b27aec1c Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 12:46:18 +0100 Subject: [PATCH 106/133] Completely untested cuz I need to commit before I can merge the compile fix, but the intent of this commit is: * Fix S_PLAY_FLY_TIRED animation being fast. * Add moving tails to S_PLAY_SWIM animation! * Fix autobrake happening when your controls are locked by pw_nocontrol/PF_STASIS. (Resolves #219, hopefully..?) --- src/p_user.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 43138d2e9..ff887a171 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8200,7 +8200,7 @@ static void P_MovePlayer(player_t *player) else { // Tails-gets-tired Stuff - if (player->panim == PA_ABILITY) + if (player->panim == PA_ABILITY && player->mo->state-states != S_PLAY_FLY_TIRED) P_SetPlayerMobjState(player->mo, S_PLAY_FLY_TIRED); if (player->charability == CA_FLY && (leveltime % 10 == 0) @@ -10604,7 +10604,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) angle_t horizangle = player->drawangle; fixed_t zoffs = 0; fixed_t backwards = -1*FRACUNIT; - boolean doroll = (player->panim == PA_ROLL || player->panim == PA_JUMP); + boolean doroll = (player->panim == PA_ROLL || (player->panim == PA_JUMP && !(player->charflags & SF_NOJUMPSPIN)) || player->mo->sprite2 == SPR2_SWIM); angle_t rollangle; boolean panimchange; INT32 ticnum = 0; @@ -10636,12 +10636,17 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) else zdist = player->mo->momz; rollangle = R_PointToAngle2(0, 0, testval, -P_MobjFlip(player->mo)*zdist); - zoffs = 3*FRACUNIT + 12*FINESINE(rollangle >> ANGLETOFINESHIFT); - backwards = -12*FINECOSINE(rollangle >> ANGLETOFINESHIFT); + if (player->mo->sprite2 == SPR2_SWIM) + backwards = -5*FRACUNIT; + else + { + zoffs = 3*FRACUNIT + 12*FINESINE(rollangle >> ANGLETOFINESHIFT); + backwards = -12*FINECOSINE(rollangle >> ANGLETOFINESHIFT); + } } else if (player->panim == PA_RUN) backwards = -5*FRACUNIT; - else if (player->panim == PA_SPRING) + else if (player->panim == PA_SPRING || player->panim == PA_JUMP) { zoffs += 4*FRACUNIT; backwards /= 2; @@ -10663,7 +10668,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) zoffs = -7*FRACUNIT; backwards = -9*FRACUNIT; } - else if (player->mo->sprite2 == SPR2_FLY || player->mo->sprite2 == SPR2_TIRE) + else if (player->panim == PA_ABILITY) backwards = -5*FRACUNIT; // sprite... @@ -10680,7 +10685,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) else chosenstate = S_TAILSOVERLAY_0DEGREES; } - else if (player->panim == PA_SPRING) + else if (player->panim == PA_SPRING || player->panim == PA_JUMP) chosenstate = S_TAILSOVERLAY_MINUS60DEGREES; else if (player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE) chosenstate = S_TAILSOVERLAY_PLUS60DEGREES; @@ -10703,6 +10708,8 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) } else if (player->mo->sprite2 == SPR2_FLY) chosenstate = S_TAILSOVERLAY_FLY; + else if (player->mo->sprite2 == SPR2_SWIM) + chosenstate = S_TAILSOVERLAY_FLY; else if (player->mo->sprite2 == SPR2_TIRE) chosenstate = S_TAILSOVERLAY_TIRE; else if (player->panim == PA_ABILITY2) @@ -11269,8 +11276,8 @@ void P_PlayerThink(player_t *player) { boolean currentlyonground = P_IsObjectOnGround(player->mo); - if (!player->powers[pw_carry] - && ((player->pflags & (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) == (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) + if (!player->powers[pw_carry] && !player->powers[pw_nocontrol] + && ((player->pflags & (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE|PF_STASIS)) == (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) && !(cmd->forwardmove || cmd->sidemove) && (player->rmomx || player->rmomy) && (!player->capsule || (player->capsule->reactiontime != (player-players)+1))) From 9d774f7578a3e4b709980b1f9fbb588b77a69264 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 13:46:17 +0100 Subject: [PATCH 107/133] More swim stuff! * Prevent being able to damage enemies from below while swimming. * Make the swim-specific bubbles happen at the hands instead of where the propeller would be. * Improve placement/angle of swimming tails overlay. * Immediately set flight time to 0 if a player is being carried underwater. --- src/p_user.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index ff887a171..699069592 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1109,7 +1109,7 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) } else if (P_MobjFlip(player->mo)*(topheight - (thing->z + thing->height/2)) < 0) { - if (player->charability == CA_FLY && player->panim == PA_ABILITY && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0)) + if (player->charability == CA_FLY && player->panim == PA_ABILITY && !(player->mo->eflags & MFE_UNDERWATER) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0)) return true; } @@ -2964,22 +2964,19 @@ static void P_DoBubbleBreath(player_t *player) P_SetScale(bubble, bubble->destscale); } - if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS Super doesn't spawn flight bubbles - return; - // Tails stirs up the water while flying in it if (player->powers[pw_tailsfly] && (leveltime & 1) && player->charability != CA_SWIM) { - fixed_t radius = (3*player->mo->radius)>>1; + fixed_t radius = player->mo->radius; angle_t fa = ((leveltime%45)*FINEANGLES/8) & FINEMASK; fixed_t stirwaterx = FixedMul(FINECOSINE(fa),radius); fixed_t stirwatery = FixedMul(FINESINE(fa),radius); fixed_t stirwaterz; if (player->mo->eflags & MFE_VERTICALFLIP) - stirwaterz = player->mo->z + player->mo->height - FixedDiv(player->mo->height,3*FRACUNIT/2); + stirwaterz = player->mo->z + player->mo->height - (4<mo->z + FixedDiv(player->mo->height,3*FRACUNIT/2); + stirwaterz = player->mo->z + (4<mo->x + stirwaterx, @@ -10604,7 +10601,8 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) angle_t horizangle = player->drawangle; fixed_t zoffs = 0; fixed_t backwards = -1*FRACUNIT; - boolean doroll = (player->panim == PA_ROLL || (player->panim == PA_JUMP && !(player->charflags & SF_NOJUMPSPIN)) || player->mo->sprite2 == SPR2_SWIM); + boolean doswim = (player->panim == PA_ABILITY && (player->mo->eflags & MFE_UNDERWATER)); + boolean doroll = (player->panim == PA_ROLL || (player->panim == PA_JUMP && !(player->charflags & SF_NOJUMPSPIN)) || doswim); angle_t rollangle; boolean panimchange; INT32 ticnum = 0; @@ -10631,14 +10629,17 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) if (testval < FRACUNIT) testval = FRACUNIT; } - if (smilesonground && !player->mo->reactiontime) + + if (doswim) + zdist = player->mo->momz<<1; + else if (smilesonground && !player->mo->reactiontime) zdist = (player->mo->z - tails->threshold); else zdist = player->mo->momz; + rollangle = R_PointToAngle2(0, 0, testval, -P_MobjFlip(player->mo)*zdist); - if (player->mo->sprite2 == SPR2_SWIM) - backwards = -5*FRACUNIT; - else + + if (!doswim) { zoffs = 3*FRACUNIT + 12*FINESINE(rollangle >> ANGLETOFINESHIFT); backwards = -12*FINECOSINE(rollangle >> ANGLETOFINESHIFT); @@ -11819,6 +11820,8 @@ void P_PlayerAfterThink(player_t *player) { if (player->mo->state-states != S_PLAY_RIDE) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); + if (tails->eflags & MFE_UNDERWATER) + tails->player->powers[pw_tailsfly] = 0; } else P_SetTarget(&player->mo->tracer, NULL); From e993b8981ecf1f960de2ada89c590a79049302b4 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 13:55:20 +0100 Subject: [PATCH 108/133] Fix solidity of lava in reverse gravity. (Resolves #216) --- src/p_mobj.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 44c6b9f6e..236347eae 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2381,22 +2381,42 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover) { + fixed_t topheight; + I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - { - fixed_t topheight = - #ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : - #endif - *rover->topheight; + // not a lava block with solid planes + if (!(rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 + && !(rover->master->flags & ML_BLOCKMONSTERS))) + return false; - if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 - && !(rover->master->flags & ML_BLOCKMONSTERS) - && ((rover->master->flags & ML_EFFECT3) || mo->z-mo->momz > topheight - FixedMul(16*FRACUNIT, mo->scale))) + // is solid from the sides + if (rover->master->flags & ML_EFFECT3) + return true; + + if (mo->eflags & MFE_VERTICALFLIP) + { + topheight = + #ifdef ESLOPE + *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : + #endif + *rover->bottomheight; + + if (mo->z+mo->height-mo->momz < topheight + FixedMul(16*FRACUNIT, mo->scale)) return true; + return false; } + topheight = + #ifdef ESLOPE + *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : + #endif + *rover->topheight; + + if (mo->z-mo->momz > topheight - FixedMul(16*FRACUNIT, mo->scale)) + return true; + return false; } From a8a8ae0d0bdfb8a6c6eb1db644b24250ee8326f2 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 14:11:06 +0100 Subject: [PATCH 109/133] Only set flight time to 0 if skin has SPR2_SWIM spriteset. --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 699069592..b719ae33b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11820,7 +11820,7 @@ void P_PlayerAfterThink(player_t *player) { if (player->mo->state-states != S_PLAY_RIDE) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); - if (tails->eflags & MFE_UNDERWATER) + if ((tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER)) tails->player->powers[pw_tailsfly] = 0; } else From 5d37ddd676a75a68eb47b8cca3218df5cc17e060 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 14:16:52 +0100 Subject: [PATCH 110/133] Change threshold on autobrake skidding sound/animaton to runspeed rather than half of runspeed. --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index b719ae33b..e0a4d710c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11289,7 +11289,7 @@ void P_PlayerThink(player_t *player) if (!currentlyonground) acceleration /= 2; // fake skidding! see P_SkidStuff for reference on conditionals - else if (!player->skidtime && !(player->mo->eflags & MFE_GOOWATER) && !(player->pflags & (PF_JUMPED|PF_SPINNING|PF_SLIDING)) && !(player->charflags & SF_NOSKID) && P_AproxDistance(player->mo->momx, player->mo->momy) >= FixedMul(player->runspeed/2, player->mo->scale)) + else if (!player->skidtime && !(player->mo->eflags & MFE_GOOWATER) && !(player->pflags & (PF_JUMPED|PF_SPINNING|PF_SLIDING)) && !(player->charflags & SF_NOSKID) && P_AproxDistance(player->mo->momx, player->mo->momy) >= FixedMul(player->runspeed, player->mo->scale)) // modified from player->runspeed/2 'cuz the skid was just TOO frequent ngl { if (player->mo->state-states != S_PLAY_SKID) P_SetPlayerMobjState(player->mo, S_PLAY_SKID); From 2ed9d957b082d5717bb4acbe51317cc4c0042478 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 15:26:21 +0100 Subject: [PATCH 111/133] Fix Knuckles being able to climb up solid midtextures by repeatedly gliding at them. (addresses #174 checkbox 2) --- src/p_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 28bfd2806..dee1b5c40 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3199,7 +3199,7 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle) && glidesector->sector->ceilingpic == skyflatnum) return false; - if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < ceilingz) + if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < floorz) || (player->mo->z >= ceilingz)) floorclimb = true; } From 3285cc9a0df647cf5d09cd56a4e11ca1abb512d4 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 16:06:13 +0100 Subject: [PATCH 112/133] Properly scrub the player struct clean between level transitions. (Good chance this fixes our new bug where the player gets stuck in their standing pose when the map begins..?) --- src/g_game.c | 50 ++++++++++++++++++++++++-------------------------- src/g_game.h | 2 +- src/p_mobj.c | 2 +- src/p_setup.c | 40 +++++++++------------------------------- 4 files changed, 35 insertions(+), 59 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 7a876e968..a3025f949 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2100,7 +2100,7 @@ static inline void G_PlayerFinishLevel(INT32 player) // G_PlayerReborn // Called after a player dies. Almost everything is cleared and initialized. // -void G_PlayerReborn(INT32 player) +void G_PlayerReborn(INT32 player, boolean betweenmaps) { player_t *p; INT32 score; @@ -2205,7 +2205,7 @@ void G_PlayerReborn(INT32 player) bot = players[player].bot; pity = players[player].pity; - if (!G_IsSpecialStage(gamemap)) + if (betweenmaps || !G_IsSpecialStage(gamemap)) { rings = (ultimatemode ? 0 : mapheaderinfo[gamemap-1]->startrings); spheres = 0; @@ -2284,6 +2284,28 @@ void G_PlayerReborn(INT32 player) //if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there //p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent + // Check to make sure their color didn't change somehow... + if (G_GametypeHasTeams()) + { + if (p->ctfteam == 1 && p->skincolor != skincolor_redteam) + { + if (p == &players[consoleplayer]) + CV_SetValue(&cv_playercolor, skincolor_redteam); + else if (p == &players[secondarydisplayplayer]) + CV_SetValue(&cv_playercolor2, skincolor_redteam); + } + else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam) + { + if (p == &players[consoleplayer]) + CV_SetValue(&cv_playercolor, skincolor_blueteam); + else if (p == &players[secondarydisplayplayer]) + CV_SetValue(&cv_playercolor2, skincolor_blueteam); + } + } + + if (betweenmaps) + return; + if (p-players == consoleplayer) { if (mapmusflags & MUSIC_RELOADRESET) @@ -2303,9 +2325,6 @@ void G_PlayerReborn(INT32 player) if (gametype == GT_COOP) P_FindEmerald(); // scan for emeralds to hunt for - // Reset Nights score and max link to 0 on death - p->marescore = p->maxlink = 0; - // If NiGHTS, find lowest mare to start with. p->mare = P_FindLowestMare(); @@ -2313,27 +2332,6 @@ void G_PlayerReborn(INT32 player) if (p->mare == 255) p->mare = 0; - - p->marelap = p->marebonuslap = 0; - - // Check to make sure their color didn't change somehow... - if (G_GametypeHasTeams()) - { - if (p->ctfteam == 1 && p->skincolor != skincolor_redteam) - { - if (p == &players[consoleplayer]) - CV_SetValue(&cv_playercolor, skincolor_redteam); - else if (p == &players[secondarydisplayplayer]) - CV_SetValue(&cv_playercolor2, skincolor_redteam); - } - else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam) - { - if (p == &players[consoleplayer]) - CV_SetValue(&cv_playercolor, skincolor_blueteam); - else if (p == &players[secondarydisplayplayer]) - CV_SetValue(&cv_playercolor2, skincolor_blueteam); - } - } } // diff --git a/src/g_game.h b/src/g_game.h index e161bc8ed..df1301dd7 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -100,7 +100,7 @@ extern INT32 localaiming, localaiming2; // should be an angle_t but signed // void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo); void G_DoReborn(INT32 playernum); -void G_PlayerReborn(INT32 player); +void G_PlayerReborn(INT32 player, boolean betweenmaps); void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean skipprecutscene, boolean FLS); char *G_BuildMapTitle(INT32 mapnum); diff --git a/src/p_mobj.c b/src/p_mobj.c index 236347eae..994ddcfe7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10432,7 +10432,7 @@ void P_SpawnPlayer(INT32 playernum) mobj_t *mobj; if (p->playerstate == PST_REBORN) - G_PlayerReborn(playernum); + G_PlayerReborn(playernum, false); // spawn as spectator determination if (!G_GametypeHasSpectators()) diff --git a/src/p_setup.c b/src/p_setup.c index 0753f01d3..c83c8cd5c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2246,6 +2246,8 @@ static void P_LevelInitStuff(void) for (i = 0; i < MAXPLAYERS; i++) { + G_PlayerReborn(i, true); + if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0)) { // In Co-Op, replenish a user's lives if they are depleted. @@ -2253,42 +2255,18 @@ static void P_LevelInitStuff(void) } // obliteration station... - players[i].spheres =\ - players[i].xtralife = players[i].deadtimer =\ - players[i].numboxes = players[i].totalring =\ - players[i].laps = players[i].aiming =\ - players[i].losstime = players[i].timeshit =\ - players[i].marescore = players[i].lastmarescore =\ - players[i].maxlink = players[i].startedtime =\ - players[i].finishedtime = players[i].finishedspheres =\ - players[i].finishedrings = players[i].lastmare =\ - players[i].lastmarelap = players[i].lastmarebonuslap =\ - players[i].totalmarelap = players[i].totalmarebonuslap =\ - players[i].marebegunat = players[i].textvar =\ - players[i].texttimer = players[i].linkcount =\ - players[i].linktimer = players[i].flyangle =\ - players[i].anotherflyangle = players[i].nightstime =\ - players[i].oldscale = players[i].mare = players[i].marelap =\ - players[i].marebonuslap = players[i].lapbegunat =\ - players[i].lapstartedtime = players[i].totalmarescore =\ - players[i].realtime = players[i].exiting = 0; + players[i].numboxes = players[i].totalring =\ + players[i].laps = players[i].marescore = players[i].lastmarescore =\ + players[i].mare = players[i].exiting = 0; - // i guess this could be part of the above but i feel mildly uncomfortable implicitly casting - players[i].gotcontinue = false; - - // aha, the first evidence this shouldn't be a memset! players[i].drillmeter = 40*20; - players[i].rings = (ultimatemode ? 0 : mapheaderinfo[gamemap-1]->startrings); - P_ResetPlayer(&players[i]); // hit these too - players[i].pflags &= ~(PF_GAMETYPEOVER|PF_TRANSFERTOCLOSEST); - - // unset ALL the pointers. P_SetTarget isn't needed here because if this - // function is being called we're just going to clobber the data anyways - players[i].mo = players[i].followmobj = players[i].awayviewmobj =\ - players[i].capsule = players[i].axis1 = players[i].axis2 = players[i].drone = NULL; + players[i].pflags &= ~(PF_GAMETYPEOVER); } + + if (botingame) + CV_SetValue(&cv_analog2, true); } // From a5460c74512f071d4fedf501ce073897e0ecc86f Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 17:24:22 +0100 Subject: [PATCH 113/133] Correct location of MT_CACTI10 and MT_CACTI11 in relation to their positions given in info.h and dehacked.c (fixes several ACZ-related crashes) --- src/info.c | 108 ++++++++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/info.c b/src/info.c index b6d6d49a7..54573e94f 100644 --- a/src/info.c +++ b/src/info.c @@ -11687,6 +11687,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_CACTI10 + 1230, // doomednum + S_CACTI10, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 64*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SCENERY|MF_PAIN, // flags + S_NULL // raisestate + }, + + { // MT_CACTI11 + 1231, // doomednum + S_CACTI11, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SCENERY|MF_PAIN, // flags + S_NULL // raisestate + }, + { // MT_ARIDSIGN_CAUTION 1212, // doomednum S_ARIDSIGN_CAUTION, // spawnstate @@ -12308,60 +12362,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_CACTI10 - 1230, // doomednum - S_CACTI10, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 64*FRACUNIT, // height - 0, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SCENERY|MF_PAIN, // flags - S_NULL // raisestate - }, - - { // MT_CACTI11 - 1231, // doomednum - S_CACTI11, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SCENERY|MF_PAIN, // flags - S_NULL // raisestate - }, - { // MT_FLAMEJET 1300, // doomednum S_FLAMEJETSTND, // spawnstate From f870b5237f5dabbb80fd7778e35745e31a1ecb81 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 17:48:41 +0100 Subject: [PATCH 114/133] * Fix native MF_PAIN sound extension being limited to UINT8 range, which only became evident when the new s1/2/cd/3db/kc sfx were added. * Make the pain-causing cactodes have DMG_SPIKE. --- src/info.c | 16 ++++++++-------- src/p_map.c | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/info.c b/src/info.c index 54573e94f..0fea743f6 100644 --- a/src/info.c +++ b/src/info.c @@ -11599,7 +11599,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 20*FRACUNIT, // radius 128*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11624,9 +11624,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // deathsound 0, // speed 24*FRACUNIT, // radius - 224*FRACUNIT, // height + 224*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11651,9 +11651,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // deathsound 0, // speed 24*FRACUNIT, // radius - 256*FRACUNIT, // height + 256*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11680,7 +11680,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 48*FRACUNIT, // radius 96*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11707,7 +11707,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16*FRACUNIT, // radius 64*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11734,7 +11734,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags diff --git a/src/p_map.c b/src/p_map.c index 28bfd2806..27e8f2f7d 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1019,7 +1019,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // underneath if (tmthing->flags & MF_SHOOTABLE && thing->health > 0) { - UINT8 damagetype = (thing->info->mass & 0xFF); + UINT32 damagetype = (thing->info->mass & 0xFF); if (!damagetype && thing->flags & MF_FIRE) // BURN! damagetype = DMG_FIRE; if (P_DamageMobj(tmthing, thing, thing, 1, damagetype) && (damagetype = (thing->info->mass>>8))) @@ -1036,7 +1036,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // underneath if (thing->flags & MF_SHOOTABLE && tmthing->health > 0) { - UINT8 damagetype = (tmthing->info->mass & 0xFF); + UINT32 damagetype = (tmthing->info->mass & 0xFF); if (!damagetype && tmthing->flags & MF_FIRE) // BURN! damagetype = DMG_FIRE; if (P_DamageMobj(thing, tmthing, tmthing, 1, damagetype) && (damagetype = (tmthing->info->mass>>8))) From c81452211d23b7feb31e3c570a214d3614d36109 Mon Sep 17 00:00:00 2001 From: sphere Date: Wed, 18 Sep 2019 21:40:33 +0200 Subject: [PATCH 115/133] Updated ACZ cacti. --- src/dehacked.c | 4 ++ src/info.c | 128 +++++++++++++++++++++++++++++++++++-------------- src/info.h | 30 +++++++----- 3 files changed, 113 insertions(+), 49 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index b19607d8e..a65a2249b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5744,6 +5744,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_CACTI9", "S_CACTI10", "S_CACTI11", + "S_CACTITINYSEG", + "S_CACTISMALLSEG", // Warning signs sprites "S_ARIDSIGN_CAUTION", @@ -7530,6 +7532,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_CACTI9", "MT_CACTI10", "MT_CACTI11", + "MT_CACTITINYSEG", + "MT_CACTISMALLSEG", "MT_ARIDSIGN_CAUTION", "MT_ARIDSIGN_CACTI", "MT_ARIDSIGN_SHARPTURN", diff --git a/src/info.c b/src/info.c index 96c5ebb0f..10ace455d 100644 --- a/src/info.c +++ b/src/info.c @@ -2330,18 +2330,20 @@ state_t states[NUMSTATES] = {SPR_STBL, 6, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL8}, // S_LITTLETUMBLEWEED_ROLL7 {SPR_STBL, 7, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL1}, // S_LITTLETUMBLEWEED_ROLL8 - // Cacti Sprites - {SPR_CACT, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI1 - {SPR_CACT, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI2 - {SPR_CACT, 2, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI3 - {SPR_CACT, 3, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI4 + // Cacti + {SPR_CACT, 0, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL}, // S_CACTI1 + {SPR_CACT, 1, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL}, // S_CACTI2 + {SPR_CACT, 2, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL}, // S_CACTI3 + {SPR_CACT, 3, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL}, // S_CACTI4 {SPR_CACT, 4, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI5 {SPR_CACT, 5, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI6 {SPR_CACT, 6, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI7 {SPR_CACT, 7, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI8 {SPR_CACT, 8, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI9 - {SPR_CACT, 9, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI10 - {SPR_CACT, 10, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI11 + {SPR_CACT, 9, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL}, // S_CACTI10 + {SPR_CACT, 10, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL}, // S_CACTI11 + {SPR_CACT, 11, -1, {NULL}, 0, 0, S_NULL}, // S_CACTITINYSEG + {SPR_CACT, 12, -1, {NULL}, 0, 0, S_NULL}, // S_CACTISMALLSEG // Warning Signs {SPR_WWSG, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_ARIDSIGN_CAUTION @@ -11522,13 +11524,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 13*FRACUNIT, // radius + 24*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags S_NULL // raisestate }, @@ -11549,13 +11551,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 64*FRACUNIT, // height + 15*FRACUNIT, // radius + 52*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags S_NULL // raisestate }, @@ -11576,13 +11578,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 13*FRACUNIT, // radius + 24*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags S_NULL // raisestate }, @@ -11603,13 +11605,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 80*FRACUNIT, // height + 15*FRACUNIT, // radius + 52*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags S_NULL // raisestate }, @@ -11633,7 +11635,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 32*FRACUNIT, // radius 96*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11660,7 +11662,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 20*FRACUNIT, // radius 128*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11687,7 +11689,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 24*FRACUNIT, // radius 224*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11714,7 +11716,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 24*FRACUNIT, // radius 256*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11741,7 +11743,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 48*FRACUNIT, // radius 96*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11765,13 +11767,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 64*FRACUNIT, // height + 13*FRACUNIT, // radius + 28*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound - MF_SOLID|MF_SCENERY|MF_PAIN, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags S_NULL // raisestate }, @@ -11792,13 +11794,67 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 15*FRACUNIT, // radius + 60*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound - MF_SOLID|MF_SCENERY|MF_PAIN, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_CACTITINYSEG + -1, // doomednum + S_CACTITINYSEG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 13*FRACUNIT, // radius + 28*FRACUNIT, // height + 0, // display offset + DMG_SPIKE, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_CACTISMALLSEG + -1, // doomednum + S_CACTISMALLSEG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 15*FRACUNIT, // radius + 60*FRACUNIT, // height + 0, // display offset + DMG_SPIKE, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags S_NULL // raisestate }, diff --git a/src/info.h b/src/info.h index ae979df31..e125b05f3 100644 --- a/src/info.h +++ b/src/info.h @@ -2445,7 +2445,7 @@ typedef enum state S_LITTLETUMBLEWEED_ROLL7, S_LITTLETUMBLEWEED_ROLL8, - // Cacti Sprites + // Cacti S_CACTI1, S_CACTI2, S_CACTI3, @@ -2457,8 +2457,10 @@ typedef enum state S_CACTI9, S_CACTI10, S_CACTI11, + S_CACTITINYSEG, + S_CACTISMALLSEG, - // Warning signs sprites + // Warning signs S_ARIDSIGN_CAUTION, S_ARIDSIGN_CACTI, S_ARIDSIGN_SHARPTURN, @@ -4254,17 +4256,19 @@ typedef enum mobj_type // Arid Canyon Scenery MT_BIGTUMBLEWEED, MT_LITTLETUMBLEWEED, - MT_CACTI1, - MT_CACTI2, - MT_CACTI3, - MT_CACTI4, - MT_CACTI5, // Harmful Cactus 1 - MT_CACTI6, // Harmful Cactus 2 - MT_CACTI7, // Harmful Cactus 3 - MT_CACTI8, // Harmful Cactus 4 - MT_CACTI9, // Harmful Cactus 5 - MT_CACTI10, // Harmful Cactus 6 - MT_CACTI11, // Harmful Cactus 7 + MT_CACTI1, // Tiny Red Flower Cactus + MT_CACTI2, // Small Red Flower Cactus + MT_CACTI3, // Tiny Blue Flower Cactus + MT_CACTI4, // Small Blue Flower Cactus + MT_CACTI5, // Prickly Pear + MT_CACTI6, // Barrel Cactus + MT_CACTI7, // Tall Barrel Cactus + MT_CACTI8, // Armed Cactus + MT_CACTI9, // Ball Cactus + MT_CACTI10, // Tiny Cactus + MT_CACTI11, // Small Cactus + MT_CACTITINYSEG, // Tiny Cactus Segment + MT_CACTISMALLSEG, // Small Cactus Segment MT_ARIDSIGN_CAUTION, // Caution Sign MT_ARIDSIGN_CACTI, // Cacti Sign MT_ARIDSIGN_SHARPTURN, // Sharp Turn Sign From 5015f8e14272c922fc002897668019d1a49239b5 Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 19 Sep 2019 17:34:04 +0800 Subject: [PATCH 116/133] Added Camera Options submenu (provided my files aren't broken again (please D:)) --- src/m_menu.c | 85 +++++++++++++++++++++++++++++++++++++++++----------- src/m_menu.h | 4 +++ src/p_user.c | 4 +-- 3 files changed, 73 insertions(+), 20 deletions(-) mode change 100644 => 100755 src/m_menu.c mode change 100644 => 100755 src/m_menu.h diff --git a/src/m_menu.c b/src/m_menu.c old mode 100644 new mode 100755 index e9c5715fc..4350d6c73 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -275,9 +275,10 @@ menu_t MP_MainDef; // Split into multiple parts due to size // Controls menu_t OP_ChangeControlsDef; -menu_t OP_MPControlsDef, OP_CameraControlsDef, OP_MiscControlsDef; +menu_t OP_MPControlsDef, OP_MiscControlsDef; menu_t OP_P1ControlsDef, OP_P2ControlsDef, OP_MouseOptionsDef; menu_t OP_Mouse2OptionsDef, OP_Joystick1Def, OP_Joystick2Def; +menu_t OP_CameraOptionsDef, OP_Camera2OptionsDef; static void M_VideoModeMenu(INT32 choice); static void M_Setup1PControlsMenu(INT32 choice); static void M_Setup2PControlsMenu(INT32 choice); @@ -1002,14 +1003,11 @@ static menuitem_t OP_P1ControlsMenu[] = {IT_SUBMENU | IT_STRING, NULL, "Mouse Options...", &OP_MouseOptionsDef, 20}, {IT_SUBMENU | IT_STRING, NULL, "Gamepad Options...", &OP_Joystick1Def , 30}, - {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam , 50}, - {IT_STRING | IT_CVAR, NULL, "Third-person Orbital" , &cv_cam_orbit , 60}, - {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam , 70}, - {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 80}, + {IT_SUBMENU | IT_STRING, NULL, "Camera Options...", &OP_CameraOptionsDef, 50}, //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog, 100}, - {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar, 100}, - {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake, 110}, + {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar, 70}, + {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake, 80}, }; static menuitem_t OP_P2ControlsMenu[] = @@ -1018,14 +1016,11 @@ static menuitem_t OP_P2ControlsMenu[] = {IT_SUBMENU | IT_STRING, NULL, "Second Mouse Options...", &OP_Mouse2OptionsDef, 20}, {IT_SUBMENU | IT_STRING, NULL, "Second Gamepad Options...", &OP_Joystick2Def , 30}, - {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam2 , 50}, - {IT_STRING | IT_CVAR, NULL, "Third-person Orbital" , &cv_cam2_orbit , 60}, - {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam2 , 70}, - {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 80}, + {IT_SUBMENU | IT_STRING, NULL, "Camera Options...", &OP_Camera2OptionsDef, 50}, //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog2, 100}, - {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar2, 100}, - {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake2, 110}, + {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar2, 70}, + {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake2, 80}, }; static menuitem_t OP_ChangeControlsMenu[] = @@ -1154,6 +1149,34 @@ static menuitem_t OP_Mouse2OptionsMenu[] = NULL, "Mouse Y Sensitivity", &cv_mouseysens2, 80}, }; +static menuitem_t OP_CameraOptionsMenu[] = +{ + {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam , 10}, + {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam , 20}, + {IT_STRING | IT_CVAR, NULL, "Orbital Looking" , &cv_cam_orbit , 30}, + {IT_STRING | IT_CVAR, NULL, "Downhill Slope Adjustment", &cv_cam_adjust, 40}, + + {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Distance", &cv_cam_dist, 60}, + {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Height", &cv_cam_height, 70}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Speed", &cv_cam_speed, 80}, + + {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 100}, +}; + +static menuitem_t OP_Camera2OptionsMenu[] = +{ + {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam2 , 10}, + {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam2 , 20}, + {IT_STRING | IT_CVAR, NULL, "Orbital Looking" , &cv_cam2_orbit , 30}, + {IT_STRING | IT_CVAR, NULL, "Downhill Slope Adjustment", &cv_cam2_adjust, 40}, + + {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Distance", &cv_cam2_dist, 60}, + {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Height", &cv_cam2_height, 70}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Speed", &cv_cam2_speed, 80}, + + {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 100}, +}; + static menuitem_t OP_VideoOptionsMenu[] = { {IT_HEADER, NULL, "Screen", NULL, 0}, @@ -1879,6 +1902,13 @@ menu_t OP_JoystickSetDef = 0, NULL }; +menu_t OP_CameraOptionsDef = DEFAULTMENUSTYLE( + MN_OP_MAIN + (MN_OP_P1CONTROLS << 6) + (MN_OP_P1CAMERA << 12), + "M_CONTRO", OP_CameraOptionsMenu, &OP_P1ControlsDef, 35, 30); +menu_t OP_Camera2OptionsDef = DEFAULTMENUSTYLE( + MN_OP_MAIN + (MN_OP_P2CONTROLS << 6) + (MN_OP_P2CAMERA << 12), + "M_CONTRO", OP_Camera2OptionsMenu, &OP_P2ControlsDef, 35, 30); + menu_t OP_VideoOptionsDef = { @@ -2740,13 +2770,27 @@ static void M_ChangeCvar(INT32 choice) ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_INVISSLIDER) ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_NOMOD)) { - CV_SetValue(cv,cv->value+(choice)); + if (cv->flags & CV_FLOAT && (currentMenu->menuitems[itemOn].status & IT_CV_FLOATSLIDER) == IT_CV_FLOATSLIDER) + { + char s[20]; + sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f)); + CV_Set(cv,s); + } + else + CV_SetValue(cv,cv->value+(choice)); } else if (cv->flags & CV_FLOAT) { - char s[20]; - sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f)); - CV_Set(cv,s); + if (currentMenu->menuitems[itemOn].status & IT_CV_INTEGERSTEP) + { + CV_SetValue(cv,FIXED_TO_FLOAT(cv->value)+(choice)); + } + else + { + char s[20]; + sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f)); + CV_Set(cv,s); + } } else CV_AddValue(cv,choice); @@ -3636,7 +3680,12 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop) for (i = 0; cv->PossibleValue[i+1].strvalue; i++); - if ((range = atoi(cv->defaultvalue)) != cv->value) + if (cv->flags & CV_FLOAT) + range = (INT32)(atof(cv->defaultvalue)*FRACUNIT); + else + range = atoi(cv->defaultvalue); + + if (range != cv->value) { range = ((range - cv->PossibleValue[0].value) * 100 / (cv->PossibleValue[i].value - cv->PossibleValue[0].value)); diff --git a/src/m_menu.h b/src/m_menu.h old mode 100644 new mode 100755 index 347725e10..67b1ddb94 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -72,10 +72,12 @@ typedef enum MN_OP_P1MOUSE, MN_OP_P1JOYSTICK, MN_OP_JOYSTICKSET, // OP_JoystickSetDef shared with P2 + MN_OP_P1CAMERA, MN_OP_P2CONTROLS, MN_OP_P2MOUSE, MN_OP_P2JOYSTICK, + MN_OP_P2CAMERA, MN_OP_VIDEO, MN_OP_VIDEOMODE, @@ -242,6 +244,8 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); #define IT_CV_NOPRINT 1536 #define IT_CV_NOMOD 2048 #define IT_CV_INVISSLIDER 2560 +#define IT_CV_INTEGERSTEP 4096 // if IT_CV_NORMAL and cvar is CV_FLOAT, modify it by 1 instead of 0.0625 +#define IT_CV_FLOATSLIDER 4608 // IT_CV_SLIDER, value modified by 0.0625 instead of 1 (for CV_FLOAT cvars) //call/submenu specific // There used to be a lot more here but ... diff --git a/src/p_user.c b/src/p_user.c index 13450bc9f..22cc919ab 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9295,7 +9295,7 @@ consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NUL consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_orbit = {"cam_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam_adjust = {"cam_adjust", "Off", CV_SAVE|CV_SHOWMODIF, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_adjust = {"cam_adjust", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_height = {"cam2_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -9303,7 +9303,7 @@ consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, N consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_orbit = {"cam2_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam2_adjust = {"cam2_adjust", "Off", CV_SAVE|CV_SHOWMODIF, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam2_adjust = {"cam2_adjust", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; fixed_t t_cam_dist = -42; fixed_t t_cam_height = -42; From cf14d5fe5d4290f52e4ea04519edcc705ac6750a Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 19 Sep 2019 12:30:30 +0100 Subject: [PATCH 117/133] * Remove sounds from swimming. * Lower default swim animation speed. * Make speed of flight/swim animation increase whenever mashing jump. --- src/info.c | 2 +- src/p_user.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index 0fea743f6..05204fc86 100644 --- a/src/info.c +++ b/src/info.c @@ -739,7 +739,7 @@ state_t states[NUMSTATES] = // CA_FLY/CA_SWIM {SPR_PLAY, SPR2_FLY , 2, {NULL}, 0, 0, S_PLAY_FLY}, // S_PLAY_FLY - {SPR_PLAY, SPR2_SWIM, 2, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM + {SPR_PLAY, SPR2_SWIM, 4, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM {SPR_PLAY, SPR2_TIRE, 12, {NULL}, 0, 0, S_PLAY_FLY_TIRED}, // S_PLAY_FLY_TIRED // CA_GLIDEANDCLIMB diff --git a/src/p_user.c b/src/p_user.c index e0a4d710c..83c154fdf 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8180,12 +8180,18 @@ static void P_MovePlayer(player_t *player) if (P_MobjFlip(player->mo)*player->mo->momz < FixedMul(5*actionspd, player->mo->scale)) P_SetObjectMomZ(player->mo, actionspd/2, true); + P_SetPlayerMobjState(player->mo, player->mo->state->nextstate); + player->fly1--; } } // Tails Put-Put noise - if (player->charability == CA_FLY && player->bot != 1 && leveltime % 10 == 0 && !player->spectator) + if (player->charability == CA_FLY + && player->bot != 1 + && !(player->mo->eflags & MFE_UNDERWATER) + && leveltime % 10 == 0 + && !player->spectator) S_StartSound(player->mo, sfx_putput); // Descend @@ -8202,6 +8208,7 @@ static void P_MovePlayer(player_t *player) if (player->charability == CA_FLY && (leveltime % 10 == 0) && player->mo->state-states == S_PLAY_FLY_TIRED + && !(player->mo->eflags & MFE_UNDERWATER) && !player->spectator) S_StartSound(player->mo, sfx_pudpud); } @@ -10736,8 +10743,10 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) } } +#if 0 if (player->fly1 != 0 && player->powers[pw_tailsfly] != 0 && !smilesonground) P_SetMobjState(tails, chosenstate); +#endif // animation... if (player->panim == PA_SPRING || player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE) @@ -10752,7 +10761,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) else if (player->mo->state-states == S_PLAY_GASP) tails->tics = -1; else if (player->mo->sprite2 == SPR2_TIRE) - ticnum = 4; + ticnum = (doswim ? 2 : 4); else if (player->panim != PA_IDLE) ticnum = player->mo->tics; From ca9e6e31dab7ee71a74c68e3a1dd992df933fb46 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 19 Sep 2019 13:20:05 +0100 Subject: [PATCH 118/133] * Resolve #224 (landing frames on ceiling contact). * Fix some other landing weirdness with CA_BOUNCE. --- src/p_map.c | 7 +- src/p_user.c | 283 ++++++++++++++++++++++++++------------------------- 2 files changed, 146 insertions(+), 144 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index dfac3ae05..01c41131b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2881,11 +2881,8 @@ static boolean P_ThingHeightClip(mobj_t *thing) thing->z = thing->ceilingz - thing->height; } - if (thing->z != oldz) - { - if (thing->player) - P_PlayerHitFloor(thing->player, !onfloor); - } + if (P_MobjFlip(thing)*(thing->z - oldz) > 0 && thing->player) + P_PlayerHitFloor(thing->player, !onfloor); // debug: be sure it falls to the floor thing->eflags &= ~MFE_ONGROUND; diff --git a/src/p_user.c b/src/p_user.c index 83c154fdf..572cf01fb 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2217,148 +2217,153 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) player->pflags &= ~PF_SPINNING; } - if (player->pflags & PF_SPINNING) - { - if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH)) - { - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_spin); - } - } - else if (player->pflags & PF_GLIDING) // ground gliding - { - if (dorollstuff) - { - player->skidtime = TICRATE; - player->mo->tics = -1; - } - else if (!player->skidtime) - player->pflags &= ~PF_GLIDING; - } - else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) - { - if (player->mo->state-states != S_PLAY_MELEE_LANDING) - { - mobjtype_t type = player->revitem; - P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); - player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; - S_StartSound(player->mo, sfx_s3k8b); - player->pflags |= PF_FULLSTASIS; - - // hearticles - if (type) - { - UINT8 i = 0; - angle_t throwang = -(2*ANG30); - fixed_t xo = P_ReturnThrustX(player->mo, player->drawangle, 16*player->mo->scale); - fixed_t yo = P_ReturnThrustY(player->mo, player->drawangle, 16*player->mo->scale); - fixed_t zo = 6*player->mo->scale; - fixed_t mu = FixedMul(player->maxdash, player->mo->scale); - fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); - fixed_t ev; - mobj_t *missile = NULL; - if (mu2 < mu) - mu2 = mu; - ev = (50*FRACUNIT - (mu/25))/50; - while (i < 5) - { - missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); - P_SetTarget(&missile->target, player->mo); - missile->angle = throwang + player->drawangle; - P_Thrust(missile, player->drawangle + ANGLE_90, - P_ReturnThrustY(missile, throwang, mu)); // side to side component - P_Thrust(missile, player->drawangle, mu2); // forward component - P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); - missile->momz += player->mo->pmomz; - missile->fuse = TICRATE/2; - missile->extravalue2 = ev; - - i++; - throwang += ANG30; - } - if (mobjinfo[type].seesound && missile) - S_StartSound(missile, missile->info->seesound); - } - } - } - else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2) - ; - else if (player->panim != PA_IDLE && player->panim != PA_WALK && player->panim != PA_RUN && player->panim != PA_DASH) - { - if (player->cmomx || player->cmomy) - { - if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); - else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) - && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN); - else if ((player->rmomx || player->rmomy) - && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) - P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE) - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - } - else - { - if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); - else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) - && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN); - else if ((player->mo->momx || player->mo->momy) - && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) - P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE) - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - } - } - - if (!(player->pflags & PF_GLIDING)) - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); - player->pflags &= ~(PF_STARTJUMP|PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/); - player->secondjump = 0; - player->glidetime = 0; - player->climbing = 0; - player->powers[pw_tailsfly] = 0; - - if (player->pflags & PF_SHIELDABILITY) - { - player->pflags &= ~PF_SHIELDABILITY; - - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) // Elemental shield's stomp attack. - { - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) // play a blunt sound - S_StartSound(player->mo, sfx_s3k4c); - else // create a fire pattern on the ground - { - S_StartSound(player->mo, sfx_s3k47); - P_ElementalFire(player, true); - } - P_SetObjectMomZ(player->mo, - (player->mo->eflags & MFE_UNDERWATER) - ? 6*FRACUNIT/5 - : 5*FRACUNIT/2, - false); - P_SetPlayerMobjState(player->mo, S_PLAY_FALL); - player->mo->momx = player->mo->momy = 0; - clipmomz = false; - } - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) // Bubble shield's bounce attack. - { - P_DoBubbleBounce(player); - clipmomz = false; - } - } - if (player->pflags & PF_BOUNCING) { - P_MobjCheckWater(player->mo); - player->mo->momz *= -1; - P_DoAbilityBounce(player, true); - if (player->scoreadd) - player->scoreadd--; + if (dorollstuff && player->mo->state-states != S_PLAY_BOUNCE_LANDING) + { + P_MobjCheckWater(player->mo); + player->mo->momz *= -1; + P_DoAbilityBounce(player, true); + if (player->scoreadd) + player->scoreadd--; + } clipmomz = false; } + else + { + if (player->pflags & PF_SPINNING) + { + if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH)) + { + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_spin); + } + } + else if (player->pflags & PF_GLIDING) // ground gliding + { + if (dorollstuff) + { + player->skidtime = TICRATE; + player->mo->tics = -1; + } + else if (!player->skidtime) + player->pflags &= ~PF_GLIDING; + } + else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) + { + if (player->mo->state-states != S_PLAY_MELEE_LANDING) + { + mobjtype_t type = player->revitem; + P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); + player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; + S_StartSound(player->mo, sfx_s3k8b); + player->pflags |= PF_FULLSTASIS; + + // hearticles + if (type) + { + UINT8 i = 0; + angle_t throwang = -(2*ANG30); + fixed_t xo = P_ReturnThrustX(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t yo = P_ReturnThrustY(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t zo = 6*player->mo->scale; + fixed_t mu = FixedMul(player->maxdash, player->mo->scale); + fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); + fixed_t ev; + mobj_t *missile = NULL; + if (mu2 < mu) + mu2 = mu; + ev = (50*FRACUNIT - (mu/25))/50; + while (i < 5) + { + missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); + P_SetTarget(&missile->target, player->mo); + missile->angle = throwang + player->drawangle; + P_Thrust(missile, player->drawangle + ANGLE_90, + P_ReturnThrustY(missile, throwang, mu)); // side to side component + P_Thrust(missile, player->drawangle, mu2); // forward component + P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); + missile->momz += player->mo->pmomz; + missile->fuse = TICRATE/2; + missile->extravalue2 = ev; + + i++; + throwang += ANG30; + } + if (mobjinfo[type].seesound && missile) + S_StartSound(missile, missile->info->seesound); + } + } + } + else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2) + ; + else if (player->panim != PA_IDLE && player->panim != PA_WALK && player->panim != PA_RUN && player->panim != PA_DASH) + { + if (player->cmomx || player->cmomy) + { + if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) + P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) + && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) + P_SetPlayerMobjState(player->mo, S_PLAY_RUN); + else if ((player->rmomx || player->rmomy) + && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE) + P_SetPlayerMobjState(player->mo, S_PLAY_STND); + } + else + { + if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) + P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) + && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) + P_SetPlayerMobjState(player->mo, S_PLAY_RUN); + else if ((player->mo->momx || player->mo->momy) + && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE) + P_SetPlayerMobjState(player->mo, S_PLAY_STND); + } + } + + if (!(player->pflags & PF_GLIDING)) + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); + player->pflags &= ~(PF_STARTJUMP|PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/); + player->secondjump = 0; + player->glidetime = 0; + player->climbing = 0; + player->powers[pw_tailsfly] = 0; + + if (player->pflags & PF_SHIELDABILITY) + { + player->pflags &= ~PF_SHIELDABILITY; + + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) // Elemental shield's stomp attack. + { + if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) // play a blunt sound + S_StartSound(player->mo, sfx_s3k4c); + else // create a fire pattern on the ground + { + S_StartSound(player->mo, sfx_s3k47); + P_ElementalFire(player, true); + } + P_SetObjectMomZ(player->mo, + (player->mo->eflags & MFE_UNDERWATER) + ? 6*FRACUNIT/5 + : 5*FRACUNIT/2, + false); + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + player->mo->momx = player->mo->momy = 0; + clipmomz = false; + } + else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) // Bubble shield's bounce attack. + { + P_DoBubbleBounce(player); + clipmomz = false; + } + } + } } return clipmomz; @@ -8080,7 +8085,7 @@ static void P_MovePlayer(player_t *player) } else if (player->pflags & PF_BOUNCING) { - if (!(player->pflags & PF_JUMPDOWN) || (onground && P_MobjFlip(player->mo)*player->mo->momz <= 0)) // If not holding the jump button OR on flat ground + if (!(player->pflags & PF_JUMPDOWN)) // If not holding the jump button { P_ResetPlayer(player); // down, stop bouncing. player->pflags |= PF_THOKKED; From f8475eef26f4197d32a55cff19ded58e2fbdff3d Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 19 Sep 2019 13:20:52 +0100 Subject: [PATCH 119/133] Disable some code which sometimes makes the player enter walking frames when jumping up to a platform, such as the CEZ3 buttons, despite still being in jumping mode. If this causes more problems than it solves it can be reverted, but doing a bunch of playthroughs of DSZ1/2, GFZ1, and CEZ3 didn't seem to uncover anything, so I'm tentatively putting it in this branch. --- src/p_mobj.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 994ddcfe7..4cede843c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4001,6 +4001,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) } else { +#if 0 // i don't know why this is here, it's causing a few undesired state glitches, and disabling it doesn't appear to negatively affect the game, but i don't want it gone permanently just in case some obscure bug crops up if (!(mobj->player->powers[pw_carry] == CR_NIGHTSMODE)) // used for drilling mobj->player->pflags &= ~PF_STARTJUMP; mobj->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); @@ -4010,6 +4011,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->player->powers[pw_tailsfly] = 0; P_SetPlayerMobjState(mobj, S_PLAY_WALK); } +#endif mobj->eflags &= ~MFE_JUSTHITFLOOR; } From a3ea2274f42e9a7b4ab023c850dbc4e2f62dc629 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 19 Sep 2019 17:43:23 +0100 Subject: [PATCH 120/133] Fix inconsistency between score tally screen and timerres cvar (Resolves #213). --- src/y_inter.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index 1cb1b9cd8..0d6a3d03c 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -261,7 +261,7 @@ void Y_IntermissionDrawer(void) // draw time ST_DrawPatchFromHud(HUD_TIME, sbotime); - if (cv_timetic.value == 1) + if (cv_timetic.value == 3) ST_DrawNumFromHud(HUD_SECONDS, data.coop.tics); else { @@ -275,8 +275,7 @@ void Y_IntermissionDrawer(void) ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon); // Colon ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2); // Seconds - // we should show centiseconds on the intermission screen too, if the conditions are right. - if (modeattacking || cv_timetic.value == 2) + if (cv_timetic.value == 1 || cv_timetic.value == 2 || modeattacking) // there's not enough room for tics in splitscreen, don't even bother trying! { ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics From 802ddf94b15e6d4b1c5513f0a7cae554357727dd Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 19 Sep 2019 18:44:55 +0100 Subject: [PATCH 121/133] Always pretend cv_playersforexit is 4 in co-op special stages. --- src/p_user.c | 5 +++-- src/st_stuff.c | 60 +++++++++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 572cf01fb..0438075f2 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10989,7 +10989,8 @@ void P_PlayerThink(player_t *player) if (player->exiting == 2 || countdown2 == 2) { - if (cv_playersforexit.value) // Count to be sure everyone's exited + UINT8 numneeded = (G_IsSpecialStage(gamemap) ? 4 : cv_playersforexit.value); + if (numneeded) // Count to be sure everyone's exited { INT32 i, total = 0, exiting = 0; @@ -11005,7 +11006,7 @@ void P_PlayerThink(player_t *player) exiting++; } - if (!total || ((4*exiting)/total) >= cv_playersforexit.value) + if (!total || ((4*exiting)/total) >= numneeded) { if (server) SendNetXCmd(XD_EXITLEVEL, NULL, 0); diff --git a/src/st_stuff.c b/src/st_stuff.c index c4f1327c0..20a132b3a 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2100,39 +2100,43 @@ static void ST_drawTextHUD(void) textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) } - if (gametype == GT_COOP && (!stplyr->spectator || (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))) && stplyr->exiting && cv_playersforexit.value) + if (gametype == GT_COOP && (!stplyr->spectator || (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))) && stplyr->exiting) { - INT32 i, total = 0, exiting = 0; - - for (i = 0; i < MAXPLAYERS; i++) + UINT8 numneeded = (G_IsSpecialStage(gamemap) ? 4 : cv_playersforexit.value); + if (numneeded) { - if (!playeringame[i] || players[i].spectator) - continue; - if (players[i].lives <= 0) - continue; + INT32 i, total = 0, exiting = 0; - total++; - if (players[i].exiting) - exiting++; - } - - if (cv_playersforexit.value != 4) - { - total *= cv_playersforexit.value; - if (total & 3) - total += 4; // round up - total /= 4; - } - - if (exiting < total) - { - if (!splitscreen && !donef12) + for (i = 0; i < MAXPLAYERS; i++) { - textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) - donef12 = true; + if (!playeringame[i] || players[i].spectator) + continue; + if (players[i].lives <= 0) + continue; + + total++; + if (players[i].exiting) + exiting++; + } + + if (numneeded != 4) + { + total *= cv_playersforexit.value; + if (total & 3) + total += 4; // round up + total /= 4; + } + + if (exiting < total) + { + if (!splitscreen && !donef12) + { + textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) + donef12 = true; + } + total -= exiting; + textHUDdraw(va(M_GetText("%d player%s remaining"), total, ((total == 1) ? "" : "s"))) } - total -= exiting; - textHUDdraw(va(M_GetText("%d player%s remaining"), total, ((total == 1) ? "" : "s"))) } } else if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator)) From 222d4f2b7c85efde262280dbca9476cc1de3f22f Mon Sep 17 00:00:00 2001 From: lachwright Date: Fri, 20 Sep 2019 02:02:17 +0800 Subject: [PATCH 122/133] Improved orbital camera in Software; cam_adjust cvars changed to on by default --- src/p_user.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 22cc919ab..c3f862952 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9295,7 +9295,7 @@ consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NUL consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_orbit = {"cam_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam_adjust = {"cam_adjust", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_adjust = {"cam_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_height = {"cam2_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -9303,7 +9303,7 @@ consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, N consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_orbit = {"cam2_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam2_adjust = {"cam2_adjust", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam2_adjust = {"cam2_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; fixed_t t_cam_dist = -42; fixed_t t_cam_height = -42; @@ -9359,7 +9359,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall angle_t angle = 0, focusangle = 0, focusaiming = 0; fixed_t x, y, z, dist, distxy, distz, checkdist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight, slopez = 0; INT32 camrotate; - boolean camstill, cameranoclip; + boolean camstill, cameranoclip, camorbit; mobj_t *mo; subsector_t *newsubsec; fixed_t f1, f2; @@ -9440,6 +9440,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // force defaults because we have a camera look section camspeed = (INT32)(atof(cv_cam_speed.defaultvalue) * FRACUNIT); camstill = (!stricmp(cv_cam_still.defaultvalue, "off")) ? false : true; + camorbit = (!stricmp(cv_cam_orbit.defaultvalue, "off")) ? false : true; camrotate = atoi(cv_cam_rotate.defaultvalue); camdist = FixedMul((INT32)(atof(cv_cam_dist.defaultvalue) * FRACUNIT), mo->scale); camheight = FixedMul((INT32)(atof(cv_cam_height.defaultvalue) * FRACUNIT), FixedMul(player->camerascale, mo->scale)); @@ -9448,6 +9449,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall { camspeed = cv_cam_speed.value; camstill = cv_cam_still.value; + camorbit = cv_cam_orbit.value; camrotate = cv_cam_rotate.value; camdist = FixedMul(cv_cam_dist.value, mo->scale); camheight = FixedMul(cv_cam_height.value, FixedMul(player->camerascale, mo->scale)); @@ -9456,6 +9458,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall { camspeed = cv_cam2_speed.value; camstill = cv_cam2_still.value; + camorbit = cv_cam2_orbit.value; camrotate = cv_cam2_rotate.value; camdist = FixedMul(cv_cam2_dist.value, mo->scale); camheight = FixedMul(cv_cam2_height.value, FixedMul(player->camerascale, mo->scale)); @@ -9595,7 +9598,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if ((thiscam == &camera && cv_cam_orbit.value) || (thiscam == &camera2 && cv_cam2_orbit.value)) //Sev here, I'm guessing this is where orbital cam lives { - distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); + if (rendermode == render_opengl) + distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); + else + distxy = dist; distz = -FixedMul(dist, FINESINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)) + slopez; } else From 4c7a7a7e0b77c5beea1f09a07a47249014b8a261 Mon Sep 17 00:00:00 2001 From: sphere Date: Fri, 20 Sep 2019 00:51:44 +0200 Subject: [PATCH 123/133] Small DSZ coral tweaks. --- src/dehacked.c | 16 +++++----- src/info.c | 86 +++++++++++++++++++++++++++++++++++++++----------- src/info.h | 22 ++++++------- 3 files changed, 86 insertions(+), 38 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index a65a2249b..8334de61a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5578,14 +5578,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_DRIPC1", "S_DRIPC2", - // Coral 1 + // Coral "S_CORAL1", - - // Coral 2 "S_CORAL2", - - // Coral 3 "S_CORAL3", + "S_CORAL4", + "S_CORAL5", // Blue Crystal "S_BLUECRYSTAL1", @@ -7464,9 +7462,11 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_SEAWEED", // DSZ Seaweed "MT_WATERDRIP", // Dripping Water source "MT_WATERDROP", // Water drop from dripping water - "MT_CORAL1", // Coral 1 - "MT_CORAL2", // Coral 2 - "MT_CORAL3", // Coral 3 + "MT_CORAL1", // Coral + "MT_CORAL2", + "MT_CORAL3", + "MT_CORAL4", + "MT_CORAL5", "MT_BLUECRYSTAL", // Blue Crystal "MT_KELP", // Kelp "MT_ANIMALGAETOP", // Animated algae top diff --git a/src/info.c b/src/info.c index 10ace455d..e627b949d 100644 --- a/src/info.c +++ b/src/info.c @@ -212,9 +212,7 @@ char sprnames[NUMSPRITES + 1][5] = "GARG", // Deep Sea Gargoyle "SEWE", // Deep Sea Seaweed "DRIP", // Dripping water - "CRL1", // Coral 1 - "CRL2", // Coral 2 - "CRL3", // Coral 3 + "CORL", // Coral "BCRY", // Blue Crystal "KELP", // Kelp "ALGA", // Animated algae top @@ -248,7 +246,7 @@ char sprnames[NUMSPRITES + 1][5] = // Arid Canyon Scenery "BTBL", // Big tumbleweed "STBL", // Small tumbleweed - "CACT", // Cacti sprites + "CACT", // Cacti "WWSG", // Caution Sign "WWS2", // Cacti Sign "WWS3", // Sharp Turn Sign @@ -2166,14 +2164,12 @@ state_t states[NUMSTATES] = {SPR_DRIP, FF_TRANS30|4, 1, {NULL}, 0, 0, S_DRIPC2}, // S_DRIPC1 {SPR_DRIP, FF_TRANS30|5, 1, {NULL}, 0, 0, S_NULL}, // S_DRIPC2 - // Coral 1 - {SPR_CRL1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL1 - - // Coral 2 - {SPR_CRL2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL2 - - // Coral 3 - {SPR_CRL3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL3 + // Coral + {SPR_CORL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL1 + {SPR_CORL, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL2 + {SPR_CORL, 2, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL3 + {SPR_CORL, 3, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL4 + {SPR_CORL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL5 // Blue Crystal {SPR_BCRY, FF_TRANS30, -1, {NULL}, 0, 0, S_NULL}, // S_BLUECRYSTAL1 @@ -10093,8 +10089,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height + 29*FRACUNIT, // radius + 40*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage @@ -10120,8 +10116,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height + 30*FRACUNIT, // radius + 53*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage @@ -10147,8 +10143,62 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height + 28*FRACUNIT, // radius + 41*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_CORAL4 + 1014, // doomednum + S_CORAL4, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 56*FRACUNIT, // radius + 112*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_CORAL5 + 1015, // doomednum + S_CORAL5, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 56*FRACUNIT, // radius + 112*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage diff --git a/src/info.h b/src/info.h index e125b05f3..74e4b87a2 100644 --- a/src/info.h +++ b/src/info.h @@ -458,9 +458,7 @@ typedef enum sprite SPR_GARG, // Deep Sea Gargoyle SPR_SEWE, // Deep Sea Seaweed SPR_DRIP, // Dripping water - SPR_CRL1, // Coral 1 - SPR_CRL2, // Coral 2 - SPR_CRL3, // Coral 3 + SPR_CORL, // Coral SPR_BCRY, // Blue Crystal SPR_KELP, // Kelp SPR_ALGA, // Animated algae top @@ -494,7 +492,7 @@ typedef enum sprite // Arid Canyon Scenery SPR_BTBL, // Big tumbleweed SPR_STBL, // Small tumbleweed - SPR_CACT, // Cacti sprites + SPR_CACT, // Cacti SPR_WWSG, // Caution Sign SPR_WWS2, // Cacti Sign SPR_WWS3, // Sharp Turn Sign @@ -2291,14 +2289,12 @@ typedef enum state S_DRIPC1, S_DRIPC2, - // Coral 1 + // Coral S_CORAL1, - - // Coral 2 S_CORAL2, - - // Coral 3 S_CORAL3, + S_CORAL4, + S_CORAL5, // Blue Crystal S_BLUECRYSTAL1, @@ -4199,9 +4195,11 @@ typedef enum mobj_type MT_SEAWEED, // DSZ Seaweed MT_WATERDRIP, // Dripping Water source MT_WATERDROP, // Water drop from dripping water - MT_CORAL1, // Coral 1 - MT_CORAL2, // Coral 2 - MT_CORAL3, // Coral 3 + MT_CORAL1, // Coral + MT_CORAL2, + MT_CORAL3, + MT_CORAL4, + MT_CORAL5, MT_BLUECRYSTAL, // Blue Crystal MT_KELP, // Kelp MT_ANIMALGAETOP, // Animated algae top From ef7e8c5d588f12f4827ad6dee870550b9d7a09c7 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Sep 2019 22:40:23 -0300 Subject: [PATCH 124/133] use byteptr.h macros --- src/r_data.c | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index be27fecad..9c5a574b4 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -23,6 +23,7 @@ #include "z_zone.h" #include "p_setup.h" // levelflats #include "v_video.h" // pMasterPalette +#include "byteptr.h" #include "dehacked.h" #ifdef _WIN32 @@ -2819,18 +2820,14 @@ patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean t UINT8 *imgptr = imgbuf; UINT8 *colpointers, *startofspan; - #define WRITE8(buf, a) ({*buf = (a); buf++;}) - #define WRITE16(buf, a) ({*buf = (a)&255; buf++; *buf = (a)>>8; buf++;}) - #define WRITE32(buf, a) ({WRITE16(buf, (a)&65535); WRITE16(buf, (a)>>16);}) - if (!raw) I_Error("R_PNGToPatch: conversion failed"); // Write image size and offset - WRITE16(imgptr, width); - WRITE16(imgptr, height); - WRITE16(imgptr, leftoffset); - WRITE16(imgptr, topoffset); + WRITEINT16(imgptr, width); + WRITEINT16(imgptr, height); + WRITEINT16(imgptr, leftoffset); + WRITEINT16(imgptr, topoffset); // Leave placeholder to column pointers colpointers = imgptr; @@ -2845,7 +2842,7 @@ patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean t //printf("%d ", x); // Write column pointer (@TODO may be wrong) - WRITE32(colpointers, imgptr - imgbuf); + WRITEINT32(colpointers, imgptr - imgbuf); // Write pixels for (y = 0; y < height; y++) @@ -2857,7 +2854,7 @@ patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean t if (!opaque) { if (startofspan) - WRITE8(imgptr, 0); + WRITEUINT8(imgptr, 0); startofspan = NULL; continue; } @@ -2869,15 +2866,15 @@ patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean t // If we reached the span size limit, finish the previous span if (startofspan) - WRITE8(imgptr, 0); + WRITEUINT8(imgptr, 0); if (y > 254) { // Make sure we're aligned to 254 if (lastStartY < 254) { - WRITE8(imgptr, 254); - WRITE8(imgptr, 0); + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); imgptr += 2; lastStartY = 254; } @@ -2887,15 +2884,15 @@ patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean t while (writeY > 254) { - WRITE8(imgptr, 254); - WRITE8(imgptr, 0); + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); imgptr += 2; writeY -= 254; } } startofspan = imgptr; - WRITE8(imgptr, writeY);///@TODO calculate starting y pos + WRITEUINT8(imgptr, writeY);///@TODO calculate starting y pos imgptr += 2; spanSize = 0; @@ -2903,21 +2900,17 @@ patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean t } // Write the pixel - WRITE8(imgptr, paletteIndex); + WRITEUINT8(imgptr, paletteIndex); spanSize++; startofspan[1] = spanSize; } if (startofspan) - WRITE8(imgptr, 0); + WRITEUINT8(imgptr, 0); - WRITE8(imgptr, 0xFF); + WRITEUINT8(imgptr, 0xFF); } - #undef WRITE8 - #undef WRITE16 - #undef WRITE32 - size = imgptr-imgbuf; img = Z_Malloc(size, PU_STATIC, NULL); memcpy(img, imgbuf, size); From 530b5784b8bc6021b9577ae48ad8877a5ff6a953 Mon Sep 17 00:00:00 2001 From: Alam Arias Date: Thu, 19 Sep 2019 21:42:59 -0400 Subject: [PATCH 125/133] platersprite_t is not the same as unsigned --- src/hardware/hw_md2.c | 2 +- src/r_things.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 7b6367cf3..db1c1f727 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1202,7 +1202,7 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p if (!md2 || !skin) return 0; - if ((unsigned)(spr2 & ~FF_SPR2SUPER) >= free_spr2) + if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) return 0; while (!(md2->model->spr2frames[spr2*2 + 1]) diff --git a/src/r_things.c b/src/r_things.c index 392821869..43e006a30 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2524,7 +2524,7 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) if (!skin) return 0; - if ((unsigned)(spr2 & ~FF_SPR2SUPER) >= free_spr2) + if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) return 0; while (!(skin->sprites[spr2].numframes) From 19e0e43e87472764eba7bad17991c56714492a01 Mon Sep 17 00:00:00 2001 From: lachwright Date: Fri, 20 Sep 2019 12:07:57 +0800 Subject: [PATCH 126/133] test?? --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index c3f862952..415fcc1ed 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9596,7 +9596,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } } - if ((thiscam == &camera && cv_cam_orbit.value) || (thiscam == &camera2 && cv_cam2_orbit.value)) //Sev here, I'm guessing this is where orbital cam lives + if (camorbit) //Sev here, I'm guessing this is where orbital cam lives { if (rendermode == render_opengl) distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); From 8d3d5566b802b78952535be8572224abd84ba44e Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Fri, 20 Sep 2019 12:18:57 -0400 Subject: [PATCH 127/133] Undo file mode change on menu files --- src/m_menu.c | 0 src/m_menu.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/m_menu.c mode change 100755 => 100644 src/m_menu.h diff --git a/src/m_menu.c b/src/m_menu.c old mode 100755 new mode 100644 diff --git a/src/m_menu.h b/src/m_menu.h old mode 100755 new mode 100644 From 113568095a609c662e33e67f311c94e28be127d9 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 20 Sep 2019 17:22:09 +0100 Subject: [PATCH 128/133] * Resolve compiling issues with logmessages. * Improve logfile print. (I know Steel wanted it gone entirely, but I feel like it's relevant to have it in game..?) --- src/sdl/i_main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index 2a67e88fe..029febc05 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -131,11 +131,12 @@ int main(int argc, char **argv) #ifdef LOGMESSAGES if (!M_CheckParm("-nolog")) { - logdir = D_Home(); - time_t my_time; struct tm * timeinfo; char buf[26]; + + logdir = D_Home(); + my_time = time(NULL); timeinfo = localtime(&my_time); @@ -183,8 +184,11 @@ int main(int argc, char **argv) // startup SRB2 CONS_Printf("Setting up SRB2...\n"); D_SRB2Main(); +#ifdef LOGMESSAGES + if (!M_CheckParm("-nolog")) + CONS_Printf("Logfile: %s\n", logfile); +#endif CONS_Printf("Entering main game loop...\n"); - CONS_Printf("%s\n", logfile); // never return D_SRB2Loop(); From 92779487a4130a244dbb90d12061a031ba5253d0 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Fri, 20 Sep 2019 12:32:18 -0400 Subject: [PATCH 129/133] avoid the source code from getting the wrong EOL --- .gitattributes | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.gitattributes b/.gitattributes index d45620912..7751149ac 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,12 @@ +#Source code +/src/*.c text=auto +/src/*.h text=auto +/src/*.s text=auto +/src/*.m text=auto +/src/*.xpm text=auto +/src/Makefile text=auto +/src/Make*.cfg text=auto +/src/CMakeLists.txt text=auto # Windows EOL *.cs -crlf -whitespace *.mk -crlf -whitespace From c36123aa5687c5151aad98fd1941412f7407ae52 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 20 Sep 2019 17:43:41 +0100 Subject: [PATCH 130/133] Mark new-style log names as loaded. --- src/filesrch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filesrch.c b/src/filesrch.c index 8f157bdd5..13d73b6f4 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -751,7 +751,7 @@ boolean preparefilemenu(boolean samedepth) } else if (ext == EXT_TXT) { - if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt")) + if (!strncmp(dent->d_name, "log-", 4) || !strcmp(dent->d_name, "errorlog.txt")) ext |= EXT_LOADED; } From f8c97aeb2775556b8b6e1c2167c668fffcf860b0 Mon Sep 17 00:00:00 2001 From: sphere Date: Sun, 22 Sep 2019 04:05:22 +0200 Subject: [PATCH 131/133] Tweak bubble grabbing behavior. --- src/p_inter.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 79491e245..bfdec3e23 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1701,13 +1701,15 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; if (mariomode) return; + if (special->state-states != S_EXTRALARGEBUBBLE) + return; // Don't grab the bubble during its spawn animation else if (toucher->eflags & MFE_VERTICALFLIP) { - if (special->z+special->height < toucher->z + toucher->height / 3 - || special->z+special->height > toucher->z + (toucher->height*2/3)) + if (special->z+special->height < toucher->z + || special->z+special->height > toucher->z + (toucher->height*2/3)) return; // Only go in the mouth } - else if (special->z < toucher->z + toucher->height / 3 + else if (special->z < toucher->z || special->z > toucher->z + (toucher->height*2/3)) return; // Only go in the mouth From f7ad5501e12db30beecc0eba7bf119280208ddd7 Mon Sep 17 00:00:00 2001 From: sphere Date: Sun, 22 Sep 2019 04:19:09 +0200 Subject: [PATCH 132/133] Increase emblem and token hitbox sizes. --- src/info.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/info.c b/src/info.c index dae028f62..da8022cd4 100644 --- a/src/info.c +++ b/src/info.c @@ -6504,8 +6504,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height + 16*FRACUNIT, // radius + 32*FRACUNIT, // height 0, // display offset 100, // mass 1, // damage @@ -6585,8 +6585,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_ncitem, // deathsound 1, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height + 16*FRACUNIT, // radius + 30*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage From 73146a833882f2041b0e59e26c6d764e9ac3aa5d Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 22 Sep 2019 20:30:07 -0400 Subject: [PATCH 133/133] Restore code that somehow got reverted??? How did this even happen?? --- src/hardware/hw_md2.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index db1c1f727..cd1b957f0 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -26,6 +26,7 @@ #include #include +#include "../d_main.h" #include "../doomdef.h" #include "../doomstat.h" #include "../fastcmp.h" @@ -70,6 +71,10 @@ #endif #endif +#ifndef errno +#include "errno.h" +#endif + #define NUMVERTEXNORMALS 162 float avertexnormals[NUMVERTEXNORMALS][3] = { {-0.525731f, 0.000000f, 0.850651f}, @@ -294,7 +299,8 @@ static md2_model_t *md2_readModel(const char *filename) if (model == NULL) return 0; - file = fopen(filename, "rb"); + //Filename checking fixed ~Monster Iestyn and Golden + file = fopen(va("%s"PATHSEP"%s", srb2home, filename), "rb"); if (!file) { free(model); @@ -523,7 +529,8 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_ #endif #endif png_FILE_p png_FILE; - char *pngfilename = va("md2/%s", filename); + //Filename checking fixed ~Monster Iestyn and Golden + char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pngfilename, ".png"); png_FILE = fopen(pngfilename, "rb"); @@ -651,7 +658,8 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h, size_t pw, ph, size, ptr = 0; INT32 ch, rep; FILE *file; - char *pcxfilename = va("md2/%s", filename); + //Filename checking fixed ~Monster Iestyn and Golden + char *pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pcxfilename, ".pcx"); file = fopen(pcxfilename, "rb"); @@ -845,11 +853,12 @@ void HWR_InitMD2(void) } // read the md2.dat file - f = fopen("md2.dat", "rt"); + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); if (!f) { - CONS_Printf("%s", M_GetText("Error while loading md2.dat\n")); + CONS_Printf("%s %s\n", M_GetText("Error while loading md2.dat:"), strerror(errno)); nomd2s = true; return; } @@ -911,7 +920,8 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup CONS_Printf("AddPlayerMD2()...\n"); // read the md2.dat file - f = fopen("md2.dat", "rt"); + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); if (!f) { @@ -956,7 +966,8 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu return; // Read the md2.dat file - f = fopen("md2.dat", "rt"); + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); if (!f) {

l)j}@K+?}=3h*Jh;?2_uiRlu8B-V@NuP5S| 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 e Date: Sun, 28 Jul 2019 17:06:01 -0400 Subject: [PATCH 019/133] Update mac icon --- src/sdl/macosx/Srb2mac.icns | Bin 83019 -> 173437 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/sdl/macosx/Srb2mac.icns b/src/sdl/macosx/Srb2mac.icns index 96cb8a36d991818eb03b7d80343518ab168bda7d..a3e37aab3ee846900a873610f7d8d66fd34bfda3 100644 GIT binary patch literal 173437 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 Date: Sun, 28 Jul 2019 18:19:00 -0400 Subject: [PATCH 020/133] Change it back to const char --- src/sdl/IMG_xpm.c | 22 +++++++++++----------- src/sdl/SDL_icon.xpm | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/sdl/IMG_xpm.c b/src/sdl/IMG_xpm.c index 51cedfd6d..4c56ce363 100644 --- a/src/sdl/IMG_xpm.c +++ b/src/sdl/IMG_xpm.c @@ -34,7 +34,7 @@ * * Besides the standard API, also provides * - * SDL_Surface *IMG_ReadXPMFromArray(char **xpm) + * SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) * * that reads the image data from an XPM file included in the C source. * @@ -48,7 +48,7 @@ // SDLCALL terms removed from original SDL_image declarations int IMG_isXPM(SDL_RWops *src); SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src); -SDL_Surface *IMG_ReadXPMFromArray(char **xpm); +SDL_Surface *IMG_ReadXPMFromArray(const char **xpm); #define IMG_SetError SDL_SetError #define IMG_GetError SDL_GetError #endif @@ -192,7 +192,7 @@ static void free_colorhash(struct color_hash *hash) * convert colour spec to RGB (in 0xrrggbb format). * return 1 if successful. */ -static int color_to_rgb(char *spec, int speclen, Uint32 *rgb) +static int color_to_rgb(const char *spec, int speclen, Uint32 *rgb) { /* poor man's rgb.txt */ static struct { char *name; Uint32 rgb; } known[] = { @@ -933,7 +933,7 @@ static char *error; * If len > 0, it's assumed to be at least len chars (for efficiency). * Return NULL and set error upon EOF or parse error. */ -static char *get_next_line(char ***lines, SDL_RWops *src, int len) +static const char *get_next_line(const char ***lines, SDL_RWops *src, int len) { char *linebufnew; @@ -1005,7 +1005,7 @@ do { \ } while (0) /* read XPM from either array or RWops */ -static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src) +static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) { Sint64 start = 0; SDL_Surface *image = NULL; @@ -1017,8 +1017,8 @@ static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src) struct color_hash *colors = NULL; SDL_Color *im_colors = NULL; char *keystrings = NULL, *nextkey; - char *line; - char ***xpmlines = NULL; + const char *line; + const char ***xpmlines = NULL; int pixels_len; error = NULL; @@ -1085,7 +1085,7 @@ static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src) goto done; } for (index = 0; index < ncolors; ++index ) { - char *p; + const char *p; line = get_next_line(xpmlines, src, 0); if (!line) goto done; @@ -1095,7 +1095,7 @@ static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src) /* parse a colour definition */ for (;;) { char nametype; - char *colname; + const char *colname; Uint32 rgb, pixel; SKIPSPACE(p); @@ -1188,7 +1188,7 @@ SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) return load_xpm(NULL, src); } -SDL_Surface *IMG_ReadXPMFromArray(char **xpm) +SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) { if (!xpm) { IMG_SetError("array is NULL"); @@ -1212,7 +1212,7 @@ SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) return(NULL); } -SDL_Surface *IMG_ReadXPMFromArray(char **xpm) +SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) { return NULL; } diff --git a/src/sdl/SDL_icon.xpm b/src/sdl/SDL_icon.xpm index c5c957468..2180d782c 100644 --- a/src/sdl/SDL_icon.xpm +++ b/src/sdl/SDL_icon.xpm @@ -1,5 +1,5 @@ /* XPM */ -static char * SDL_icon_xpm[] = { +static const char *SDL_icon_xpm[] = { "64 64 32 1", " c None", ". c #000271", From 1a643b1bd9f64dbaea280d261c179a9709a406a9 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Mon, 29 Jul 2019 19:08:55 -0400 Subject: [PATCH 021/133] SDL2: more const in xpm code --- src/sdl/IMG_xpm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sdl/IMG_xpm.c b/src/sdl/IMG_xpm.c index 4c56ce363..f156335fa 100644 --- a/src/sdl/IMG_xpm.c +++ b/src/sdl/IMG_xpm.c @@ -79,7 +79,7 @@ int IMG_isXPM(SDL_RWops *src) #define STARTING_HASH_SIZE 256 struct hash_entry { - char *key; + const char *key; Uint32 color; struct hash_entry *next; }; @@ -152,7 +152,7 @@ static struct color_hash *create_colorhash(int maxnum) } static int add_colorhash(struct color_hash *hash, - char *key, int cpp, Uint32 color) + const char *key, int cpp, Uint32 color) { int index = hash_key(key, cpp, hash->size); struct hash_entry *e = hash->next_free++; @@ -195,7 +195,7 @@ static void free_colorhash(struct color_hash *hash) static int color_to_rgb(const char *spec, int speclen, Uint32 *rgb) { /* poor man's rgb.txt */ - static struct { char *name; Uint32 rgb; } known[] = { + static struct { const char *name; Uint32 rgb; } known[] = { { "none", 0xFFFFFFFF }, { "black", 0x000000 }, { "white", 0xFFFFFF }, @@ -926,7 +926,7 @@ static int color_to_rgb(const char *spec, int speclen, Uint32 *rgb) static char *linebuf; static int buflen; -static char *error; +static const char *error; /* * Read next line from the source. From a8637d034e07afebd6a980604d5f8bb53cef2738 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Mon, 29 Jul 2019 19:22:14 -0400 Subject: [PATCH 022/133] SDL2: more consts --- src/sdl/IMG_xpm.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/sdl/IMG_xpm.c b/src/sdl/IMG_xpm.c index f156335fa..43fb4ded2 100644 --- a/src/sdl/IMG_xpm.c +++ b/src/sdl/IMG_xpm.c @@ -88,8 +88,8 @@ struct color_hash { struct hash_entry **table; struct hash_entry *entries; /* array of all entries */ struct hash_entry *next_free; - int size; - int maxnum; + size_t size; + size_t maxnum; }; static int hash_key(const char *key, int cpp, int size) @@ -103,9 +103,9 @@ static int hash_key(const char *key, int cpp, int size) return hash & (size - 1); } -static struct color_hash *create_colorhash(int maxnum) +static struct color_hash *create_colorhash(size_t maxnum) { - int bytes, s; + size_t bytes, s; struct color_hash *hash; /* we know how many entries we need, so we can allocate @@ -164,7 +164,7 @@ static int add_colorhash(struct color_hash *hash, } /* fast lookup that works if cpp == 1 */ -#define QUICK_COLORHASH(hash, key) ((hash)->table[*(Uint8 *)(key)]->color) +#define QUICK_COLORHASH(hash, key) ((hash)->table[*(const Uint8 *)(key)]->color) static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp) { @@ -909,7 +909,7 @@ static int color_to_rgb(const char *spec, int speclen, Uint32 *rgb) *rgb = (Uint32)SDL_strtol(buf, NULL, 16); return 1; } else { - int i; + size_t i; for (i = 0; i < SDL_arraysize(known); i++) { if (SDL_strncasecmp(known[i].name, spec, speclen) == 0) { *rgb = known[i].rgb; @@ -1009,10 +1009,11 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) { Sint64 start = 0; SDL_Surface *image = NULL; - int index; + size_t index; int x, y; - int w, h, ncolors, cpp; - int indexed; + int w, h, cpp; + size_t ncolors; + size_t indexed; Uint8 *dst; struct color_hash *colors = NULL; SDL_Color *im_colors = NULL; @@ -1043,7 +1044,7 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) * Right now we don't use the hotspots but it should be handled * one day. */ - if (SDL_sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4 + if (SDL_sscanf(line, "%d %d %lu %d", &w, &h, &ncolors, &cpp) != 4 || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) { error = "Invalid format description"; goto done; From c93fb440e543c7683f9998c01683ab999ab1478c Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 30 Jul 2019 20:56:03 -0400 Subject: [PATCH 023/133] use VERSIONSTRING --- src/win32/Srb2win.rc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index f133a4bcb..8e7fdccc9 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -66,8 +66,8 @@ END #include "../doomdef.h" // Needed for version string VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,2 - PRODUCTVERSION 2,2 + FILEVERSION 2,2,0,0 + PRODUCTVERSION 2,2,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -85,14 +85,14 @@ BEGIN VALUE "Comments", "Visit our web site at www.srb2.org for news and updates!\0" VALUE "CompanyName", "Sonic Team Junior\0" VALUE "FileDescription", "Sonic Robo Blast 2\0" - VALUE "FileVersion", "2.2\0" + VALUE "FileVersion", VERSIONSTRING VALUE "InternalName", "srb2\0" VALUE "LegalCopyright", "Copyright 1998-2019 by Sonic Team Junior\0" VALUE "LegalTrademarks", "Sonic the Hedgehog and related characters are trademarks of Sega.\0" VALUE "OriginalFilename", "srb2win.exe\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "Sonic Robo Blast 2\0" - VALUE "ProductVersion", "2.2\0" + VALUE "ProductVersion", VERSIONSTRING VALUE "SpecialBuild", "\0" END END From 46993268aecf7b239441ffdd0612d6c02be33ded Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 4 Aug 2019 20:02:38 -0400 Subject: [PATCH 024/133] * Added FORCERESETMUSIC level header * cv_resetmusicbyheader toggle to disable said override * Never reset music during time attack * Change cv_resetmusic default back to off --- src/dehacked.c | 14 ++++++++++++++ src/doomstat.h | 2 ++ src/g_game.c | 2 +- src/lua_maplib.c | 2 ++ src/m_menu.c | 13 +++++++++++-- src/p_setup.c | 5 +++-- src/s_sound.c | 7 +++++-- src/s_sound.h | 9 +++++++++ 8 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 2f28a74cf..92b0ee841 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1181,6 +1181,20 @@ static void readlevelheader(MYFILE *f, INT32 num) mapheaderinfo[num-1]->muspostbosspos = (UINT32)get_number(word2); else if (fastcmp(word, "MUSICPOSTBOSSFADEIN")) mapheaderinfo[num-1]->muspostbossfadein = (UINT32)get_number(word2); + else if (fastcmp(word, "FORCERESETMUSIC")) + { + // This is a weird one because "FALSE"/"NO" could either apply to "leave to default preference" (cv_resetmusic) + // or "force off". Let's assume it means "force off", and let an unspecified value mean "default preference" + if (fastcmp(word2, "OFF") || word2[0] == 'F' || word2[0] == 'N') i = 0; + else if (fastcmp(word2, "ON") || word2[0] == 'T' || word2[0] == 'Y') i = 1; + else i = -1; // (fastcmp(word2, "DEFAULT")) + + if (i >= -1 && i <= 1) // -1 to force off, 1 to force on, 0 to honor default. + // This behavior can be disabled with cv_resetmusicbyheader + mapheaderinfo[num-1]->musforcereset = (SINT8)i; + else + deh_warning("Level header %d: invalid forceresetmusic option %d", num, i); + } else if (fastcmp(word, "FORCECHARACTER")) { strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1); diff --git a/src/doomstat.h b/src/doomstat.h index b6c376d1c..a70a122a6 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -333,6 +333,8 @@ typedef struct UINT32 muspostbosspos; ///< Post-bossdeath position UINT32 muspostbossfadein; ///< Post-bossdeath fade-in milliseconds. + SINT8 musforcereset; ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on) + // Lua stuff. // (This is not ifdeffed so the map header structure can stay identical, just in case.) UINT8 numCustomOptions; ///< Internal. For Lua custom value support. diff --git a/src/g_game.c b/src/g_game.c index dad873fe7..3c623e7f1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2310,7 +2310,7 @@ void G_PlayerReborn(INT32 player) } // This is in S_Start, but this was not here previously. - // if (cv_resetmusic.value) + // if (RESETMUSIC) // S_StopMusic(); S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); } diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 74b259921..dbb69b7e2 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -2017,6 +2017,8 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->muspostbosspos); else if (fastcmp(field,"muspostbossfadein")) lua_pushinteger(L, header->muspostbossfadein); + else if (fastcmp(field,"musforcereset")) + lua_pushinteger(L, header->musforcereset); else if (fastcmp(field,"forcecharacter")) lua_pushstring(L, header->forcecharacter); else if (fastcmp(field,"weather")) diff --git a/src/m_menu.c b/src/m_menu.c index a3e986fdf..57ce6a3ca 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1322,6 +1322,12 @@ static menuitem_t OP_SoundOptionsMenu[] = #define OPENMPT_MENUOFFSET 0 #endif +#ifdef HAVE_MIXERX +#define MIXERX_MENUOFFSET 81 +#else +#define MIXERX_MENUOFFSET 0 +#endif + static menuitem_t OP_SoundAdvancedMenu[] = { #ifdef HAVE_OPENMPT @@ -1333,12 +1339,15 @@ static menuitem_t OP_SoundAdvancedMenu[] = {IT_HEADER, NULL, "MIDI Settings", NULL, OPENMPT_MENUOFFSET+10}, {IT_STRING | IT_CVAR, NULL, "MIDI Player", &cv_midiplayer, OPENMPT_MENUOFFSET+22}, {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "FluidSynth Sound Font File", &cv_midisoundfontpath, OPENMPT_MENUOFFSET+34}, - {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "TiMidity++ Config Folder", &cv_miditimiditypath, OPENMPT_MENUOFFSET+61} + {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "TiMidity++ Config Folder", &cv_miditimiditypath, OPENMPT_MENUOFFSET+61}, #endif + + {IT_HEADER, NULL, "Miscellaneous", NULL, OPENMPT_MENUOFFSET+MIXERX_MENUOFFSET+10}, + {IT_STRING | IT_CVAR, NULL, "Let Levels Force Reset Music", &cv_resetmusicbyheader, OPENMPT_MENUOFFSET+MIXERX_MENUOFFSET+22}, }; #undef OPENMPT_MENUOFFSET - +#undef MIXERX_MENUOFFSET #endif static menuitem_t OP_DataOptionsMenu[] = diff --git a/src/p_setup.c b/src/p_setup.c index d0cd14b22..29f63f1bb 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -221,6 +221,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->muspostbosstrack = 0; mapheaderinfo[num]->muspostbosspos = 0; mapheaderinfo[num]->muspostbossfadein = 0; + mapheaderinfo[num]->musforcereset = -1; mapheaderinfo[num]->forcecharacter[0] = '\0'; mapheaderinfo[num]->weather = 0; mapheaderinfo[num]->skynum = 1; @@ -2692,7 +2693,7 @@ boolean P_SetupLevel(boolean skipprecip) S_StartSound(NULL, sfx_s3kaf); // Fade music! Time it to S3KAF: 0.25 seconds is snappy. - if (cv_resetmusic.value || + if (RESETMUSIC || strnicmp(S_MusicName(), (mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7)) S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE) @@ -2725,7 +2726,7 @@ boolean P_SetupLevel(boolean skipprecip) // Fade out music here. Deduct 2 tics so the fade volume actually reaches 0. // But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug. - if (!titlemapinaction && (cv_resetmusic.value || + if (!titlemapinaction && (RESETMUSIC || strnicmp(S_MusicName(), (mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7))) S_FadeMusic(0, FixedMul( diff --git a/src/s_sound.c b/src/s_sound.c index 2c6faf041..bcb20833a 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -108,7 +108,9 @@ consvar_t cv_closedcaptioning = {"closedcaptioning", "Off", CV_SAVE|CV_CALL, CV_ consvar_t cv_numChannels = {"snd_channels", "32", CV_SAVE|CV_CALL, CV_Unsigned, SetChannelsNum, 0, NULL, NULL, 0, 0, NULL}; static consvar_t surround = {"surround", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_resetmusic = {"resetmusic", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_resetmusic = {"resetmusic", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_resetmusicbyheader = {"resetmusicbyheader", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; // Sound system toggles, saved into the config consvar_t cv_gamedigimusic = {"digimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameDigiMusic_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -275,6 +277,7 @@ void S_RegisterSoundStuff(void) CV_RegisterVar(&surround); CV_RegisterVar(&cv_samplerate); CV_RegisterVar(&cv_resetmusic); + CV_RegisterVar(&cv_resetmusicbyheader); CV_RegisterVar(&cv_gamesounds); CV_RegisterVar(&cv_gamedigimusic); CV_RegisterVar(&cv_gamemidimusic); @@ -2096,7 +2099,7 @@ void S_StartEx(boolean reset) mapmusposition = mapheaderinfo[gamemap-1]->muspos; } - if (cv_resetmusic.value || reset) + if (RESETMUSIC || reset) S_StopMusic(); S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); diff --git a/src/s_sound.h b/src/s_sound.h index e0737eff7..48128527c 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -31,7 +31,16 @@ openmpt_module *openmpt_mhandle; extern consvar_t stereoreverse; extern consvar_t cv_soundvolume, cv_closedcaptioning, cv_digmusicvolume, cv_midimusicvolume; extern consvar_t cv_numChannels; + extern consvar_t cv_resetmusic; +extern consvar_t cv_resetmusicbyheader; + +#define RESETMUSIC (!modeattacking && \ + (cv_resetmusicbyheader.value ? \ + (mapheaderinfo[gamemap-1]->musforcereset != -1 ? mapheaderinfo[gamemap-1]->musforcereset : cv_resetmusic.value) \ + : cv_resetmusic.value) \ + ) + extern consvar_t cv_gamedigimusic; extern consvar_t cv_gamemidimusic; extern consvar_t cv_gamesounds; From 1f2baf5b6bad77edf176c2a4e9115bb0c70cd0bb Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 22 Aug 2019 22:30:36 +0100 Subject: [PATCH 025/133] Make polyobjects agree with sector lighting/colormap like a FOF. Caution: has weird retry/reload bug. Ask sphere for sample map/coords. --- src/hardware/hw_main.c | 19 ++++++++++++------- src/r_bsp.c | 10 +++++----- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c600800fd..c6a8b16e5 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3333,6 +3333,7 @@ static void HWR_AddPolyObjectPlanes(void) { size_t i; sector_t *polyobjsector; + INT32 light = 0; // Polyobject Planes need their own function for drawing because they don't have extrasubsectors by themselves // It should be okay because polyobjects should always be convex anyway @@ -3351,19 +3352,22 @@ static void HWR_AddPolyObjectPlanes(void) && polyobjsector->floorheight >= gr_frontsector->floorheight && (viewz < polyobjsector->floorheight)) { + light = R_GetPlaneLight(gr_frontsector, polyobjsector->floorheight, true); if (po_ptrs[i]->translucency > 0) { FSurfaceInfo Surf; - FBITFIELD blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); + FBITFIELD blendmode; + memset(&Surf, 0x00, sizeof(Surf)); + blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, po_ptrs[i], false, polyobjsector->floorheight, - polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL); + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else { HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum); HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, - polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, - polyobjsector, 255, NULL); + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, + polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } } @@ -3371,6 +3375,7 @@ static void HWR_AddPolyObjectPlanes(void) && polyobjsector->ceilingheight <= gr_frontsector->ceilingheight && (viewz > polyobjsector->ceilingheight)) { + light = R_GetPlaneLight(gr_frontsector, polyobjsector->ceilingheight, true); if (po_ptrs[i]->translucency > 0) { FSurfaceInfo Surf; @@ -3378,14 +3383,14 @@ static void HWR_AddPolyObjectPlanes(void) memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, po_ptrs[i], true, polyobjsector->ceilingheight, - polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL); + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else { HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, - polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, - polyobjsector, 255, NULL); + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, + polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } } } diff --git a/src/r_bsp.c b/src/r_bsp.c index d521d9f4d..23e751420 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -1088,9 +1088,9 @@ static void R_Subsector(size_t num) { light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight); ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic, - polysec->lightlevel, polysec->floor_xoffs, polysec->floor_yoffs, + (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floor_xoffs, polysec->floor_yoffs, polysec->floorpic_angle-po->angle, - NULL, NULL, po + (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po #ifdef ESLOPE , NULL // will ffloors be slopable eventually? #endif @@ -1115,10 +1115,10 @@ static void R_Subsector(size_t num) && polysec->ceilingheight <= ceilingcenterz && (viewz > polysec->ceilingheight)) { - light = R_GetPlaneLight(frontsector, polysec->ceilingheight, viewz < polysec->ceilingheight); + light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight); ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic, - polysec->lightlevel, polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle, - NULL, NULL, po + (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle, + (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po #ifdef ESLOPE , NULL // will ffloors be slopable eventually? #endif From 4e256b73b2c6d8a47c3bb1f46cf14fad4115764a Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 24 Aug 2019 18:25:27 +0100 Subject: [PATCH 026/133] Lua save-banks! * Array of 8 INT32's natively embedded into savedata (net and SP)! * Initialised to zero whenever a new save (or equivalent) is started, otherwise untouched by the base game. * Requires reservation to avoid clobber-conflicts. * Access via `reserveLuabanks()` - returns a read-write userdata. * Assign userdata to local variable or global rawset to use later. Mostly for future SUGOIlikes, but I'm sure someone could figure out an unrelated usage eventually. --- src/d_main.c | 1 + src/d_netcmd.c | 4 +++ src/doomstat.h | 4 +++ src/g_game.c | 25 ++++++++++++++++- src/lua_baselib.c | 15 ++++++++++ src/lua_infolib.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++- src/lua_libs.h | 2 ++ src/m_menu.c | 27 +++++++++++++++++- src/p_saveg.c | 51 ++++++++++++++++++++++++++++++---- 9 files changed, 191 insertions(+), 8 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index eaeae4b10..d99fb7494 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -716,6 +716,7 @@ void D_StartTitle(void) botskin = 0; cv_debug = 0; emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); lastmaploaded = 0; // In case someone exits out at the same time they start a time attack run, diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3e82fc60c..c1183ebbe 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1908,7 +1908,10 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) precache = false; if (resetplayer && !FLS) + { emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); + } if (modeattacking) { @@ -4103,6 +4106,7 @@ void Command_ExitGame_f(void) botskin = 0; cv_debug = 0; emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); if (dirmenu) closefilemenu(true); diff --git a/src/doomstat.h b/src/doomstat.h index b6c376d1c..1bf67de61 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -418,6 +418,10 @@ extern UINT16 emeralds; #define EMERALD7 64 #define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) +// yes, even in non HAVE_BLUA +#define NUM_LUABANKS 8 // please only make this number go up between versions, never down. you'll break saves otherwise. also, must fit in UINT8 +extern INT32 luabanks[NUM_LUABANKS]; + extern INT32 nummaprings; //keep track of spawned rings/coins /** Time attack information, currently a very small structure. diff --git a/src/g_game.c b/src/g_game.c index e70241269..ec86c3d51 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -172,6 +172,7 @@ static boolean retrying = false; UINT8 stagefailed; // Used for GEMS BONUS? Also to see if you beat the stage. UINT16 emeralds; +INT32 luabanks[NUM_LUABANKS]; // yes, even in non HAVE_BLUA UINT32 token; // Number of tokens collected in a level UINT32 tokenlist; // List of tokens collected boolean gottoken; // Did you get a token? Used for end of act @@ -3778,7 +3779,29 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) // File end marker check CHECKPOS - if (READUINT8(save_p) != 0x1d) BADSAVE; + switch (READUINT8(save_p)) + { + case 0xb7: + { + UINT8 i, banksinuse; + CHECKPOS + banksinuse = READUINT8(save_p); + CHECKPOS + if (banksinuse > NUM_LUABANKS) + BADSAVE + for (i = 0; i < banksinuse; i++) + { + (void)READINT32(save_p); + CHECKPOS + } + if (READUINT8(save_p) != 0x1d) + BADSAVE + } + case 0x1d: + break; + default: + BADSAVE + } // done saved = FIL_WriteFile(backup, savebuffer, length); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 3c136a436..a69e8a188 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -182,6 +182,8 @@ static const struct { {META_CAMERA, "camera_t"}, {META_ACTION, "action"}, + + {META_LUABANKS, "luabanks[]"}, {NULL, NULL} }; @@ -228,6 +230,18 @@ static int lib_isPlayerAdmin(lua_State *L) return 1; } +static int lib_reserveLuabanks(lua_State *L) +{ + static boolean reserved = false; + if (!lua_lumploading) + return luaL_error(L, "luabanks[] cannot be reserved from within a hook or coroutine!"); + if (reserved) + return luaL_error(L, "luabanks[] has already been reserved! Only one savedata-enabled mod at a time may use this feature."); + reserved = true; + LUA_PushUserdata(L, &luabanks, META_LUABANKS); + return 1; +} + // M_RANDOM ////////////// @@ -2736,6 +2750,7 @@ static luaL_Reg lib[] = { {"chatprintf", lib_chatprintf}, {"userdataType", lib_userdataType}, {"IsPlayerAdmin", lib_isPlayerAdmin}, + {"reserveLuabanks", lib_reserveLuabanks}, // m_random {"P_RandomFixed",lib_pRandomFixed}, diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 77f37f8ec..8338fa5b9 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -18,6 +18,7 @@ #include "p_mobj.h" #include "p_local.h" #include "z_zone.h" +#include "doomstat.h" // luabanks[] #include "lua_script.h" #include "lua_libs.h" @@ -146,7 +147,7 @@ static int lib_getSpr2default(lua_State *L) return luaL_error(L, "spr2defaults[] invalid index"); if (i >= free_spr2) - return 0; + return luaL_error(L, "spr2defaults[] index %d out of range (%d - %d)", i, 0, free_spr2-1); lua_pushinteger(L, spr2defaults[i]); return 1; @@ -1026,6 +1027,61 @@ static int sfxinfo_num(lua_State *L) return 1; } +////////////// +// LUABANKS // +////////////// + +static int lib_getluabanks(lua_State *L) +{ + UINT8 i; + + lua_remove(L, 1); // don't care about luabanks[] dummy userdata. + + if (lua_isnumber(L, 1)) + i = lua_tonumber(L, 1); + else + return luaL_error(L, "luabanks[] invalid index"); + + if (i >= NUM_LUABANKS) + luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS); + + lua_pushinteger(L, luabanks[i]); + return 1; +} + +static int lib_setluabanks(lua_State *L) +{ + UINT8 i; + INT32 j = 0; + + if (hud_running) + return luaL_error(L, "Do not alter luabanks[] in HUD rendering code!"); + + lua_remove(L, 1); // don't care about luabanks[] dummy userdata. + + if (lua_isnumber(L, 1)) + i = lua_tonumber(L, 1); + else + return luaL_error(L, "luabanks[] invalid index"); + + if (i >= NUM_LUABANKS) + luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS-1); + + if (lua_isnumber(L, 2)) + j = lua_tonumber(L, 2); + else + return luaL_error(L, "luabanks[] invalid set"); + + luabanks[i] = j; + return 0; +} + +static int lib_luabankslen(lua_State *L) +{ + lua_pushinteger(L, NUM_LUABANKS); + return 1; +} + ////////////////////////////// // // Now push all these functions into the Lua state! @@ -1147,6 +1203,18 @@ int LUA_InfoLib(lua_State *L) lua_pushvalue(L, -1); lua_setglobal(L, "S_sfx"); lua_setglobal(L, "sfxinfo"); + + luaL_newmetatable(L, META_LUABANKS); + lua_pushcfunction(L, lib_getluabanks); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setluabanks); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_luabankslen); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + return 0; } diff --git a/src/lua_libs.h b/src/lua_libs.h index 827c1d798..7609971ce 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -67,6 +67,8 @@ extern lua_State *gL; #define META_ACTION "ACTIONF_T*" +#define META_LUABANKS "LUABANKS[]*" + boolean luaL_checkboolean(lua_State *L, int narg); int LUA_EnumLib(lua_State *L); diff --git a/src/m_menu.c b/src/m_menu.c index 128b15a76..96efb569a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6885,6 +6885,7 @@ static void M_StartTutorial(INT32 choice) tutorialmode = true; // turn on tutorial mode emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); M_ClearMenus(true); gamecomplete = false; cursaveslot = 0; @@ -7293,7 +7294,29 @@ static void M_ReadSavegameInfo(UINT32 slot) // File end marker check CHECKPOS - if (READUINT8(save_p) != 0x1d) BADSAVE; + switch (READUINT8(save_p)) + { + case 0xb7: + { + UINT8 i, banksinuse; + CHECKPOS + banksinuse = READUINT8(save_p); + CHECKPOS + if (banksinuse > NUM_LUABANKS) + BADSAVE + for (i = 0; i < banksinuse; i++) + { + (void)READINT32(save_p); + CHECKPOS + } + if (READUINT8(save_p) != 0x1d) + BADSAVE + } + case 0x1d: + break; + default: + BADSAVE + } // done Z_Free(savebuffer); @@ -8495,6 +8518,7 @@ static void M_ChooseNightsAttack(INT32 choice) char nameofdemo[256]; (void)choice; emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); M_ClearMenus(true); modeattacking = ATTACKING_NIGHTS; @@ -8519,6 +8543,7 @@ static void M_ChooseTimeAttack(INT32 choice) char nameofdemo[256]; (void)choice; emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); M_ClearMenus(true); modeattacking = ATTACKING_RECORD; diff --git a/src/p_saveg.c b/src/p_saveg.c index ea998b445..e03863bc2 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -4109,12 +4109,54 @@ static inline boolean P_NetUnArchiveMisc(void) return true; } +static inline void P_ArchiveLuabanksAndConsistency(void) +{ + UINT8 i, banksinuse = NUM_LUABANKS; + + while (banksinuse && !luabanks[banksinuse-1]) + banksinuse--; // get the last used bank + + if (banksinuse) + { + WRITEUINT8(save_p, 0xb7); // luabanks marker + WRITEUINT8(save_p, banksinuse); + for (i = 0; i < banksinuse; i++) + WRITEINT32(save_p, luabanks[i]); + } + + WRITEUINT8(save_p, 0x1d); // consistency marker +} + +static inline boolean P_UnArchiveLuabanksAndConsistency(void) +{ + switch (READUINT8(save_p)) + { + case 0xb7: + { + UINT8 i, banksinuse = READUINT8(save_p); + if (banksinuse > NUM_LUABANKS) + return false; + for (i = 0; i < banksinuse; i++) + luabanks[i] = READINT32(save_p); + if (READUINT8(save_p) != 0x1d) + return false; + } + case 0x1d: + break; + default: + return false; + } + + return true; +} + void P_SaveGame(void) { P_ArchiveMisc(); P_ArchivePlayer(); - WRITEUINT8(save_p, 0x1d); // consistency marker + // yes, even in non HAVE_BLUA + P_ArchiveLuabanksAndConsistency(); } void P_SaveNetGame(void) @@ -4153,7 +4195,7 @@ void P_SaveNetGame(void) LUA_Archive(); #endif - WRITEUINT8(save_p, 0x1d); // consistency marker + P_ArchiveLuabanksAndConsistency(); } boolean P_LoadGame(INT16 mapoverride) @@ -4165,8 +4207,7 @@ boolean P_LoadGame(INT16 mapoverride) P_UnArchiveSPGame(mapoverride); P_UnArchivePlayer(); - // Savegame end marker - if (READUINT8(save_p) != 0x1d) + if (!P_UnArchiveLuabanksAndConsistency()) return false; // Only do this after confirming savegame is ok @@ -4207,5 +4248,5 @@ boolean P_LoadNetGame(void) // precipitation when loading a netgame save. Instead, precip has to be spawned here. // This is done in P_NetUnArchiveSpecials now. - return READUINT8(save_p) == 0x1d; + return P_UnArchiveLuabanksAndConsistency(); } From fbec4af086956df517ed631220d16778f9dfa425 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 24 Aug 2019 17:17:55 -0400 Subject: [PATCH 027/133] Fallback graphic for firework display, if the character lacks one. --- src/f_finale.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index da042abeb..056b7f815 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1595,11 +1595,11 @@ void F_StartEnding(void) sprframe = &sprdef->spriteframes[4]; endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); } - else // eh, yknow what? too lazy to put MISSINGs here. eggman wins if you don't give your character an ending firework display. + else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this) { - endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_LEVEL); - endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_LEVEL); - endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_LEVEL); + endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_LEVEL); + endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_LEVEL); + endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_LEVEL); } endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_LEVEL); From b746ef66ac5abb7e4574e56e875f114564f24c87 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 24 Aug 2019 22:56:20 +0100 Subject: [PATCH 028/133] Fix range print for getter error (setter was caught ahead of time) --- src/lua_infolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 8338fa5b9..8ef0bafcf 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1043,7 +1043,7 @@ static int lib_getluabanks(lua_State *L) return luaL_error(L, "luabanks[] invalid index"); if (i >= NUM_LUABANKS) - luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS); + luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS-1); lua_pushinteger(L, luabanks[i]); return 1; From 141631220028cba50baa5fb15dd8c6f25ccff86c Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 26 Aug 2019 20:38:32 -0400 Subject: [PATCH 029/133] Move some cvars out of D_ClientServerInit and save them Ported over from Kart --- src/d_clisrv.c | 15 +++++---------- src/d_clisrv.h | 1 + src/d_netcmd.c | 7 +++++++ 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 556d86384..aaca4a84f 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -152,7 +152,7 @@ ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL}; -static consvar_t cv_showjoinaddress = {"showjoinaddress", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_showjoinaddress = {"showjoinaddress", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_playbackspeed = {"playbackspeed", "1", 0, playbackspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -2938,13 +2938,13 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) CL_RemovePlayer(pnum, kickreason); } -consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; -consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done +consvar_t cv_allownewplayer = {"allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; +consvar_t cv_joinnextround = {"joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t resynchattempts_cons_t[] = {{0, "MIN"}, {20, "MAX"}, {0, NULL}}; -consvar_t cv_resynchattempts = {"resynchattempts", "10", 0, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL }; -consvar_t cv_blamecfail = {"blamecfail", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; +consvar_t cv_resynchattempts = {"resynchattempts", "10", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL }; +consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; // max file size to send to a player (in kilobytes) static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}}; @@ -2985,11 +2985,6 @@ void D_ClientServerInit(void) RegisterNetXCmd(XD_KICK, Got_KickCmd); RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer); #ifndef NONET - CV_RegisterVar(&cv_allownewplayer); - CV_RegisterVar(&cv_joinnextround); - CV_RegisterVar(&cv_showjoinaddress); - CV_RegisterVar(&cv_resynchattempts); - CV_RegisterVar(&cv_blamecfail); #ifdef DUMPCONSISTENCY CV_RegisterVar(&cv_dumpconsistency); #endif diff --git a/src/d_clisrv.h b/src/d_clisrv.h index a6783fb3d..cfa58aad7 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -441,6 +441,7 @@ extern INT32 mapchangepending; // Points inside doomcom extern doomdata_t *netbuffer; +extern consvar_t cv_showjoinaddress; extern consvar_t cv_playbackspeed; #define BASEPACKETSIZE offsetof(doomdata_t, u) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3e82fc60c..63ad35355 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -556,9 +556,16 @@ void D_RegisterServerCommands(void) // d_clisrv CV_RegisterVar(&cv_maxplayers); + CV_RegisterVar(&cv_resynchattempts); CV_RegisterVar(&cv_maxsend); CV_RegisterVar(&cv_noticedownload); CV_RegisterVar(&cv_downloadspeed); +#ifndef NONET + CV_RegisterVar(&cv_allownewplayer); + CV_RegisterVar(&cv_joinnextround); + CV_RegisterVar(&cv_showjoinaddress); + CV_RegisterVar(&cv_blamecfail); +#endif COM_AddCommand("ping", Command_Ping_f); CV_RegisterVar(&cv_nettimeout); From b2712af2d07e0f4b68fcc9700e77b0837bece817 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 26 Aug 2019 21:49:12 -0400 Subject: [PATCH 030/133] Reorder the main multiplayer menu --- src/m_menu.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 128b15a76..63b372810 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -884,12 +884,12 @@ static menuitem_t MP_SplitServerMenu[] = static menuitem_t MP_MainMenu[] = { - {IT_HEADER, NULL, "Host a game", NULL, 0}, - {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 12}, - {IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 22}, - {IT_HEADER, NULL, "Join a game", NULL, 40}, - {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenu, 52}, - {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 62}, + {IT_HEADER, NULL, "Join a game", NULL, 0}, + {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenu, 12}, + {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 22}, + {IT_HEADER, NULL, "Host a game", NULL, 54}, + {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 66}, + {IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 76}, {IT_HEADER, NULL, "Player setup", NULL, 94}, {IT_STRING|IT_CALL, NULL, "Player 1...", M_SetupMultiPlayer, 106}, {IT_STRING|IT_CALL, NULL, "Player 2... ", M_SetupMultiPlayer2, 116}, @@ -9259,20 +9259,16 @@ static void M_DrawMPMainMenu(void) // use generic drawer for cursor, items and title M_DrawGenericMenu(); -#if MAXPLAYERS == 32 - V_DrawRightAlignedString(BASEVIDWIDTH-x, y+12, - ((itemOn == 1) ? V_YELLOWMAP : 0), "(2-32 players)"); -#else -Update the maxplayers label... -#endif + V_DrawRightAlignedString(BASEVIDWIDTH-x, y+66, + ((itemOn == 4) ? V_YELLOWMAP : 0), va("(2-%d players)", MAXPLAYERS)); - V_DrawRightAlignedString(BASEVIDWIDTH-x, y+22, - ((itemOn == 2) ? V_YELLOWMAP : 0), "(2 players)"); + V_DrawRightAlignedString(BASEVIDWIDTH-x, y+76, + ((itemOn == 5) ? V_YELLOWMAP : 0), "(2 players)"); V_DrawRightAlignedString(BASEVIDWIDTH-x, y+116, ((itemOn == 8) ? V_YELLOWMAP : 0), "(splitscreen)"); - y += 62; + y += 22; V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 159); @@ -9280,7 +9276,7 @@ Update the maxplayers label... V_DrawString(x+8,y+12, V_MONOSPACE, setupm_ip); // draw text cursor for name - if (itemOn == 5 //0 + if (itemOn == 2 //0 && skullAnimCounter < 4) //blink cursor V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_MONOSPACE),y+12,'_',false); } From a98862b3ed72e1f353c6d8d40d730f35d6fdb88e Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 26 Aug 2019 22:00:07 -0400 Subject: [PATCH 031/133] Allow letters to be used on ipv4 address field --- src/m_menu.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 63b372810..586a85629 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9247,7 +9247,7 @@ static void M_StartServerMenu(INT32 choice) // CONNECT VIA IP // ============== -static char setupm_ip[16]; +static char setupm_ip[28]; // Draw the funky Connect IP menu. Tails 11-19-2002 // So much work for such a little thing! @@ -9273,12 +9273,12 @@ static void M_DrawMPMainMenu(void) V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 159); // draw name string - V_DrawString(x+8,y+12, V_MONOSPACE, setupm_ip); + V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip); // draw text cursor for name if (itemOn == 2 //0 && skullAnimCounter < 4) //blink cursor - V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_MONOSPACE),y+12,'_',false); + V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_ALLOWLOWERCASE),y+12,'_',false); } // Tails 11-19-2002 @@ -9349,10 +9349,11 @@ static void M_HandleConnectIP(INT32 choice) default: l = strlen(setupm_ip); - if (l >= 16-1) + if (l >= 28-1) break; - if (choice == 46 || (choice >= 48 && choice <= 57)) // Rudimentary number and period enforcing + // Rudimentary number and period enforcing - also allows letters so hostnames can be used instead + if ((choice >= '-' && choice <= ':') || (choice >= 'A' && choice <= 'Z') || (choice >= 'a' && choice <= 'z')) { S_StartSound(NULL,sfx_menu1); // Tails setupm_ip[l] = (char)choice; From b4d81266750d8389b060f8f506dcfecaa0404eea Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 27 Aug 2019 18:05:30 -0400 Subject: [PATCH 032/133] Rename offline mode to private mode --- src/m_menu.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 586a85629..926e74438 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -948,7 +948,7 @@ enum static menuitem_t MP_RoomMenu[] = { - {IT_STRING | IT_CALL, NULL, "", M_ChooseRoom, 9}, + {IT_STRING | IT_CALL, NULL, "", M_ChooseRoom, 9}, {IT_DISABLED, NULL, "", M_ChooseRoom, 18}, {IT_DISABLED, NULL, "", M_ChooseRoom, 27}, {IT_DISABLED, NULL, "", M_ChooseRoom, 36}, @@ -8872,7 +8872,7 @@ static void M_DrawConnectMenu(void) // Room name if (ms_RoomId < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey, - V_YELLOWMAP, (itemOn == mp_connect_room) ? "" : ""); else V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey, V_YELLOWMAP, room_list[menuRoomIndex].name); @@ -9022,7 +9022,14 @@ static void M_ConnectMenu(INT32 choice) // first page of servers serverlistpage = 0; - M_SetupNextMenu(&MP_ConnectDef); + if (ms_RoomId < 0) + { + M_RoomMenu(0); // Select a room instead of staring at an empty list + // This prevents us from returning to the modified game alert. + currentMenu->prevMenu = &MP_MainDef; + } + else + M_SetupNextMenu(&MP_ConnectDef); itemOn = 0; M_Refresh(0); } @@ -9081,7 +9088,16 @@ static void M_ChooseRoom(INT32 choice) } serverlistpage = 0; - M_SetupNextMenu(currentMenu->prevMenu); + /* + We were on the Multiplayer menu? That means that we must have been trying to + view the server browser, but we hadn't selected a room yet. So we need to go + to the browser next, not back there. + */ + if (currentMenu->prevMenu == &MP_MainDef) + M_SetupNextMenu(&MP_ConnectDef); + else + M_SetupNextMenu(currentMenu->prevMenu); + if (currentMenu == &MP_ConnectDef) M_Refresh(0); } @@ -9140,7 +9156,7 @@ static void M_DrawServerMenu(void) M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true, false); if (ms_RoomId < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, - V_YELLOWMAP, (itemOn == mp_server_room) ? "" : ""); else V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, V_YELLOWMAP, room_list[menuRoomIndex].name); From 7e47117afa7802e12e6716ac25098c1507e69223 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 28 Aug 2019 20:24:30 -0400 Subject: [PATCH 033/133] Add warning message when attempting to use the master server browser while `modifiedgame` is true. --- src/m_menu.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 926e74438..e29568536 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -265,6 +265,7 @@ static void M_ServerOptions(INT32 choice); #ifndef NONET static void M_StartServerMenu(INT32 choice); static void M_ConnectMenu(INT32 choice); +static void M_ConnectMenuModChecks(INT32 choice); static void M_Refresh(INT32 choice); static void M_Connect(INT32 choice); static void M_ChooseRoom(INT32 choice); @@ -885,7 +886,7 @@ static menuitem_t MP_SplitServerMenu[] = static menuitem_t MP_MainMenu[] = { {IT_HEADER, NULL, "Join a game", NULL, 0}, - {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenu, 12}, + {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenuModChecks, 12}, {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 22}, {IT_HEADER, NULL, "Host a game", NULL, 54}, {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 66}, @@ -5603,7 +5604,7 @@ static boolean M_AddonsRefresh(void) { S_StartSound(NULL, sfx_lose); if (refreshdirmenu & REFRESHDIR_MAX) - message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); + message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nif you wish to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); else message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); } @@ -9034,6 +9035,20 @@ static void M_ConnectMenu(INT32 choice) M_Refresh(0); } +static void M_ConnectMenuModChecks(INT32 choice) +{ + (void)choice; + // okay never mind we want to COMMUNICATE to the player pre-emptively instead of letting them try and then get confused when it doesn't work + + if (modifiedgame) + { + M_StartMessage(M_GetText("Add-ons are currently loaded.\n\nYou will only be able to join a server if\nit has the same ones loaded in the same order, which may be unlikely.\n\nIf you wish to play on other servers,\nrestart the game to clear existing add-ons.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER); + return; + } + + M_ConnectMenu(-1); +} + static UINT32 roomIds[NUM_LIST_ROOMS]; static void M_RoomMenu(INT32 choice) From 8655b8f1f15f0b138d9c85af07a6f1b4a7a4dff1 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 29 Aug 2019 01:57:58 -0400 Subject: [PATCH 034/133] Add spawn object linedef special. Note that spawning a object within a random range does not fully work yet and crashes the game --- src/p_setup.c | 1 + src/p_spec.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index d0cd14b22..65335be3f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1480,6 +1480,7 @@ static void P_LoadRawSideDefs2(void *data) case 425: // Calls P_SetMobjState on calling mobj case 434: // Custom Power case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors + case 461: // Spawns an object on the map based on texture offsets { char process[8*3+1]; memset(process,0,8*3+1); diff --git a/src/p_spec.c b/src/p_spec.c index 37a1652f0..325f5ebe7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3953,6 +3953,27 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; + case 461: // Spawns an object on the map based on texture offsets + { + const mobjtype_t type = (mobjtype_t)(sides[line->sidenum[0]].toptexture); + + fixed_t x, y, z; + x = sides[line->sidenum[0]].textureoffset; + y = sides[line->sidenum[0]].rowoffset; + z = line->frontsector->floorheight; + + if (line->flags & ML_NOCLIMB) // If noclimb is set, spawn randomly within a range + { + x = P_RandomRange(sides[line->sidenum[0]].textureoffset, sides[line->sidenum[1]].textureoffset); + y = P_RandomRange(sides[line->sidenum[0]].rowoffset, sides[line->sidenum[1]].rowoffset); + z = P_RandomRange(line->frontsector->floorheight, line->frontsector->ceilingheight); + } + + CONS_Printf("mobjtype_t: %d\n", type); + P_SpawnMobj(x, y, z, type); + } + break; + #ifdef POLYOBJECTS case 480: // Polyobj_DoorSlide case 481: // Polyobj_DoorSwing From 656879b90bff5073c0e875235d58105b977d5eb2 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 29 Aug 2019 15:56:46 -0400 Subject: [PATCH 035/133] Is this thing working? --- src/p_user.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index 35399c2b8..b93cf5b44 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11576,9 +11576,21 @@ void P_PlayerAfterThink(player_t *player) #endif if (splitscreen && player == &players[secondarydisplayplayer]) + { thiscam = &camera2; + if (P_AproxDistance(player->mo->x-thiscam->x-thiscam->momx, player->mo->y-thiscam->y-thiscam->momy) > ((player->speed+cv_cam2_dist.value)*2)) + { + P_ResetCamera(player, thiscam); + } + } else if (player == &players[displayplayer]) + { thiscam = &camera; + if (P_AproxDistance(player->mo->x-thiscam->x-thiscam->momx, player->mo->y-thiscam->y-thiscam->momy) > ((player->speed+cv_cam_dist.value)*2)) + { + P_ResetCamera(player, thiscam); + } + } if (player->playerstate == PST_DEAD) { From bcd0b044883a18eeeda61897bb01a2a731951264 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 29 Aug 2019 17:17:58 -0400 Subject: [PATCH 036/133] Forgot to account for z axis -- thanks James R --- src/p_user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index b93cf5b44..2903e546f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11578,7 +11578,7 @@ void P_PlayerAfterThink(player_t *player) if (splitscreen && player == &players[secondarydisplayplayer]) { thiscam = &camera2; - if (P_AproxDistance(player->mo->x-thiscam->x-thiscam->momx, player->mo->y-thiscam->y-thiscam->momy) > ((player->speed+cv_cam2_dist.value)*2)) + if ((P_AproxDistance(player->mo->x-thiscam->x-thiscam->momx, player->mo->y-thiscam->y-thiscam->momy) > ((player->speed+cv_cam2_dist.value)*2)) || (abs(thiscam->z - player->mo->z) > ((player->speed+cv_cam2_dist.value)*2))) { P_ResetCamera(player, thiscam); } @@ -11586,7 +11586,7 @@ void P_PlayerAfterThink(player_t *player) else if (player == &players[displayplayer]) { thiscam = &camera; - if (P_AproxDistance(player->mo->x-thiscam->x-thiscam->momx, player->mo->y-thiscam->y-thiscam->momy) > ((player->speed+cv_cam_dist.value)*2)) + if ((P_AproxDistance(player->mo->x-thiscam->x-thiscam->momx, player->mo->y-thiscam->y-thiscam->momy) > ((player->speed+cv_cam_dist.value)*2)) || (abs(thiscam->z - player->mo->z) > ((player->speed+cv_cam_dist.value)*2))) { P_ResetCamera(player, thiscam); } From 10ea0f21ae3b61b2584b599adab57a5b65b29c82 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 29 Aug 2019 23:56:15 -0400 Subject: [PATCH 037/133] Fix spawning within random range --- src/p_spec.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 325f5ebe7..014a09845 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3964,13 +3964,24 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->flags & ML_NOCLIMB) // If noclimb is set, spawn randomly within a range { - x = P_RandomRange(sides[line->sidenum[0]].textureoffset, sides[line->sidenum[1]].textureoffset); - y = P_RandomRange(sides[line->sidenum[0]].rowoffset, sides[line->sidenum[1]].rowoffset); - z = P_RandomRange(line->frontsector->floorheight, line->frontsector->ceilingheight); + if (line->sidenum[1] != 0xffff) // Make sure the linedef has a back side + { + x = P_RandomRange(sides[line->sidenum[0]].textureoffset>>FRACBITS, sides[line->sidenum[1]].textureoffset>>FRACBITS)<sidenum[0]].rowoffset>>FRACBITS, sides[line->sidenum[1]].rowoffset>>FRACBITS)<frontsector->floorheight>>FRACBITS, line->frontsector->ceilingheight>>FRACBITS)<special); + break; + } } - CONS_Printf("mobjtype_t: %d\n", type); - P_SpawnMobj(x, y, z, type); + mobj_t *mobj = P_SpawnMobj(x, y, z, type); + if (mobj) + CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow. + else + CONS_Alert(CONS_ERROR,"Linedef Type %d - Spawn Object: Object did not spawn!\n", line->special); } break; From 5c295d285b5c52a12e9cabc5bb23a33ec41ea15b Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Fri, 30 Aug 2019 00:36:10 -0400 Subject: [PATCH 038/133] Capitalize the 'if' --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index e29568536..e71877d53 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5604,7 +5604,7 @@ static boolean M_AddonsRefresh(void) { S_StartSound(NULL, sfx_lose); if (refreshdirmenu & REFRESHDIR_MAX) - message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nif you wish to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); + message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you wish to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); else message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); } From 8167a88becac105af29808d1f25f52f19095e00d Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Fri, 30 Aug 2019 00:38:58 -0400 Subject: [PATCH 039/133] Rename private mode to unlisted mode --- src/m_menu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index e71877d53..5f5e987bd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -949,7 +949,7 @@ enum static menuitem_t MP_RoomMenu[] = { - {IT_STRING | IT_CALL, NULL, "", M_ChooseRoom, 9}, + {IT_STRING | IT_CALL, NULL, "", M_ChooseRoom, 9}, {IT_DISABLED, NULL, "", M_ChooseRoom, 18}, {IT_DISABLED, NULL, "", M_ChooseRoom, 27}, {IT_DISABLED, NULL, "", M_ChooseRoom, 36}, @@ -8873,7 +8873,7 @@ static void M_DrawConnectMenu(void) // Room name if (ms_RoomId < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey, - V_YELLOWMAP, (itemOn == mp_connect_room) ? "" : ""); else V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey, V_YELLOWMAP, room_list[menuRoomIndex].name); @@ -9171,7 +9171,7 @@ static void M_DrawServerMenu(void) M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true, false); if (ms_RoomId < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, - V_YELLOWMAP, (itemOn == mp_server_room) ? "" : ""); else V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, V_YELLOWMAP, room_list[menuRoomIndex].name); From 6a9da63d7f2429492028d72fba08444c1060bd80 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 30 Aug 2019 19:19:54 +0100 Subject: [PATCH 040/133] Motor's new Eggman sprites, along with some other sweet bits of boss polish. What else can I say? Just play it. --- src/dehacked.c | 63 ++------ src/hardware/hw_light.c | 7 +- src/info.c | 333 ++++++++++++++-------------------------- src/info.h | 73 +++------ src/p_enemy.c | 234 ++++++++++++++++++++-------- src/p_inter.c | 6 + src/p_mobj.c | 114 ++++++++------ src/r_draw.c | 11 +- 8 files changed, 408 insertions(+), 433 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 04ac2ef4b..cf767a4b5 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4585,10 +4585,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SONIC3KBOSSEXPLOSION6", "S_JETFUME1", - "S_JETFUME2", // Boss 1 "S_EGGMOBILE_STND", + "S_EGGMOBILE_ROFL", "S_EGGMOBILE_LATK1", "S_EGGMOBILE_LATK2", "S_EGGMOBILE_LATK3", @@ -4598,7 +4598,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE_LATK7", "S_EGGMOBILE_LATK8", "S_EGGMOBILE_LATK9", - "S_EGGMOBILE_LATK10", "S_EGGMOBILE_RATK1", "S_EGGMOBILE_RATK2", "S_EGGMOBILE_RATK3", @@ -4608,7 +4607,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE_RATK7", "S_EGGMOBILE_RATK8", "S_EGGMOBILE_RATK9", - "S_EGGMOBILE_RATK10", "S_EGGMOBILE_PANIC1", "S_EGGMOBILE_PANIC2", "S_EGGMOBILE_PANIC3", @@ -4616,6 +4614,14 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE_PANIC5", "S_EGGMOBILE_PANIC6", "S_EGGMOBILE_PANIC7", + "S_EGGMOBILE_PANIC8", + "S_EGGMOBILE_PANIC9", + "S_EGGMOBILE_PANIC10", + "S_EGGMOBILE_PANIC11", + "S_EGGMOBILE_PANIC12", + "S_EGGMOBILE_PANIC13", + "S_EGGMOBILE_PANIC14", + "S_EGGMOBILE_PANIC15", "S_EGGMOBILE_PAIN", "S_EGGMOBILE_PAIN2", "S_EGGMOBILE_DIE1", @@ -4626,6 +4632,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE_FLEE2", "S_EGGMOBILE_BALL", "S_EGGMOBILE_TARGET", + "S_BOSSEGLZ1", + "S_BOSSEGLZ2", // Boss 2 "S_EGGMOBILE2_STND", @@ -4657,11 +4665,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Boss 3 "S_EGGMOBILE3_STND", - "S_EGGMOBILE3_LAUGH1", - "S_EGGMOBILE3_LAUGH2", - "S_EGGMOBILE3_LAUGH3", - "S_EGGMOBILE3_LAUGH4", - "S_EGGMOBILE3_LAUGH5", + "S_EGGMOBILE3_SHOCK", "S_EGGMOBILE3_ATK1", "S_EGGMOBILE3_ATK2", "S_EGGMOBILE3_ATK3A", @@ -4670,21 +4674,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE3_ATK3D", "S_EGGMOBILE3_ATK4", "S_EGGMOBILE3_ATK5", - "S_EGGMOBILE3_LAUGH6", - "S_EGGMOBILE3_LAUGH7", - "S_EGGMOBILE3_LAUGH8", - "S_EGGMOBILE3_LAUGH9", - "S_EGGMOBILE3_LAUGH10", - "S_EGGMOBILE3_LAUGH11", - "S_EGGMOBILE3_LAUGH12", - "S_EGGMOBILE3_LAUGH13", - "S_EGGMOBILE3_LAUGH14", - "S_EGGMOBILE3_LAUGH15", - "S_EGGMOBILE3_LAUGH16", - "S_EGGMOBILE3_LAUGH17", - "S_EGGMOBILE3_LAUGH18", - "S_EGGMOBILE3_LAUGH19", - "S_EGGMOBILE3_LAUGH20", + "S_EGGMOBILE3_ROFL", "S_EGGMOBILE3_PAIN", "S_EGGMOBILE3_PAIN2", "S_EGGMOBILE3_DIE1", @@ -4694,15 +4684,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE3_FLEE1", "S_EGGMOBILE3_FLEE2", - // Boss 3 Propeller - "S_PROPELLER1", - "S_PROPELLER2", - "S_PROPELLER3", - "S_PROPELLER4", - "S_PROPELLER5", - "S_PROPELLER6", - "S_PROPELLER7", - // Boss 3 pinch "S_FAKEMOBILE_INIT", "S_FAKEMOBILE", @@ -4715,6 +4696,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FAKEMOBILE_DIE1", "S_FAKEMOBILE_DIE2", + "S_BOSSSEBH1", + "S_BOSSSEBH2", + // Boss 4 "S_EGGMOBILE4_STND", "S_EGGMOBILE4_LATK1", @@ -5118,16 +5102,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_MSSHIELD_F1", "S_MSSHIELD_F2", - "S_MSSHIELD_F3", - "S_MSSHIELD_F4", - "S_MSSHIELD_F5", - "S_MSSHIELD_F6", - "S_MSSHIELD_F7", - "S_MSSHIELD_F8", - "S_MSSHIELD_F9", - "S_MSSHIELD_F10", - "S_MSSHIELD_F11", - "S_MSSHIELD_F12", // Ring "S_RING", @@ -7211,6 +7185,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_EGGTRAP", "MT_BOSS3WAYPOINT", "MT_BOSS9GATHERPOINT", + "MT_BOSSJUNK", // Boss 1 "MT_EGGMOBILE", @@ -7222,15 +7197,11 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Boss 2 "MT_EGGMOBILE2", "MT_EGGMOBILE2_POGO", - "MT_BOSSTANK1", - "MT_BOSSTANK2", - "MT_BOSSSPIGOT", "MT_GOOP", "MT_GOOPTRAIL", // Boss 3 "MT_EGGMOBILE3", - "MT_PROPELLER", "MT_FAKEMOBILE", "MT_SHOCK", diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index a52d72869..edfe328b8 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -186,17 +186,16 @@ light_t *t_lspr[NUMSPRITES] = // Boss 1, (Greenflower) &lspr[NOLIGHT], // SPR_EGGM + &lspr[NOLIGHT], // SPR_EGLZ // Boss 2, (Techno Hill) &lspr[NOLIGHT], // SPR_EGGN - &lspr[NOLIGHT], // SPR_TNKA - &lspr[NOLIGHT], // SPR_TNKB - &lspr[NOLIGHT], // SPR_SPNK + &lspr[NOLIGHT], // SPR_TANK &lspr[NOLIGHT], // SPR_GOOP // Boss 3 (Deep Sea) &lspr[NOLIGHT], // SPR_EGGO - &lspr[NOLIGHT], // SPR_PRPL + &lspr[NOLIGHT], // SPR_SEBH &lspr[NOLIGHT], // SPR_FAKE // Boss 4 (Castle Eggman) diff --git a/src/info.c b/src/info.c index 18f0e838a..5baf28943 100644 --- a/src/info.c +++ b/src/info.c @@ -73,18 +73,17 @@ char sprnames[NUMSPRITES + 1][5] = "JETF", // Boss jet fumes // Boss 1 (Greenflower) - "EGGM", + "EGGM", // Boss 1 + "EGLZ", // Boss 1 Junk // Boss 2 (Techno Hill) "EGGN", // Boss 2 - "TNKA", // Boss 2 Tank 1 - "TNKB", // Boss 2 Tank 2 - "SPNK", // Boss 2 Spigot + "TANK", // Boss 2 Junk "GOOP", // Boss 2 Goop // Boss 3 (Deep Sea) "EGGO", // Boss 3 - "PRPL", // Boss 3 Propeller + "SEBH", // Boss 3 Junk "FAKE", // Boss 3 Fakemobile // Boss 4 (Castle Eggman) @@ -1179,49 +1178,58 @@ state_t states[NUMSTATES] = {SPR_BOM3, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION6}, // S_SONIC3KBOSSEXPLOSION5 {SPR_BOM3, FF_FULLBRIGHT|5, 4, {NULL}, 0, 0, S_NULL}, // S_SONIC3KBOSSEXPLOSION6 - {SPR_JETF, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_JETFUME2}, // S_JETFUME1 - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_JETFUME1}, // S_JETFUME2 + {SPR_JETF, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 2, 1, S_NULL}, // S_JETFUME1 // Boss 1 {SPR_EGGM, 0, 1, {A_Boss1Chase}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_STND + {SPR_EGGM, FF_ANIMATE|17, 35, {A_FaceTarget}, 1, 2, S_EGGMOBILE_STND}, // S_EGGMOBILE_ROFL {SPR_EGGM, 1, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK2}, // S_EGGMOBILE_LATK1 {SPR_EGGM, 2, 15, {NULL}, 0, 0, S_EGGMOBILE_LATK3}, // S_EGGMOBILE_LATK2 - {SPR_EGGM, 3, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK4}, // S_EGGMOBILE_LATK3 - {SPR_EGGM, 4, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK5}, // S_EGGMOBILE_LATK4 - {SPR_EGGM, 5, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK6}, // S_EGGMOBILE_LATK5 - {SPR_EGGM, 6, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK7}, // S_EGGMOBILE_LATK6 - {SPR_EGGM, 7, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK8}, // S_EGGMOBILE_LATK7 - {SPR_EGGM, 8, 45, {A_Boss1Laser}, MT_LASER, 0, S_EGGMOBILE_LATK9}, // S_EGGMOBILE_LATK8 - {SPR_EGGM, 9, 10, {NULL}, 0, 0, S_EGGMOBILE_LATK10}, // S_EGGMOBILE_LATK9 - {SPR_EGGM, 10, 2, {NULL}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_LATK10 - {SPR_EGGM, 11, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK2}, // S_EGGMOBILE_RATK1 - {SPR_EGGM, 12, 15, {NULL}, 0, 0, S_EGGMOBILE_RATK3}, // S_EGGMOBILE_RATK2 - {SPR_EGGM, 13, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK4}, // S_EGGMOBILE_RATK3 - {SPR_EGGM, 14, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK5}, // S_EGGMOBILE_RATK4 - {SPR_EGGM, 15, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK6}, // S_EGGMOBILE_RATK5 - {SPR_EGGM, 16, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK7}, // S_EGGMOBILE_RATK6 - {SPR_EGGM, 17, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK8}, // S_EGGMOBILE_RATK7 - {SPR_EGGM, 18, 45, {A_Boss1Laser}, MT_LASER, 1, S_EGGMOBILE_RATK9}, // S_EGGMOBILE_RATK8 - {SPR_EGGM, 19, 10, {NULL}, 0, 0, S_EGGMOBILE_RATK10}, // S_EGGMOBILE_RATK9 - {SPR_EGGM, 20, 2, {NULL}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_RATK10 - {SPR_EGGM, 3, 12, {NULL}, 0, 0, S_EGGMOBILE_PANIC2}, // S_EGGMOBILE_PANIC1 - {SPR_EGGM, 4, 45, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC3}, // S_EGGMOBILE_PANIC2 - {SPR_EGGM, 3, 8, {NULL}, 0, 0, S_EGGMOBILE_PANIC4}, // S_EGGMOBILE_PANIC3 - {SPR_EGGM, 4, 45, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC5 }, // S_EGGMOBILE_PANIC4 - {SPR_EGGM, 3, 8, {NULL}, 0, 0, S_EGGMOBILE_PANIC6}, // S_EGGMOBILE_PANIC5 - {SPR_EGGM, 4, 45, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC7 }, // S_EGGMOBILE_PANIC6 - {SPR_EGGM, 0, 35, {NULL}, 0, 0, S_EGGMOBILE_STND }, // S_EGGMOBILE_PANIC7 - {SPR_EGGM, 21, 24, {A_Pain}, 0, 0, S_EGGMOBILE_PAIN2}, // S_EGGMOBILE_PAIN - {SPR_EGGM, 21, 16, {A_SkullAttack}, 1, 1, S_EGGMOBILE_STND}, // S_EGGMOBILE_PAIN2 - {SPR_EGGM, 22, 2, {A_Fall}, 0, 0, S_EGGMOBILE_DIE2}, // S_EGGMOBILE_DIE1 - {SPR_EGGM, 22, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_DIE3}, // S_EGGMOBILE_DIE2 - {SPR_EGGM, 22, 0, {A_Repeat}, 17, S_EGGMOBILE_DIE2, S_EGGMOBILE_DIE4}, // S_EGGMOBILE_DIE3 - {SPR_EGGM, 22, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE_DIE4 - {SPR_EGGM, 23, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE2}, // S_EGGMOBILE_FLEE1 - {SPR_EGGM, 24, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE1}, // S_EGGMOBILE_FLEE2 + {SPR_EGGM, 3, 2, {NULL}, 0, 0, S_EGGMOBILE_LATK4}, // S_EGGMOBILE_LATK3 + {SPR_EGGM, 4, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK5}, // S_EGGMOBILE_LATK4 + {SPR_EGGM, 6, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_LATK6}, // S_EGGMOBILE_LATK5 + {SPR_EGGM, 5, 1, {A_Boss1Laser}, MT_LASER, 0, S_EGGMOBILE_LATK7}, // S_EGGMOBILE_LATK6 + {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, (1<<16), S_EGGMOBILE_LATK8}, // S_EGGMOBILE_LATK7 + {SPR_EGGM, 5, 0, {A_Repeat}, 45, S_EGGMOBILE_LATK6, S_EGGMOBILE_LATK9}, // S_EGGMOBILE_LATK8 + {SPR_EGGM, 8, 2, {NULL}, 0, 0, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_LATK9 + {SPR_EGGM, 9, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK2}, // S_EGGMOBILE_RATK1 + {SPR_EGGM, 10, 15, {NULL}, 0, 0, S_EGGMOBILE_RATK3}, // S_EGGMOBILE_RATK2 + {SPR_EGGM, 11, 2, {NULL}, 0, 0, S_EGGMOBILE_RATK4}, // S_EGGMOBILE_RATK3 + {SPR_EGGM, 12, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK5}, // S_EGGMOBILE_RATK4 + {SPR_EGGM, 14, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_RATK6}, // S_EGGMOBILE_RATK5 + {SPR_EGGM, 13, 1, {A_Boss1Laser}, MT_LASER, 1, S_EGGMOBILE_RATK7}, // S_EGGMOBILE_RATK6 + {SPR_EGGM, 14, 1, {A_Boss1Laser}, MT_LASER, 1|(1<<16), S_EGGMOBILE_RATK8}, // S_EGGMOBILE_RATK7 + {SPR_EGGM, 13, 0, {A_Repeat}, 45, S_EGGMOBILE_RATK6, S_EGGMOBILE_RATK9}, // S_EGGMOBILE_RATK8 + {SPR_EGGM, 16, 2, {NULL}, 0, 0, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_RATK9 + {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC2}, // S_EGGMOBILE_PANIC1 + {SPR_EGGM, FF_ANIMATE|1, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC3}, // S_EGGMOBILE_PANIC2 + {SPR_EGGM, 7, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC4}, // S_EGGMOBILE_PANIC3 + {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC5}, // S_EGGMOBILE_PANIC4 + {SPR_EGGM, 6, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC3, S_EGGMOBILE_PANIC6}, // S_EGGMOBILE_PANIC5 + {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC7}, // S_EGGMOBILE_PANIC6 + {SPR_EGGM, FF_ANIMATE|9, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC8}, // S_EGGMOBILE_PANIC7 + {SPR_EGGM, 15, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC9}, // S_EGGMOBILE_PANIC8 + {SPR_EGGM, 14, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC10}, // S_EGGMOBILE_PANIC9 + {SPR_EGGM, 14, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC8, S_EGGMOBILE_PANIC11}, // S_EGGMOBILE_PANIC10 + {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC12}, // S_EGGMOBILE_PANIC11 + {SPR_EGGM, FF_ANIMATE|1, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC13}, // S_EGGMOBILE_PANIC12 + {SPR_EGGM, 7, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC14}, // S_EGGMOBILE_PANIC13 + {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC15}, // S_EGGMOBILE_PANIC14 + {SPR_EGGM, 6, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC13, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_PANIC15 + {SPR_EGGM, 19, 24, {A_Pain}, 0, 0, S_EGGMOBILE_PAIN2}, // S_EGGMOBILE_PAIN + {SPR_EGGM, 19, 16, {A_SkullAttack}, 3, 1, S_EGGMOBILE_STND}, // S_EGGMOBILE_PAIN2 + {SPR_EGGM, 20, 2, {A_Fall}, 17, 0, S_EGGMOBILE_DIE2}, // S_EGGMOBILE_DIE1 + {SPR_EGGM, 20, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_DIE3}, // S_EGGMOBILE_DIE2 + {SPR_EGGM, 20, 0, {A_Repeat}, 17, S_EGGMOBILE_DIE2, S_EGGMOBILE_DIE4}, // S_EGGMOBILE_DIE3 + {SPR_EGGM, 20, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE_DIE4 + {SPR_EGGM, 21, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE2}, // S_EGGMOBILE_FLEE1 + {SPR_EGGM, 22, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE1}, // S_EGGMOBILE_FLEE2 {SPR_UNID, 1, 1, {A_UnidusBall}, 2, 0, S_EGGMOBILE_BALL}, // S_EGGMOBILE_BALL {SPR_NULL, 0, 1, {A_FocusTarget}, 0, 0, S_EGGMOBILE_TARGET}, // S_EGGMOBILE_TARGET + {SPR_EGLZ, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSEGLZ1 + {SPR_EGLZ, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSEGLZ2 + // Boss 2 {SPR_EGGN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE2_STND {SPR_EGGN, 1, 4, {NULL}, 0, 0, S_EGGMOBILE2_POGO2}, // S_EGGMOBILE2_POGO1 @@ -1240,9 +1248,9 @@ state_t states[NUMSTATES] = {SPR_EGGN, 6, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_FLEE2}, // S_EGGMOBILE2_FLEE1 {SPR_EGGN, 7, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_FLEE1}, // S_EGGMOBILE2_FLEE2 - {SPR_TNKA, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK1 - {SPR_TNKB, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK2 - {SPR_SPNK, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSPIGOT + {SPR_TANK, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK1 + {SPR_TANK, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK2 + {SPR_TANK, 2, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSPIGOT // Boss 2 Goop {SPR_GOOP, 0, 2, {A_SpawnObjectRelative}, 0, MT_GOOPTRAIL, S_GOOP2}, // S_GOOP1 @@ -1252,34 +1260,16 @@ state_t states[NUMSTATES] = // Boss 3 {SPR_EGGO, 0, 1, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_STND - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH2}, // S_EGGMOBILE3_LAUGH1 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH3}, // S_EGGMOBILE3_LAUGH2 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH4}, // S_EGGMOBILE3_LAUGH3 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH5}, // S_EGGMOBILE3_LAUGH4 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_ATK1}, // S_EGGMOBILE3_LAUGH5 - {SPR_EGGO, 1, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_ATK1 + {SPR_EGGO, FF_ANIMATE, 24, {NULL}, 1, 2, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_SHOCK + {SPR_EGGO, 6|FF_ANIMATE, 24, {NULL}, 1, 2, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_ATK1 {SPR_EGGO, 2, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK3A}, // S_EGGMOBILE3_ATK2 {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 2, S_EGGMOBILE3_ATK3B}, // S_EGGMOBILE3_ATK3A {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 4, S_EGGMOBILE3_ATK3C}, // S_EGGMOBILE3_ATK3B {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 3, S_EGGMOBILE3_ATK3D}, // S_EGGMOBILE3_ATK3C {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 5, S_EGGMOBILE3_ATK4}, // S_EGGMOBILE3_ATK3D {SPR_EGGO, 4, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK5}, // S_EGGMOBILE3_ATK4 - {SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH6}, // S_EGGMOBILE3_ATK5 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH7}, // S_EGGMOBILE3_LAUGH6 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH8}, // S_EGGMOBILE3_LAUGH7 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH9}, // S_EGGMOBILE3_LAUGH8 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH10}, // S_EGGMOBILE3_LAUGH9 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH11}, // S_EGGMOBILE3_LAUGH10 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH12}, // S_EGGMOBILE3_LAUGH11 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH13}, // S_EGGMOBILE3_LAUGH12 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH14}, // S_EGGMOBILE3_LAUGH13 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH15}, // S_EGGMOBILE3_LAUGH14 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH16}, // S_EGGMOBILE3_LAUGH15 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH17}, // S_EGGMOBILE3_LAUGH16 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH18}, // S_EGGMOBILE3_LAUGH17 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH19}, // S_EGGMOBILE3_LAUGH18 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH20}, // S_EGGMOBILE3_LAUGH19 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_LAUGH20 + {SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_ROFL}, // S_EGGMOBILE3_ATK5 + {SPR_EGGO, 6|FF_ANIMATE, 60, {NULL}, 1, 2, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_ROFL {SPR_EGGO, 8, 1, {A_Boss3TakeDamage}, 0, 0, S_EGGMOBILE3_PAIN2}, // S_EGGMOBILE3_PAIN {SPR_EGGO, 8, 23, {A_Pain}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_PAIN2 {SPR_EGGO, 9, 2, {A_Fall}, 0, 0, S_EGGMOBILE3_DIE2}, // S_EGGMOBILE3_DIE1 @@ -1289,17 +1279,8 @@ state_t states[NUMSTATES] = {SPR_EGGO, 10, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_FLEE2}, // S_EGGMOBILE3_FLEE1 {SPR_EGGO, 11, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_FLEE1}, // S_EGGMOBILE3_FLEE2 - // Boss 3 Propeller - {SPR_PRPL, 0, 1, {NULL}, 0, 0, S_PROPELLER2}, // S_PROPELLER1 - {SPR_PRPL, 1, 1, {NULL}, 0, 0, S_PROPELLER3}, // S_PROPELLER2 - {SPR_PRPL, 2, 1, {NULL}, 0, 0, S_PROPELLER4}, // S_PROPELLER3 - {SPR_PRPL, 3, 1, {NULL}, 0, 0, S_PROPELLER5}, // S_PROPELLER4 - {SPR_PRPL, 4, 1, {NULL}, 0, 0, S_PROPELLER6}, // S_PROPELLER5 - {SPR_PRPL, 5, 1, {NULL}, 0, 0, S_PROPELLER7}, // S_PROPELLER6 - {SPR_PRPL, 6, 1, {NULL}, 0, 0, S_PROPELLER1}, // S_PROPELLER7 - // Boss 3 Pinch - {SPR_FAKE, 0, 1, {A_BossJetFume}, 1, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_INIT + {SPR_FAKE, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_INIT {SPR_FAKE, 0, 1, {A_Boss3Path}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE {SPR_FAKE, 0, 22, {NULL}, 0, 0, S_FAKEMOBILE_ATK2}, // S_FAKEMOBILE_ATK1 {SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK3A}, // S_FAKEMOBILE_ATK2 @@ -1307,33 +1288,36 @@ state_t states[NUMSTATES] = {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 4, S_FAKEMOBILE_ATK3C}, // S_FAKEMOBILE_ATK3B {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 3, S_FAKEMOBILE_ATK3D}, // S_FAKEMOBILE_ATK3C {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 5, S_FAKEMOBILE}, // S_FAKEMOBILE_ATK3D - {SPR_FAKE, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE2}, // S_FAKEMOBILE_DIE1 + {SPR_FAKE, 1, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE2}, // S_FAKEMOBILE_DIE1 {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE1}, // S_FAKEMOBILE_DIE2 + {SPR_SEBH, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSEBH1 + {SPR_SEBH, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSEBH2 + // Boss 4 {SPR_EGGP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_STND {SPR_EGGP, 1, 3, {NULL}, 0, 0, S_EGGMOBILE4_LATK2}, // S_EGGMOBILE4_LATK1 {SPR_EGGP, 2, 15, {NULL}, 0, 0, S_EGGMOBILE4_LATK3}, // S_EGGMOBILE4_LATK2 {SPR_EGGP, 3, 2, {NULL}, 0, 0, S_EGGMOBILE4_LATK4}, // S_EGGMOBILE4_LATK3 - {SPR_EGGP, 4, 4, {NULL}, 0, 0, S_EGGMOBILE4_LATK5}, // S_EGGMOBILE4_LATK4 - {SPR_EGGP, 4, 50, {A_Boss4Reverse}, sfx_mswing, 0, S_EGGMOBILE4_LATK6}, // S_EGGMOBILE4_LATK5 - {SPR_EGGP, 5, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_LATK6 - {SPR_EGGP, 6, 3, {NULL}, 0, 0, S_EGGMOBILE4_RATK2}, // S_EGGMOBILE4_RATK1 - {SPR_EGGP, 7, 15, {NULL}, 0, 0, S_EGGMOBILE4_RATK3}, // S_EGGMOBILE4_RATK2 - {SPR_EGGP, 8, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK4}, // S_EGGMOBILE4_RATK3 - {SPR_EGGP, 9, 4, {NULL}, 0, 0, S_EGGMOBILE4_RATK5}, // S_EGGMOBILE4_RATK4 - {SPR_EGGP, 9,150, {A_Boss4SpeedUp}, sfx_mswing, 0, S_EGGMOBILE4_RATK6}, // S_EGGMOBILE4_RATK5 - {SPR_EGGP,10, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RATK6 - {SPR_EGGP, 0, 20, {A_Boss4Raise}, sfx_doord1, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE1 - {SPR_EGGP,13|FF_ANIMATE, -1, {NULL}, 1, 10, S_NULL}, // S_EGGMOBILE4_RAISE2 - {SPR_EGGP,11, 0, {A_Boss4Reverse}, sfx_alarm, sfx_s3k60, S_EGGMOBILE4_PAIN2}, // S_EGGMOBILE4_PAIN1 - {SPR_EGGP,11, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN2 - {SPR_EGGP,12, 2, {A_Fall}, 0, 0, S_EGGMOBILE4_DIE2}, // S_EGGMOBILE4_DIE1 - {SPR_EGGP,12, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE3}, // S_EGGMOBILE4_DIE2 - {SPR_EGGP,12, 0, {A_Repeat}, 17, S_EGGMOBILE4_DIE2, S_EGGMOBILE4_DIE4}, // S_EGGMOBILE4_DIE3 - {SPR_EGGP,12, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE4_DIE4 - {SPR_EGGP,13, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE2}, // S_EGGMOBILE4_FLEE1 - {SPR_EGGP,14, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE1}, // S_EGGMOBILE4_FLEE2 + {SPR_EGGP, 4, 2, {NULL}, 0, 0, S_EGGMOBILE4_LATK5}, // S_EGGMOBILE4_LATK4 + {SPR_EGGP, 5, 50, {A_Boss4Reverse}, sfx_mswing, 0, S_EGGMOBILE4_LATK6}, // S_EGGMOBILE4_LATK5 + {SPR_EGGP, 6, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_LATK6 + {SPR_EGGP, 7, 3, {NULL}, 0, 0, S_EGGMOBILE4_RATK2}, // S_EGGMOBILE4_RATK1 + {SPR_EGGP, 8, 15, {NULL}, 0, 0, S_EGGMOBILE4_RATK3}, // S_EGGMOBILE4_RATK2 + {SPR_EGGP, 9, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK4}, // S_EGGMOBILE4_RATK3 + {SPR_EGGP,10, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK5}, // S_EGGMOBILE4_RATK4 + {SPR_EGGP,11,150, {A_Boss4SpeedUp}, sfx_mswing, 0, S_EGGMOBILE4_RATK6}, // S_EGGMOBILE4_RATK5 + {SPR_EGGP,12, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RATK6 + {SPR_EGGP,13, 20, {A_Boss4Raise}, sfx_doord1, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE1 + {SPR_EGGP,15|FF_ANIMATE, -1, {NULL}, 1, 10, S_NULL}, // S_EGGMOBILE4_RAISE2 + {SPR_EGGP,13, 0, {A_Boss4Reverse}, sfx_alarm, sfx_s3k60, S_EGGMOBILE4_PAIN2}, // S_EGGMOBILE4_PAIN1 + {SPR_EGGP,13, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN2 + {SPR_EGGP,14, 2, {A_Fall}, 0, 0, S_EGGMOBILE4_DIE2}, // S_EGGMOBILE4_DIE1 + {SPR_EGGP,14, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE3}, // S_EGGMOBILE4_DIE2 + {SPR_EGGP,14, 0, {A_Repeat}, 17, S_EGGMOBILE4_DIE2, S_EGGMOBILE4_DIE4}, // S_EGGMOBILE4_DIE3 + {SPR_EGGP,14, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE4_DIE4 + {SPR_EGGP,15, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE2}, // S_EGGMOBILE4_FLEE1 + {SPR_EGGP,16, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE1}, // S_EGGMOBILE4_FLEE2 {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_MACE {SPR_BMCE, 0, 2, {A_BossScream}, 1, 0, S_EGGMOBILE4_MACE_DIE2}, // S_EGGMOBILE4_MACE_DIE1 {SPR_NULL, 0, 2, {A_BossScream}, 1, 0, S_EGGMOBILE4_MACE_DIE3}, // S_EGGMOBILE4_MACE_DIE2 @@ -1732,18 +1716,8 @@ state_t states[NUMSTATES] = {SPR_METL, 11, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 {SPR_METL, 11, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 0, 1, {NULL}, 0, 0, S_MSSHIELD_F2}, // S_MSSHIELD_F1 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 1, 1, {NULL}, 0, 0, S_MSSHIELD_F3}, // S_MSSHIELD_F2 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 2, 1, {NULL}, 0, 0, S_MSSHIELD_F4}, // S_MSSHIELD_F3 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 3, 1, {NULL}, 0, 0, S_MSSHIELD_F5}, // S_MSSHIELD_F4 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 4, 1, {NULL}, 0, 0, S_MSSHIELD_F6}, // S_MSSHIELD_F5 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 5, 1, {NULL}, 0, 0, S_MSSHIELD_F7}, // S_MSSHIELD_F6 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 6, 1, {NULL}, 0, 0, S_MSSHIELD_F8}, // S_MSSHIELD_F7 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 7, 1, {NULL}, 0, 0, S_MSSHIELD_F9}, // S_MSSHIELD_F8 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 8, 1, {NULL}, 0, 0, S_MSSHIELD_F10}, // S_MSSHIELD_F9 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 9, 1, {NULL}, 0, 0, S_MSSHIELD_F11}, // S_MSSHIELD_F10 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|10, 1, {NULL}, 0, 0, S_MSSHIELD_F12}, // S_MSSHIELD_F11 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|11, 1, {NULL}, 0, 0, S_MSSHIELD_F1}, // S_MSSHIELD_F12 + {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|FF_ANIMATE, -1, {NULL}, 11, 1, S_NULL}, // S_MSSHIELD_F1 + {SPR_MSCF, FF_FULLBRIGHT|FF_ANIMATE|12, -1, {NULL}, 8, 2, S_NULL}, // S_MSSHIELD_F2 // Ring {SPR_RING, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_RING}, // S_RING @@ -5144,6 +5118,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BOSSJUNK + -1, // doomednum + S_BOSSEGLZ1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 64*FRACUNIT, // height + 2, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_EGGMOBILE 200, // doomednum S_EGGMOBILE_STND, // spawnstate @@ -5333,87 +5334,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_EGGMOBILE2_POGO5 // raisestate }, - { // MT_BOSSTANK1 - -1, // doomednum - S_BOSSTANK1, // spawnstate - 1, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 8*FRACUNIT, // radius - 64*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags - S_NULL // raisestate - }, - - { // MT_BOSSTANK2 - -1, // doomednum - S_BOSSTANK2, // spawnstate - 1, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 8*FRACUNIT, // radius - 64*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags - S_NULL // raisestate - }, - - { // MT_BOSSSPIGOT - -1, // doomednum - S_BOSSSPIGOT, // spawnstate - 1, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 8*FRACUNIT, // radius - 24*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags - S_NULL // raisestate - }, - { // MT_GOOP -1, // doomednum S_GOOP1, // spawnstate @@ -5477,10 +5397,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // reactiontime sfx_None, // attacksound S_EGGMOBILE3_PAIN, // painstate - MT_PROPELLER, // painchance + MT_NULL, // painchance sfx_dmpain, // painsound S_NULL, // meleestate - S_EGGMOBILE3_LAUGH1,// missilestate + S_EGGMOBILE3_SHOCK, // missilestate S_EGGMOBILE3_DIE1, // deathstate S_EGGMOBILE3_FLEE1, // xdeathstate sfx_s3kb4, // deathsound @@ -5492,34 +5412,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 3, // damage sfx_telept, // activesound MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY|MF_BOSS|MF_NOCLIPHEIGHT, // flags - S_EGGMOBILE3_LAUGH20 // raisestate - }, - - { // MT_PROPELLER - -1, // doomednum - S_PROPELLER1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 1, // speed - 4*FRACUNIT, // radius - 4*FRACUNIT, // height - 0, // display offset - 4, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags - S_NULL // raisestate + S_EGGMOBILE3_ROFL // raisestate }, { // MT_FAKEMOBILE @@ -5531,7 +5424,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate - MT_PROPELLER, // painchance + MT_NULL, // painchance sfx_s3k7b, // painsound S_NULL, // meleestate S_FAKEMOBILE_ATK1, // missilestate @@ -9211,7 +9104,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 20, // damage sfx_None, // activesound - MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP, // flags S_NULL // raisestate }, diff --git a/src/info.h b/src/info.h index 593c1fb7c..a9d4bdde0 100644 --- a/src/info.h +++ b/src/info.h @@ -319,18 +319,17 @@ typedef enum sprite SPR_JETF, // Boss jet fumes // Boss 1 (Greenflower) - SPR_EGGM, + SPR_EGGM, // Boss 1 + SPR_EGLZ, // Boss 1 Junk // Boss 2 (Techno Hill) SPR_EGGN, // Boss 2 - SPR_TNKA, // Boss 2 Tank 1 - SPR_TNKB, // Boss 2 Tank 2 - SPR_SPNK, // Boss 2 Spigot + SPR_TANK, // Boss 2 Junk SPR_GOOP, // Boss 2 Goop // Boss 3 (Deep Sea) SPR_EGGO, // Boss 3 - SPR_PRPL, // Boss 3 Propeller + SPR_SEBH, // Boss 3 Junk SPR_FAKE, // Boss 3 Fakemobile // Boss 4 (Castle Eggman) @@ -1333,10 +1332,10 @@ typedef enum state S_SONIC3KBOSSEXPLOSION6, S_JETFUME1, - S_JETFUME2, // Boss 1 S_EGGMOBILE_STND, + S_EGGMOBILE_ROFL, S_EGGMOBILE_LATK1, S_EGGMOBILE_LATK2, S_EGGMOBILE_LATK3, @@ -1346,7 +1345,6 @@ typedef enum state S_EGGMOBILE_LATK7, S_EGGMOBILE_LATK8, S_EGGMOBILE_LATK9, - S_EGGMOBILE_LATK10, S_EGGMOBILE_RATK1, S_EGGMOBILE_RATK2, S_EGGMOBILE_RATK3, @@ -1356,7 +1354,6 @@ typedef enum state S_EGGMOBILE_RATK7, S_EGGMOBILE_RATK8, S_EGGMOBILE_RATK9, - S_EGGMOBILE_RATK10, S_EGGMOBILE_PANIC1, S_EGGMOBILE_PANIC2, S_EGGMOBILE_PANIC3, @@ -1364,6 +1361,14 @@ typedef enum state S_EGGMOBILE_PANIC5, S_EGGMOBILE_PANIC6, S_EGGMOBILE_PANIC7, + S_EGGMOBILE_PANIC8, + S_EGGMOBILE_PANIC9, + S_EGGMOBILE_PANIC10, + S_EGGMOBILE_PANIC11, + S_EGGMOBILE_PANIC12, + S_EGGMOBILE_PANIC13, + S_EGGMOBILE_PANIC14, + S_EGGMOBILE_PANIC15, S_EGGMOBILE_PAIN, S_EGGMOBILE_PAIN2, S_EGGMOBILE_DIE1, @@ -1375,6 +1380,9 @@ typedef enum state S_EGGMOBILE_BALL, S_EGGMOBILE_TARGET, + S_BOSSEGLZ1, + S_BOSSEGLZ2, + // Boss 2 S_EGGMOBILE2_STND, S_EGGMOBILE2_POGO1, @@ -1405,11 +1413,7 @@ typedef enum state // Boss 3 S_EGGMOBILE3_STND, - S_EGGMOBILE3_LAUGH1, - S_EGGMOBILE3_LAUGH2, - S_EGGMOBILE3_LAUGH3, - S_EGGMOBILE3_LAUGH4, - S_EGGMOBILE3_LAUGH5, + S_EGGMOBILE3_SHOCK, S_EGGMOBILE3_ATK1, S_EGGMOBILE3_ATK2, S_EGGMOBILE3_ATK3A, @@ -1418,21 +1422,7 @@ typedef enum state S_EGGMOBILE3_ATK3D, S_EGGMOBILE3_ATK4, S_EGGMOBILE3_ATK5, - S_EGGMOBILE3_LAUGH6, - S_EGGMOBILE3_LAUGH7, - S_EGGMOBILE3_LAUGH8, - S_EGGMOBILE3_LAUGH9, - S_EGGMOBILE3_LAUGH10, - S_EGGMOBILE3_LAUGH11, - S_EGGMOBILE3_LAUGH12, - S_EGGMOBILE3_LAUGH13, - S_EGGMOBILE3_LAUGH14, - S_EGGMOBILE3_LAUGH15, - S_EGGMOBILE3_LAUGH16, - S_EGGMOBILE3_LAUGH17, - S_EGGMOBILE3_LAUGH18, - S_EGGMOBILE3_LAUGH19, - S_EGGMOBILE3_LAUGH20, + S_EGGMOBILE3_ROFL, S_EGGMOBILE3_PAIN, S_EGGMOBILE3_PAIN2, S_EGGMOBILE3_DIE1, @@ -1442,15 +1432,6 @@ typedef enum state S_EGGMOBILE3_FLEE1, S_EGGMOBILE3_FLEE2, - // Boss 3 Propeller - S_PROPELLER1, - S_PROPELLER2, - S_PROPELLER3, - S_PROPELLER4, - S_PROPELLER5, - S_PROPELLER6, - S_PROPELLER7, - // Boss 3 Pinch S_FAKEMOBILE_INIT, S_FAKEMOBILE, @@ -1463,6 +1444,9 @@ typedef enum state S_FAKEMOBILE_DIE1, S_FAKEMOBILE_DIE2, + S_BOSSSEBH1, + S_BOSSSEBH2, + // Boss 4 S_EGGMOBILE4_STND, S_EGGMOBILE4_LATK1, @@ -1866,16 +1850,6 @@ typedef enum state S_MSSHIELD_F1, S_MSSHIELD_F2, - S_MSSHIELD_F3, - S_MSSHIELD_F4, - S_MSSHIELD_F5, - S_MSSHIELD_F6, - S_MSSHIELD_F7, - S_MSSHIELD_F8, - S_MSSHIELD_F9, - S_MSSHIELD_F10, - S_MSSHIELD_F11, - S_MSSHIELD_F12, // Ring S_RING, @@ -3981,6 +3955,7 @@ typedef enum mobj_type MT_EGGTRAP, MT_BOSS3WAYPOINT, MT_BOSS9GATHERPOINT, + MT_BOSSJUNK, // Boss 1 MT_EGGMOBILE, @@ -3992,15 +3967,11 @@ typedef enum mobj_type // Boss 2 MT_EGGMOBILE2, MT_EGGMOBILE2_POGO, - MT_BOSSTANK1, - MT_BOSSTANK2, - MT_BOSSSPIGOT, MT_GOOP, MT_GOOPTRAIL, // Boss 3 MT_EGGMOBILE3, - MT_PROPELLER, MT_FAKEMOBILE, MT_SHOCK, diff --git a/src/p_enemy.c b/src/p_enemy.c index e3f169784..d4ec3fb96 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3003,16 +3003,19 @@ void A_Boss7FireMissiles(mobj_t *actor) // 0 - Boss 1 Left side // 1 - Boss 1 Right side // 2 - Triple laser -// >3 - Boss 1 Middle +// 3 - Boss 1 Middle +// >=3 - Generic middle // void A_Boss1Laser(mobj_t *actor) { fixed_t x, y, z, floorz, speed; INT32 locvar1 = var1; - INT32 locvar2 = var2; + INT32 locvar2 = (var2 & 65535); + INT32 upperend = (var2>>16); INT32 i; angle_t angle; mobj_t *point; + tic_t dur; #ifdef HAVE_BLUA if (LUA_CallAction("A_Boss1Laser", actor)) @@ -3021,19 +3024,24 @@ void A_Boss1Laser(mobj_t *actor) if (!actor->target) return; + if ((upperend & 1) && (actor->extravalue2 > 1)) + actor->extravalue2--; + + dur = actor->extravalue2; + switch (locvar2) { case 0: - x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); if (actor->eflags & MFE_VERTICALFLIP) z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height; else z = actor->z + FixedMul(56*FRACUNIT, actor->scale); break; case 1: - x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); if (actor->eflags & MFE_VERTICALFLIP) z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height; else @@ -3048,6 +3056,11 @@ void A_Boss1Laser(mobj_t *actor) A_Boss1Laser(actor); return; break; + case 3: + x = actor->x + P_ReturnThrustX(actor, actor->angle, FixedMul(42*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle, FixedMul(42*FRACUNIT, actor->scale)); + z = actor->z + actor->height/2; + break; default: x = actor->x; y = actor->y; @@ -3055,7 +3068,7 @@ void A_Boss1Laser(mobj_t *actor) break; } - if (!(actor->flags2 & MF2_FIRING) && actor->tics > 1) + if (!(actor->flags2 & MF2_FIRING) && dur > 1) { actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y); if (mobjinfo[locvar1].seesound) @@ -3064,7 +3077,7 @@ void A_Boss1Laser(mobj_t *actor) { point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); point->angle = actor->angle; - point->fuse = actor->tics+1; + point->fuse = dur+1; P_SetTarget(&point->target, actor->target); P_SetTarget(&actor->target, point); } @@ -3073,9 +3086,9 @@ void A_Boss1Laser(mobj_t *actor) else if (actor->target && !(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y);*/ - if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH) - angle = FixedAngle(FixedDiv(actor->tics*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT); - else + /*if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH) + angle = FixedAngle(FixedDiv(dur*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT); + else*/ angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, R_PointToDist2(x, y, actor->target->x, actor->target->y)); point = P_SpawnMobj(x, y, z, locvar1); @@ -3109,7 +3122,7 @@ void A_Boss1Laser(mobj_t *actor) point->fuse = TICRATE; } - if (actor->tics > 1) + if (dur > 1) actor->flags2 |= MF2_FIRING; else actor->flags2 &= ~MF2_FIRING; @@ -3253,6 +3266,7 @@ void A_Boss4Raise(mobj_t *actor) // 0 - Fly at the player // 1 - Fly away from the player // 2 - Strafe in relation to the player +// 3 - Dynamic mode - don't get too close to walls // var2: // 0 - Fly horizontally and vertically // 1 - Fly horizontal-only (momz = 0) @@ -3283,16 +3297,83 @@ void A_SkullAttack(mobj_t *actor) S_StartSound(actor, actor->info->activesound); A_FaceTarget(actor); + dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); + if (locvar1 == 1) actor->angle += ANGLE_180; else if (locvar1 == 2) actor->angle += (P_RandomChance(FRACUNIT/2)) ? ANGLE_90 : -ANGLE_90; + else if (locvar1 == 3) + { + statenum_t oldspawnstate = mobjinfo[MT_NULL].spawnstate; + UINT32 oldflags = mobjinfo[MT_NULL].flags; + fixed_t oldradius = mobjinfo[MT_NULL].radius; + fixed_t oldheight = mobjinfo[MT_NULL].height; + mobj_t *check; + INT32 i, j, k; + boolean allow; + angle_t testang; + + mobjinfo[MT_NULL].spawnstate = S_INVISIBLE; + mobjinfo[MT_NULL].flags = MF_NOGRAVITY|MF_NOTHINK|MF_NOCLIPTHING|MF_NOBLOCKMAP; + mobjinfo[MT_NULL].radius = mobjinfo[actor->type].radius; + mobjinfo[MT_NULL].height = mobjinfo[actor->type].height; + + if (P_RandomChance(FRACUNIT/2)) // port priority 1? + { + i = 9; + j = 27; + } + else + { + i = 27; + j = 9; + } + +#define dostuff(q) check = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_NULL);\ + testang = actor->angle + ((i+(q))*ANG10);\ + allow = (P_TryMove(check,\ + P_ReturnThrustX(check, testang, dist + 2*actor->radius),\ + P_ReturnThrustY(check, testang, dist + 2*actor->radius),\ + true));\ + P_RemoveMobj(check);\ + if (allow)\ + break; + + if (P_RandomChance(FRACUNIT/2)) // port priority 2? + { + for (k = 0; k < 9; k++) + { + dostuff(i+k) + dostuff(i-k) + dostuff(j+k) + dostuff(j-k) + } + } + else + { + for (k = 0; k < 9; k++) + { + dostuff(i-k) + dostuff(i+k) + dostuff(j-k) + dostuff(j+k) + } + } + actor->angle = testang; + +#undef dostuff + + mobjinfo[MT_NULL].spawnstate = oldspawnstate; + mobjinfo[MT_NULL].flags = oldflags; + mobjinfo[MT_NULL].radius = oldradius; + mobjinfo[MT_NULL].height = oldheight; + } an = actor->angle >> ANGLETOFINESHIFT; actor->momx = FixedMul(speed, FINECOSINE(an)); actor->momy = FixedMul(speed, FINESINE(an)); - dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); dist = dist / speed; if (dist < 1) @@ -3442,11 +3523,13 @@ void A_Pain(mobj_t *actor) // // Description: Changes a dying object's flags to reflect its having fallen to the ground. // -// var1 = unused +// var1 = value to set repeat to if nonzero // var2 = unused // void A_Fall(mobj_t *actor) { + INT32 locvar1 = var1; + #ifdef HAVE_BLUA if (LUA_CallAction("A_Fall", actor)) return; @@ -3459,6 +3542,9 @@ void A_Fall(mobj_t *actor) // So change this if corpse objects // are meant to be obstacles. + + if (locvar1) + actor->extravalue2 = locvar1; } #define LIVESBOXDISPLAYPLAYER // Use displayplayer instead of closest player @@ -3854,6 +3940,72 @@ bossjustdie: else if (P_MobjWasRemoved(mo)) return; #endif + + // Spawn your junk + switch (mo->type) + { + default: + break; + case MT_EGGMOBILE: // twin laser pods + { + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSEGLZ1); + + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSEGLZ2); + } + break; + case MT_EGGMOBILE2: // twin tanks + spigot + { + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSTANK1); + + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSTANK2); + + mo2 = P_SpawnMobjFromMobj(mo, 0, 0, + mobjinfo[MT_EGGMOBILE2].height + (32<angle = mo->angle; + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + mo2->momz += mo->momz; + P_SetMobjState(mo2, S_BOSSSPIGOT); + } + break; + case MT_EGGMOBILE3: + { + mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK); + mo2->angle = mo->angle; + P_SetMobjState(mo2, S_BOSSSEBH1); + } + break; + } + + // now do another switch case for escaping switch (mo->type) { case MT_BLACKEGGMAN: @@ -3951,7 +4103,7 @@ bossjustdie: mo->movedir = 0; mo->extravalue1 = 35; mo->flags2 |= MF2_BOSSFLEE; - mo->momz = 2*mo->scale; + mo->momz = P_MobjFlip(mo)*2*mo->scale; if (mo->target) { @@ -3969,50 +4121,6 @@ bossjustdie: break; } } - - if (mo->type == MT_EGGMOBILE2) - { - mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->y + P_ReturnThrustY(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK1].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK1); // Right tank - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) - { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; - } - P_InstaThrust(mo2, mo2->angle - ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale)); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - - mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->y + P_ReturnThrustY(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK2].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK2); // Left tank - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) - { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; - } - P_InstaThrust(mo2, mo2->angle + ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale)); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - - mo2 = P_SpawnMobj(mo->x, mo->y, - mo->z + ((mo->eflags & MFE_VERTICALFLIP)? mobjinfo[MT_BOSSSPIGOT].height-FixedMul(32*FRACUNIT,mo->scale): mo->height + FixedMul(32*FRACUNIT, mo->scale)), MT_BOSSSPIGOT); - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) - { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; - } - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - return; - } } // Function: A_CustomPower @@ -8699,7 +8807,7 @@ void A_SetObjectFlags2(mobj_t *actor) // // var1: // 0 - Triple jet fume pattern -// 1 - Boss 3's propeller +// 1 - Unused (formerly Boss 3's propeller) // 2 - Metal Sonic jet fume // 3 - Boss 4 jet flame // var2 = unused @@ -8759,7 +8867,7 @@ void A_BossJetFume(mobj_t *actor) P_SetTarget(&actor->tracer, filler); } - else if (locvar1 == 1) // Boss 3 propeller + /*else if (locvar1 == 1) // Boss 3 propeller { fixed_t jetx, jety, jetz; @@ -8779,14 +8887,14 @@ void A_BossJetFume(mobj_t *actor) filler->angle = actor->angle - ANGLE_180; P_SetTarget(&actor->tracer, filler); - } + }*/ else if (locvar1 == 2) // Metal Sonic jet fumes { filler = P_SpawnMobj(actor->x, actor->y, actor->z, MT_JETFUME1); P_SetTarget(&filler->target, actor); filler->fuse = 59; P_SetTarget(&actor->tracer, filler); - filler->destscale = actor->scale/2; + filler->destscale = actor->scale/3; P_SetScale(filler, filler->destscale); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; diff --git a/src/p_inter.c b/src/p_inter.c index 0030e8e58..ae610d0fc 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2594,6 +2594,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget case MT_EGGMOBILE3: { + mobj_t *mo2; thinker_t *th; UINT32 i = 0; // to check how many clones we've removed @@ -2614,6 +2615,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget mo->scalespeed = (mo->scale - mo->destscale)/(2*TICRATE); mo->momz = mo->info->speed; mo->angle = FixedAngle((P_RandomKey(36)*10)<angle = mo->angle; + P_SetMobjState(mo2, S_BOSSSEBH2); + if (++i == 2) // we've already removed 2 of these, let's stop now break; else diff --git a/src/p_mobj.c b/src/p_mobj.c index 1ee90d250..e5edc99c4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4359,12 +4359,6 @@ static void P_Boss3Thinker(mobj_t *mobj) if (mobj->flags2 & MF2_FRET) mobj->movedir = 1; - if (!mobj->tracer) - { - var1 = 1; - A_BossJetFume(mobj); - } - if (mobj->health <= 0) return; /* @@ -4493,7 +4487,7 @@ static void P_Boss3Thinker(mobj_t *mobj) if (mobj->health <= mobj->info->damage) // pinch phase mobj->movecount--; // limited number of shots before diving again if (mobj->movecount) - P_SetMobjState(mobj, mobj->info->missilestate); + P_SetMobjState(mobj, mobj->info->missilestate+1); } } else if (mobj->threshold >= 0) // Traveling mode @@ -4592,6 +4586,15 @@ static void P_Boss3Thinker(mobj_t *mobj) ang += (ANGLE_MAX/64); } S_StartSound(mobj, sfx_fizzle); + + // look for a new target + P_BossTargetPlayer(mobj, false); + + if (mobj->target && mobj->target->player) + { + A_FaceTarget(mobj); + P_SetMobjState(mobj, mobj->info->missilestate); + } } else if (mobj->flags2 & (MF2_STRONGBOX|MF2_CLASSICPUSH)) // just hit the bottom of your tube { @@ -5527,8 +5530,7 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); P_SetScale(mobj->tracer, mobj->tracer->destscale); } - else - mobj->tracer->frame &= ~FF_TRANSMASK; // this causes a flicker but honestly i like it this way + P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2); mobj->tracer->momx = mobj->momx; mobj->tracer->momy = mobj->momy; @@ -5645,12 +5647,12 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->health > mobj->info->damage) { - P_SetScale(missile, FRACUNIT/2); + P_SetScale(missile, FRACUNIT/3); missile->color = SKINCOLOR_GOLD; // sonic cd electric power } else { - P_SetScale(missile, FRACUNIT/4); + P_SetScale(missile, FRACUNIT/5); missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power } missile->destscale = missile->scale*2; @@ -5940,9 +5942,7 @@ static void P_Boss9Thinker(mobj_t *mobj) P_SetTarget(&mobj->tracer, shield); P_SetTarget(&shield->target, mobj); shield->height -= 20*FRACUNIT; // different offset... - shield->color = SKINCOLOR_MAGENTA; - shield->colorized = true; - P_SetMobjState(shield, S_FIRS1); + P_SetMobjState(shield, S_MSSHIELD_F2); //P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2... } mobj->fuse = 4*TICRATE; @@ -7093,9 +7093,7 @@ void P_MobjThinker(mobj_t *mobj) switch (mobj->type) { - case MT_BOSSTANK1: - case MT_BOSSTANK2: - case MT_BOSSSPIGOT: + case MT_BOSSJUNK: mobj->flags2 ^= MF2_DONTDRAW; break; case MT_MACEPOINT: @@ -7681,12 +7679,22 @@ void P_MobjThinker(mobj_t *mobj) switch (mobj->type) { case MT_EGGMOBILE: - if (mobj->health < mobj->info->damage+1 && leveltime & 1 && mobj->health > 0) - P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMOKE); + if (mobj->health < mobj->info->damage+1 && leveltime & 2) + { + fixed_t rad = mobj->radius>>FRACBITS; + fixed_t hei = mobj->height>>FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad)<momz += mobj->momz; + } if (mobj->flags2 & MF2_SKULLFLY) #if 1 P_SpawnGhostMobj(mobj); -#else +#else // all the way back from final demo... MT_THOK isn't even the same size anymore! { mobj_t *spawnmobj; spawnmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->painchance); @@ -7697,12 +7705,48 @@ void P_MobjThinker(mobj_t *mobj) P_Boss1Thinker(mobj); break; case MT_EGGMOBILE2: + if (mobj->health < mobj->info->damage+1 && leveltime & 2) + { + fixed_t rad = mobj->radius>>FRACBITS; + fixed_t hei = mobj->height>>FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad)<momz += mobj->momz; + } P_Boss2Thinker(mobj); break; case MT_EGGMOBILE3: + if (mobj->health < mobj->info->damage+1 && leveltime & 2) + { + fixed_t rad = mobj->radius>>FRACBITS; + fixed_t hei = mobj->height>>FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad)<momz += mobj->momz; + } P_Boss3Thinker(mobj); break; case MT_EGGMOBILE4: + if (mobj->health < mobj->info->damage+1 && leveltime & 2) + { + fixed_t rad = mobj->radius>>FRACBITS; + fixed_t hei = mobj->height>>FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad)<momz += mobj->momz; + } P_Boss4Thinker(mobj); break; case MT_FANG: @@ -8318,30 +8362,6 @@ void P_MobjThinker(mobj_t *mobj) mobj->fuse++; } break; - case MT_PROPELLER: - { - fixed_t jetx, jety; - - if (!mobj->target // if you have no target - || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now - { // then remove yourself as well! - P_RemoveMobj(mobj); - return; - } - - jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-60*FRACUNIT, mobj->target->scale)); - jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-60*FRACUNIT, mobj->target->scale)); - - P_UnsetThingPosition(mobj); - mobj->x = jetx; - mobj->y = jety; - mobj->z = mobj->target->z + FixedMul(17*FRACUNIT, mobj->target->scale); - mobj->angle = mobj->target->angle - ANGLE_180; - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - break; case MT_JETFLAME: { if (!mobj->target // if you have no target @@ -9038,9 +9058,9 @@ void P_MobjThinker(mobj_t *mobj) { if (mobj->state->action.acp1 == (actionf_p1)A_Boss1Laser) { - var1 = mobj->state->var1; - var2 = mobj->state->var2; - mobj->state->action.acp1(mobj); + /*var1 = mobj->state->var1; + var2 = mobj->state->var2 & 65535; + mobj->state->action.acp1(mobj);*/ } else if (leveltime & 1) // Fire mode { diff --git a/src/r_draw.c b/src/r_draw.c index d8b720caf..396ed0344 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -557,9 +557,16 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U // White! if (skinnum == TC_BOSS) - dest_colormap[31] = 0; + { + for (i = 0; i < 16; i++) + dest_colormap[31-i] = i; + } else if (skinnum == TC_METALSONIC) - dest_colormap[159] = 0; + { + for (i = 0; i < 6; i++) + dest_colormap[Color_Index[SKINCOLOR_BLUE-1][12-i]] = Color_Index[SKINCOLOR_BLUE-1][i]; + dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0; + } return; } else if (color == SKINCOLOR_NONE) From bbe8ef9ff72710934692186a11e13eea9cfc3107 Mon Sep 17 00:00:00 2001 From: James Date: Sat, 31 Aug 2019 17:06:01 -0400 Subject: [PATCH 041/133] Merged orbital cam, made my reset code not run in NiGHTS, 2D mode, or when exiting levels. --- src/p_user.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 4eeb2a7db..97ab5894a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9570,7 +9570,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (checkdist < 128*FRACUNIT) checkdist = 128*FRACUNIT; - if ((thiscam == &camera && cv_cam_orbit.value) || (thiscam == &camera2 && cv_cam2_orbit.value)) + if ((thiscam == &camera && cv_cam_orbit.value) || (thiscam == &camera2 && cv_cam2_orbit.value)) //Sev here, I'm guessing this is where orbital cam lives { distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); distz = -FixedMul(dist, FINESINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); @@ -9584,6 +9584,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), distxy); y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), distxy); + if (!(twodlevel || (mo->flags2 & MF2_TWOD)) && !(player->powers[pw_carry] == CR_NIGHTSMODE) && !(player->exiting)) //Which is why I'm slapping my cam reset code in here too + { + if ((P_AproxDistance(player->mo->x-thiscam->x-thiscam->momx, player->mo->y-thiscam->y-thiscam->momy) > ((player->speed+camdist)*2)) || (abs(thiscam->z - player->mo->z) > ((player->speed+camdist)*2))) + P_ResetCamera(player, thiscam); + } + #if 0 if (twodlevel || (mo->flags2 & MF2_TWOD)) { @@ -9934,6 +9940,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming); + } boolean P_SpectatorJoinGame(player_t *player) @@ -11591,21 +11598,9 @@ void P_PlayerAfterThink(player_t *player) #endif if (splitscreen && player == &players[secondarydisplayplayer]) - { thiscam = &camera2; - if ((P_AproxDistance(player->mo->x-thiscam->x-thiscam->momx, player->mo->y-thiscam->y-thiscam->momy) > ((player->speed+cv_cam2_dist.value)*2)) || (abs(thiscam->z - player->mo->z) > ((player->speed+cv_cam2_dist.value)*2))) - { - P_ResetCamera(player, thiscam); - } - } else if (player == &players[displayplayer]) - { thiscam = &camera; - if ((P_AproxDistance(player->mo->x-thiscam->x-thiscam->momx, player->mo->y-thiscam->y-thiscam->momy) > ((player->speed+cv_cam_dist.value)*2)) || (abs(thiscam->z - player->mo->z) > ((player->speed+cv_cam_dist.value)*2))) - { - P_ResetCamera(player, thiscam); - } - } if (player->playerstate == PST_DEAD) { From fe99c64511c71553d9ac5b945439b9986fd73151 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 1 Sep 2019 11:43:30 +0100 Subject: [PATCH 042/133] Give the Spectator Eggrobos the ability to move left and right relative to their angle, with initial direction depending on MTF_OBJECTSPECIAL/MTF_AMBUSH flag presence. (May need more tweaking before putting in CEZ3) --- src/p_mobj.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index e5edc99c4..1f42e3664 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8425,6 +8425,17 @@ void P_MobjThinker(mobj_t *mobj) } else { + + fixed_t basex = mobj->cusval, basey = mobj->cvmem; + + if (mobj->spawnpoint && mobj->spawnpoint->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)) + { + angle_t sideang = mobj->movedir + ((mobj->spawnpoint->options & MTF_AMBUSH) ? ANGLE_90 : -ANGLE_90); + fixed_t oscillate = FixedMul(FINESINE(((leveltime*ANG1)>>(ANGLETOFINESHIFT+2)) & FINEMASK), 250*mobj->scale); + basex += P_ReturnThrustX(mobj, sideang, oscillate); + basey += P_ReturnThrustY(mobj, sideang, oscillate); + } + mobj->z = mobj->threshold + FixedMul(FINESINE(((leveltime + mobj->movecount)*ANG2>>(ANGLETOFINESHIFT-2)) & FINEMASK), 8*mobj->scale); if (mobj->state != &states[mobj->info->meleestate]) { @@ -8453,8 +8464,8 @@ void P_MobjThinker(mobj_t *mobj) if (players[i].mo->z + players[i].mo->height < mobj->z - 8*mobj->scale) continue; compdist = P_AproxDistance( - players[i].mo->x + players[i].mo->momx - mobj->cusval, - players[i].mo->y + players[i].mo->momy - mobj->cvmem); + players[i].mo->x + players[i].mo->momx - basex, + players[i].mo->y + players[i].mo->momy - basey); if (compdist >= dist) continue; dist = compdist; @@ -8468,14 +8479,14 @@ void P_MobjThinker(mobj_t *mobj) mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); if (P_AproxDistance( - mobj->x - mobj->cusval, - mobj->y - mobj->cvmem) + mobj->x - basex, + mobj->y - basey) < mobj->scale) S_StartSound(mobj, mobj->info->seesound); P_TeleportMove(mobj, - (15*(mobj->x>>4)) + (mobj->cusval>>4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS>>4), - (15*(mobj->y>>4)) + (mobj->cvmem>>4) + P_ReturnThrustY(mobj, mobj->angle, SPECTATORRADIUS>>4), + (15*(mobj->x>>4)) + (basex>>4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS>>4), + (15*(mobj->y>>4)) + (basey>>4) + P_ReturnThrustY(mobj, mobj->angle, SPECTATORRADIUS>>4), mobj->z); } else @@ -8498,18 +8509,12 @@ void P_MobjThinker(mobj_t *mobj) if (!didmove) { - if (P_AproxDistance( - mobj->x - mobj->cusval, - mobj->y - mobj->cvmem) - < mobj->scale) - P_TeleportMove(mobj, - mobj->cusval, - mobj->cvmem, - mobj->z); + if (P_AproxDistance(mobj->x - basex, mobj->y - basey) < mobj->scale) + P_TeleportMove(mobj, basex, basey, mobj->z); else P_TeleportMove(mobj, - (15*(mobj->x>>4)) + (mobj->cusval>>4), - (15*(mobj->y>>4)) + (mobj->cvmem>>4), + (15*(mobj->x>>4)) + (basex>>4), + (15*(mobj->y>>4)) + (basey>>4), mobj->z); } } From f07309707d2cae3c90202c0a4ec5932df3443407 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 1 Sep 2019 15:55:23 +0100 Subject: [PATCH 043/133] Lots of death stuff. * Genesis-style love and attention to the death event. * Only visibly decrement lives/rings when you're respawning (or game over, see below). * Faster no-button-press respawn. * Game Over specific love. * Animation of Level Title font coming in from the sides. * https://cdn.discordapp.com/attachments/428262628893261828/617692325438554132/srb20067.gif * Change gameovertics to 10 seconds instead of 15. * Make the minimum time before you can force going to the Continue screen longer. * Accomodate death in MP special stages as a form of exit. * Don't have your rings or spheres reset when you die in a special stage, so that the stage isn't softlocked with the new harder limits. * Fix a bug with CoopLives_OnChange where changing to infinite lives didn't force a game-overed player to respawn. Also, two not-quite death things which nonetheless were relevant to change: * Fix quitting a special stage having some of the shared spheres/rings disappear into the aether. * Fix a warning during compilation for the Ring Penalty print. --- src/d_clisrv.c | 27 ++++++++++++++++++++++----- src/d_netcmd.c | 10 +--------- src/g_game.c | 20 ++++++++++++++++---- src/p_inter.c | 5 +---- src/p_mobj.c | 3 +-- src/p_user.c | 30 +++++++++++++----------------- src/st_stuff.c | 42 +++++++++++++++++++++++------------------- 7 files changed, 77 insertions(+), 60 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 01e94485d..2ce395769 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2415,7 +2415,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) // the remaining players. if (G_IsSpecialStage(gamemap)) { - INT32 i, count, increment, spheres; + INT32 i, count, sincrement, spheres, rincrement, rings; for (i = 0, count = 0; i < MAXPLAYERS; i++) { @@ -2425,18 +2425,35 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) count--; spheres = players[playernum].spheres; - increment = spheres/count; + rings = players[playernum].rings; + sincrement = spheres/count; + rincrement = rings/count; for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && i != playernum) { - if (spheres < increment) + if (spheres < 2*sincrement) + { P_GivePlayerSpheres(&players[i], spheres); + spheres = 0; + } else - P_GivePlayerSpheres(&players[i], increment); + { + P_GivePlayerSpheres(&players[i], sincrement); + spheres -= sincrement; + } - spheres -= increment; + if (rings < 2*rincrement) + { + P_GivePlayerRings(&players[i], rings); + rings = 0; + } + else + { + P_GivePlayerRings(&players[i], rincrement); + rings -= rincrement; + } } } } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3e82fc60c..ba28b19a2 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2706,14 +2706,6 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } } - // Clear player score and rings if a spectator. - if (players[playernum].spectator) - { - players[playernum].score = players[playernum].rings = 0; - if (players[playernum].mo) - players[playernum].mo->health = 1; - } - // In tag, check to see if you still have a game. if (G_TagGametype()) P_CheckSurvivors(); @@ -3600,7 +3592,7 @@ static void CoopLives_OnChange(void) { case 0: CONS_Printf(M_GetText("Players can now respawn indefinitely.\n")); - return; + break; case 1: CONS_Printf(M_GetText("Lives are now per-player.\n")); return; diff --git a/src/g_game.c b/src/g_game.c index d5faf6846..1630f085b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -215,7 +215,7 @@ UINT16 spacetimetics = 11*TICRATE + (TICRATE/2); UINT16 extralifetics = 4*TICRATE; UINT16 nightslinktics = 2*TICRATE; -INT32 gameovertics = 15*TICRATE; +INT32 gameovertics = 10*TICRATE; UINT8 ammoremovaltics = 2*TICRATE; @@ -2145,6 +2145,8 @@ void G_PlayerReborn(INT32 player) boolean outofcoop; INT16 bot; SINT8 pity; + INT16 rings; + INT16 spheres; score = players[player].score; lives = players[player].lives; @@ -2199,6 +2201,17 @@ void G_PlayerReborn(INT32 player) bot = players[player].bot; pity = players[player].pity; + if (!G_IsSpecialStage(gamemap)) + { + rings = (ultimatemode ? 0 : mapheaderinfo[gamemap-1]->startrings); + spheres = 0; + } + else + { + rings = players[player].rings; + spheres = players[player].spheres; + } + p = &players[player]; memset(p, 0, sizeof (*p)); @@ -2252,6 +2265,8 @@ void G_PlayerReborn(INT32 player) if (bot) p->bot = 1; // reset to AI-controlled p->pity = pity; + p->rings = rings; + p->spheres = spheres; // Don't do anything immediately p->pflags |= PF_USEDOWN; @@ -2259,7 +2274,6 @@ void G_PlayerReborn(INT32 player) p->pflags |= PF_JUMPDOWN; p->playerstate = PST_LIVE; - p->rings = p->spheres = 0; // 0 rings p->panim = PA_IDLE; // standing animation //if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there @@ -2370,8 +2384,6 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) P_SpawnPlayer(playernum); - players[playernum].rings = mapheaderinfo[gamemap-1]->startrings; - if (starpost) //Don't even bother with looking for a place to spawn. { P_MovePlayerToStarpost(playernum); diff --git a/src/p_inter.c b/src/p_inter.c index 0030e8e58..9025e2664 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3500,7 +3500,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return true; } - if (G_IsSpecialStage(gamemap)) + if (G_IsSpecialStage(gamemap) && !(damagetype & DMG_DEATHMASK)) { P_SpecialStageDamage(player, inflictor, source); return true; @@ -3524,10 +3524,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // Instant-Death if (damagetype & DMG_DEATHMASK) - { P_KillPlayer(player, source, damage); - player->rings = player->spheres = 0; - } else if (metalrecording) { if (!inflictor) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1ee90d250..abf5de87d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10397,7 +10397,7 @@ void P_SpawnPlayer(INT32 playernum) && ((leveltime > 0 && ((G_IsSpecialStage(gamemap) && (maptol & TOL_NIGHTS)) // late join special stage || (cv_coopstarposts.value == 2 && (p->jointime < 1 || p->outofcoop)))) // late join or die in new coop - || (((cv_cooplives.value == 1) || !P_GetLives(p)) && p->lives <= 0))); // game over and can't redistribute lives + || (!P_GetLives(p) && p->lives <= 0))); // game over and can't redistribute lives } else { @@ -10464,7 +10464,6 @@ void P_SpawnPlayer(INT32 playernum) P_SetupStateAnimation(mobj, mobj->state); mobj->health = 1; - p->rings = p->spheres = 0; p->playerstate = PST_LIVE; p->bonustime = false; diff --git a/src/p_user.c b/src/p_user.c index a69bd5b93..08579e48d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9027,19 +9027,22 @@ boolean P_GetLives(player_t *player) INT32 i, maxlivesplayer = -1, livescheck = 1; if (!(netgame || multiplayer) || (gametype != GT_COOP) - || (cv_cooplives.value == 1) || (player->lives == INFLIVES)) return true; - if ((cv_cooplives.value == 2 || cv_cooplives.value == 0) && player->lives > 0) - return true; - if (cv_cooplives.value == 0) // infinite lives { - player->lives++; + if (player->lives < 1) + player->lives = 1; return true; } + if ((cv_cooplives.value == 2 || cv_cooplives.value == 1) && player->lives > 0) + return true; + + if (cv_cooplives.value == 1) + return false; + for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) @@ -9146,7 +9149,7 @@ static void P_DeathThink(player_t *player) // continue logic if (!(netgame || multiplayer) && player->lives <= 0) { - if (player->deadtimer > TICRATE && (cmd->buttons & BT_USE || cmd->buttons & BT_JUMP) && player->continues > 0) + if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_USE || cmd->buttons & BT_JUMP) && player->continues > 0) G_UseContinue(); else if (player->deadtimer >= gameovertics) G_UseContinue(); // Even if we don't have one this handles ending the game @@ -9170,12 +9173,12 @@ static void P_DeathThink(player_t *player) // Force respawn if idle for more than 30 seconds in shooter modes. if (player->deadtimer > 30*TICRATE && !G_PlatformGametype()) player->playerstate = PST_REBORN; - else if ((player->lives > 0 || j != MAXPLAYERS) && !G_IsSpecialStage(gamemap)) // Don't allow "click to respawn" in special stages! + else if ((player->lives > 0 || j != MAXPLAYERS) && !(G_IsSpecialStage(gamemap))) // Don't allow "click to respawn" in special stages! { if (gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2) { P_ConsiderAllGone(); - if ((player->deadtimer > 5*TICRATE) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))) + if ((player->deadtimer > TICRATE<<1) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))) { //player->spectator = true; player->outofcoop = true; @@ -9191,16 +9194,11 @@ static void P_DeathThink(player_t *player) player->playerstate = PST_REBORN; else switch(gametype) { case GT_COOP: - if (player->deadtimer > TICRATE) - player->playerstate = PST_REBORN; - break; case GT_COMPETITION: + case GT_RACE: if (player->deadtimer > TICRATE) player->playerstate = PST_REBORN; break; - case GT_RACE: - player->playerstate = PST_REBORN; - break; default: if (player->deadtimer > cv_respawntime.value*TICRATE) player->playerstate = PST_REBORN; @@ -9209,7 +9207,7 @@ static void P_DeathThink(player_t *player) } // Single player auto respawn - if (!(netgame || multiplayer) && player->deadtimer > 5*TICRATE) + if (!(netgame || multiplayer) && player->deadtimer > TICRATE<<1) player->playerstate = PST_REBORN; } } @@ -11011,8 +11009,6 @@ void P_PlayerThink(player_t *player) { if (gametype != GT_COOP) player->score = 0; - player->mo->health = 1; - player->rings = player->spheres = 0; } else if ((netgame || multiplayer) && player->lives <= 0 && gametype != GT_COOP) { diff --git a/src/st_stuff.c b/src/st_stuff.c index 142cd3e61..0db72efd1 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -66,8 +66,6 @@ patch_t *sboperiod; // Period for time centiseconds patch_t *livesback; // Lives icon background static patch_t *nrec_timer; // Timer for NiGHTS records static patch_t *sborings; -static patch_t *sboover; -static patch_t *timeover; static patch_t *stlivex; static patch_t *sboredrings; static patch_t *sboredtime; @@ -253,8 +251,6 @@ void ST_LoadGraphics(void) sbocolon = W_CachePatchName("STTCOLON", PU_HUDGFX); // Colon for time sboperiod = W_CachePatchName("STTPERIO", PU_HUDGFX); // Period for time centiseconds - sboover = W_CachePatchName("SBOOVER", PU_HUDGFX); - timeover = W_CachePatchName("TIMEOVER", PU_HUDGFX); stlivex = W_CachePatchName("STLIVEX", PU_HUDGFX); livesback = W_CachePatchName("STLIVEBK", PU_HUDGFX); nrec_timer = W_CachePatchName("NGRTIMER", PU_HUDGFX); // Timer for NiGHTS @@ -768,7 +764,12 @@ static inline void ST_drawRings(void) ST_DrawPatchFromHud(HUD_RINGS, ((!stplyr->spectator && stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings), ((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS)); - ringnum = ((objectplacing) ? op_currentdoomednum : max(stplyr->rings, 0)); + if (objectplacing) + ringnum = op_currentdoomednum; + else if (stplyr->rings < 0 || stplyr->spectator || stplyr->playerstate == PST_REBORN) + ringnum = 0; + else + ringnum = stplyr->rings; if (cv_timetic.value == 2) // Yes, even in modeattacking ST_DrawNumFromHud(HUD_RINGSNUMTICS, ringnum, V_PERPLAYER|((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS)); @@ -877,6 +878,8 @@ static void ST_drawLivesArea(void) '\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false); else { + if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1))) + livescount++; if (livescount > 99) livescount = 99; V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, @@ -1960,7 +1963,7 @@ static void ST_drawWeaponRing(powertype_t weapon, INT32 rwflag, INT32 wepflag, I static void ST_drawMatchHUD(void) { - char penaltystr[5]; + char penaltystr[7]; const INT32 y = 176; // HUD_LIVES INT32 offset = (BASEVIDWIDTH / 2) - (NUM_WEAPONS * 10) - 6; @@ -2409,25 +2412,20 @@ static void ST_overlayDrawer(void) } } - // GAME OVER pic + // GAME OVER hud if ((gametype == GT_COOP) && (netgame || multiplayer) && (cv_cooplives.value == 0)) ; else if (G_GametypeUsesLives() && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer))) { - patch_t *p; - - if (countdown == 1) - p = timeover; - else - p = sboover; + INT32 i = MAXPLAYERS; + INT32 deadtimer = stplyr->spectator ? TICRATE : (stplyr->deadtimer-(TICRATE<<1)); if ((gametype == GT_COOP) && (netgame || multiplayer) && (cv_cooplives.value != 1)) { - INT32 i; for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) @@ -2437,15 +2435,21 @@ static void ST_overlayDrawer(void) continue; if (players[i].lives > 0) - { - p = NULL; break; - } } } - if (p) - V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, BASEVIDHEIGHT/2 - (SHORT(p->height)/2), V_PERPLAYER|(stplyr->spectator ? V_HUDTRANSHALF : V_HUDTRANS), p); + if (i == MAXPLAYERS && deadtimer >= 0) + { + const char *first = (countdown == 1) ? "TIME" : "GAME"; + const char *second = "OVER"; + INT32 w1 = V_LevelNameWidth(first), w2 = (w1 + 16 + V_LevelNameWidth(second))>>1; + INT32 lvlttlx1 = min(6*deadtimer, BASEVIDWIDTH/2), lvlttlx2 = BASEVIDWIDTH - lvlttlx1; + UINT32 flags = V_PERPLAYER|(stplyr->spectator ? V_HUDTRANSHALF : V_HUDTRANS); + + V_DrawLevelTitle(lvlttlx1 - w2, (BASEVIDHEIGHT-16)>>1, flags, first); + V_DrawLevelTitle(lvlttlx2 + w1 + 16 - w2, (BASEVIDHEIGHT-16)>>1, flags, "OVER"); + } } if (G_GametypeHasTeams()) From f6d2b5109b8a16f91b21fd0dcf9c169a825321d2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 3 Sep 2019 02:12:17 -0300 Subject: [PATCH 044/133] PRBoom sky dome --- src/hardware/hw_drv.h | 2 + src/hardware/hw_main.c | 182 +++++++++++++---------- src/hardware/hw_main.h | 1 + src/hardware/r_opengl/r_opengl.c | 243 +++++++++++++++++++++++++++++++ src/r_main.c | 1 + src/sdl/hwsym_sdl.c | 1 + src/sdl/i_video.c | 1 + src/v_video.c | 1 + src/win32/win_dll.c | 2 + 9 files changed, 361 insertions(+), 73 deletions(-) diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index e2fa90eb0..e0507bc70 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -47,6 +47,7 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal, RGBA_t *pgamma); EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl); EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color); EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags); +EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform); EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); @@ -89,6 +90,7 @@ struct hwdriver_s FinishUpdate pfnFinishUpdate; Draw2DLine pfnDraw2DLine; DrawPolygon pfnDrawPolygon; + RenderSkyDome pfnRenderSkyDome; SetBlend pfnSetBlend; ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c600800fd..b326786f8 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5805,86 +5805,122 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) // ========================================================================== // // ========================================================================== -static void HWR_DrawSkyBackground(void) +static void HWR_DrawSkyBackground(player_t *player) { - FOutVector v[4]; - angle_t angle; - float dimensionmultiply; - float aspectratio; - float angleturn; - - HWR_GetTexture(texturetranslation[skytexture]); - aspectratio = (float)vid.width/(float)vid.height; - - //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 - // because it's called just after clearing the screen - // and thus, the near clipping plane is set to 3.99 - // Sryder: Just use the near clipping plane value then - - // 3--2 - // | /| - // |/ | - // 0--1 - v[0].x = v[3].x = -ZCLIP_PLANE-1; - v[1].x = v[2].x = ZCLIP_PLANE+1; - v[0].y = v[1].y = -ZCLIP_PLANE-1; - v[2].y = v[3].y = ZCLIP_PLANE+1; - - v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1; - - // X - - // NOTE: This doesn't work right with texture widths greater than 1024 - // software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly - // The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture - - angle = (dup_viewangle + gr_xtoviewangle[0]); - - dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); - - v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left - v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f) - // use +angle and -1.0f above instead if you wanted old backwards behavior - - // Y - angle = aimingangle; - dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio)); - - if (splitscreen) + if (cv_grskydome.value) { - dimensionmultiply *= 2; - angle *= 2; - } + FTransform transform; + const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); + postimg_t *type; - // Middle of the sky should always be at angle 0 - // need to keep correct aspect ratio with X - if (atransform.flip) - { - // During vertical flip the sky should be flipped and it's y movement should also be flipped obviously - v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top - v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f) + if (splitscreen && player == &players[secondarydisplayplayer]) + type = &postimgtype2; + else + type = &postimgtype; + + memset(&transform, 0x00, sizeof(FTransform)); + + //04/01/2000: Hurdler: added for T&L + // It should replace all other gr_viewxxx when finished + transform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + transform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + + if (*type == postimg_flip) + transform.flip = true; + else + transform.flip = false; + + transform.scalex = 1; + transform.scaley = (float)vid.width/vid.height; + transform.scalez = 1; + transform.fovxangle = fpov; // Tails + transform.fovyangle = fpov; // Tails + transform.splitscreen = splitscreen; + + HWR_GetTexture(texturetranslation[skytexture]); + HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, transform); } else { - v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom - v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f) - } + FOutVector v[4]; + angle_t angle; + float dimensionmultiply; + float aspectratio; + float angleturn; - angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; + HWR_GetTexture(texturetranslation[skytexture]); + aspectratio = (float)vid.width/(float)vid.height; - if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa - { - angle = InvAngle(angle); - v[3].tow = v[2].tow += ((float) angle / angleturn); - v[0].tow = v[1].tow += ((float) angle / angleturn); - } - else - { - v[3].tow = v[2].tow -= ((float) angle / angleturn); - v[0].tow = v[1].tow -= ((float) angle / angleturn); - } + //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 + // because it's called just after clearing the screen + // and thus, the near clipping plane is set to 3.99 + // Sryder: Just use the near clipping plane value then - HWD.pfnDrawPolygon(NULL, v, 4, 0); + // 3--2 + // | /| + // |/ | + // 0--1 + v[0].x = v[3].x = -ZCLIP_PLANE-1; + v[1].x = v[2].x = ZCLIP_PLANE+1; + v[0].y = v[1].y = -ZCLIP_PLANE-1; + v[2].y = v[3].y = ZCLIP_PLANE+1; + + v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1; + + // X + + // NOTE: This doesn't work right with texture widths greater than 1024 + // software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly + // The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture + + angle = (dup_viewangle + gr_xtoviewangle[0]); + + dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); + + v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left + v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f) + // use +angle and -1.0f above instead if you wanted old backwards behavior + + // Y + angle = aimingangle; + dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio)); + + if (splitscreen) + { + dimensionmultiply *= 2; + angle *= 2; + } + + // Middle of the sky should always be at angle 0 + // need to keep correct aspect ratio with X + if (atransform.flip) + { + // During vertical flip the sky should be flipped and it's y movement should also be flipped obviously + v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top + v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f) + } + else + { + v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom + v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f) + } + + angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; + + if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa + { + angle = InvAngle(angle); + v[3].tow = v[2].tow += ((float) angle / angleturn); + v[0].tow = v[1].tow += ((float) angle / angleturn); + } + else + { + v[3].tow = v[2].tow -= ((float) angle / angleturn); + v[0].tow = v[1].tow -= ((float) angle / angleturn); + } + + HWD.pfnDrawPolygon(NULL, v, 4, 0); + } } @@ -6036,7 +6072,7 @@ if (0) } if (drawsky) - HWR_DrawSkyBackground(); + HWR_DrawSkyBackground(player); //Hurdler: it doesn't work in splitscreen mode drawsky = splitscreen; @@ -6253,7 +6289,7 @@ if (0) } if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox - HWR_DrawSkyBackground(); + HWR_DrawSkyBackground(player); //Hurdler: it doesn't work in splitscreen mode drawsky = splitscreen; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index f8524990f..31e97cc13 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -98,6 +98,7 @@ extern consvar_t cv_voodoocompatibility; extern consvar_t cv_grfovchange; extern consvar_t cv_grsolvetjoin; extern consvar_t cv_grspritebillboarding; +extern consvar_t cv_grskydome; extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index dfee19857..ae6ff7d09 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1427,6 +1427,249 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, Clamp2D(GL_TEXTURE_WRAP_T); } +// PRBoom sky dome +typedef struct vbo_vertex_s +{ + float x, y, z; + float u, v; + unsigned char r, g, b, a; +} vbo_vertex_t; + +typedef struct +{ + int mode; + int vertexcount; + int vertexindex; + int use_texture; +} GLSkyLoopDef; + +typedef struct +{ + int id; + int rows, columns; + int loopcount; + GLSkyLoopDef *loops; + vbo_vertex_t *data; +} GLSkyVBO; + +// The texture offset to be applied to the texture coordinates in SkyVertex(). +static int rows, columns; +static boolean yflip; +static int texw, texh; +static float yAdd; +static boolean foglayer; +static float delta = 0.0f; +static int gl_sky_detail = 16; +static INT32 lasttex = -1; + +static RGBA_t SkyColor; + +#define MAP_COEFF 128.0f +#define MAP_SCALE (MAP_COEFF*(float)FRACUNIT) + +static void SkyVertex(vbo_vertex_t *vbo, int r, int c) +{ + static fixed_t scale = 10000 << FRACBITS; + static angle_t maxSideAngle = ANGLE_180 / 3; + + angle_t topAngle = (angle_t)(c / (float)columns * ANGLE_MAX); + angle_t sideAngle = maxSideAngle * (rows - r) / rows; + fixed_t height = FINESINE(sideAngle>>ANGLETOFINESHIFT); + fixed_t realRadius = FixedMul(scale, FINECOSINE(sideAngle>>ANGLETOFINESHIFT)); + fixed_t x = FixedMul(realRadius, FINECOSINE(topAngle>>ANGLETOFINESHIFT)); + fixed_t y = (!yflip) ? FixedMul(scale, height) : FixedMul(scale, height) * -1; + fixed_t z = FixedMul(realRadius, FINESINE(topAngle>>ANGLETOFINESHIFT)); + float timesRepeat; + + timesRepeat = (short)(4 * (256.0f / texw)); + if (timesRepeat == 0.0f) + timesRepeat = 1.0f; + + if (!foglayer) + { + vbo->r = 255; + vbo->g = 255; + vbo->b = 255; + vbo->a = (r == 0 ? 0 : 255); + + // And the texture coordinates. + if (!yflip) // Flipped Y is for the lower hemisphere. + { + vbo->u = (-timesRepeat * c / (float)columns); + vbo->v = (r / (float)rows) * 1.f + yAdd; + } + else + { + vbo->u = (-timesRepeat * c / (float)columns); + vbo->v = ((rows-r)/(float)rows) * 1.f + yAdd; + } + + //if (SkyBox.wall.flag == GLDWF_SKYFLIP) + // vbo->u = -vbo->u; + } + + if (r != 4) + y += FRACUNIT * 300; + + // And finally the vertex. + vbo->x = (float)x/(float)MAP_SCALE; + vbo->y = (float)y/(float)MAP_SCALE + delta; + vbo->z = (float)z/(float)MAP_SCALE; +} + +GLSkyVBO sky_vbo; + +static void gld_BuildSky(int row_count, int col_count) +{ + int c, r; + vbo_vertex_t *vertex_p; + int vertex_count = 2 * row_count * (col_count * 2 + 2) + col_count * 2; + + GLSkyVBO *vbo = &sky_vbo; + + if ((vbo->columns != col_count) || (vbo->rows != row_count)) + { + free(vbo->loops); + free(vbo->data); + memset(vbo, 0, sizeof(&vbo)); + } + + if (!vbo->data) + { + memset(vbo, 0, sizeof(&vbo)); + vbo->loops = malloc((row_count * 2 + 2) * sizeof(vbo->loops[0])); + // create vertex array + vbo->data = malloc(vertex_count * sizeof(vbo->data[0])); + } + + vbo->columns = col_count; + vbo->rows = row_count; + + vertex_p = &vbo->data[0]; + vbo->loopcount = 0; + + memset(&SkyColor, 0xFF, sizeof(SkyColor)); + + for (yflip = 0; yflip < 2; yflip++) + { + vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_FAN; + vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0]; + vbo->loops[vbo->loopcount].vertexcount = col_count; + vbo->loops[vbo->loopcount].use_texture = false; + vbo->loopcount++; + + yAdd = 0.5f; + /*if (yflip == 0) + SkyColor = &sky->CeilingSkyColor[vbo_idx]; + else + SkyColor = &sky->FloorSkyColor[vbo_idx];*/ + + delta = 0.0f; + foglayer = true; + for (c = 0; c < col_count; c++) + { + SkyVertex(vertex_p, 1, c); + vertex_p->r = SkyColor.s.red; + vertex_p->g = SkyColor.s.green; + vertex_p->b = SkyColor.s.blue; + vertex_p->a = 255; + vertex_p++; + } + foglayer = false; + + delta = (yflip ? 5.0f : -5.0f) / MAP_COEFF; + + for (r = 0; r < row_count; r++) + { + vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_STRIP; + vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0]; + vbo->loops[vbo->loopcount].vertexcount = 2 * col_count + 2; + vbo->loops[vbo->loopcount].use_texture = true; + vbo->loopcount++; + + for (c = 0; c <= col_count; c++) + { + SkyVertex(vertex_p++, r + (yflip ? 1 : 0), (c ? c : 0)); + SkyVertex(vertex_p++, r + (yflip ? 0 : 1), (c ? c : 0)); + } + } + } +} + +static void RenderDomeForReal(INT32 skytexture) +{ + int i, j; + GLSkyVBO *vbo = &sky_vbo; + + //pglRotatef(-180.0f + sky->x_offset, 0.f, 1.f, 0.f); + pglRotatef(-180.0f, 0.f, 1.f, 0.f); + + rows = 4; + columns = 4 * gl_sky_detail; + + if (lasttex != skytexture) + { + lasttex = skytexture; + gld_BuildSky(rows, columns); + } + + pglScalef(1.0f, (float)texh / 230.0f, 1.0f); + + for (j = 0; j < 2; j++) + { + //gld_EnableTexture2D(GL_TEXTURE0_ARB, j != 0); + for (i = 0; i < vbo->loopcount; i++) + { + GLSkyLoopDef *loop = &vbo->loops[i]; + + if (j == 0 ? loop->use_texture : !loop->use_texture) + continue; + else + { + int k; + pglBegin(loop->mode); + for (k = loop->vertexindex; k < (loop->vertexindex + loop->vertexcount); k++) + { + vbo_vertex_t *v = &vbo->data[k]; + if (loop->use_texture) + pglTexCoord2f(v->u, v->v); + pglColor4f(v->r, v->g, v->b, v->a); + pglVertex3f(v->x, v->y, v->z); + } + pglEnd(); + } + } + } + + pglScalef(1.0f, 1.0f, 1.0f); + + // current color is undefined after glDrawArrays + pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); +} + +EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform) +{ + GLint shading_mode = GL_FLAT; + pglGetIntegerv(GL_SHADE_MODEL, &shading_mode); + pglShadeModel(GL_SMOOTH); + + pglDepthMask(false); + pglDisable(GL_DEPTH_TEST); + pglDisable(GL_ALPHA_TEST); + + SetBlend(PF_Translucent|PF_Clip|PF_NoZClip|PF_NoDepthTest|PF_Modulated); + + texw = texture_width; + texh = texture_height; + SetTransform(&transform); + RenderDomeForReal(tex); + + pglEnable(GL_ALPHA_TEST); + pglEnable(GL_DEPTH_TEST); + pglDepthMask(true); + + pglShadeModel(shading_mode); +} // ========================================================================== // diff --git a/src/r_main.c b/src/r_main.c index db351e991..5135e57ce 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1215,6 +1215,7 @@ void R_RegisterEngineStuff(void) #endif CV_RegisterVar(&cv_grmd2); CV_RegisterVar(&cv_grspritebillboarding); + CV_RegisterVar(&cv_grskydome); #endif #ifdef HWRENDER diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 05ac6450e..103398405 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -79,6 +79,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(Init); GETFUNC(Draw2DLine); GETFUNC(DrawPolygon); + GETFUNC(RenderSkyDome); GETFUNC(SetBlend); GETFUNC(ClearBuffer); GETFUNC(SetTexture); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 5a4fd7a02..b526e6124 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1499,6 +1499,7 @@ void I_StartupGraphics(void) HWD.pfnFinishUpdate = NULL; HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); + HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); HWD.pfnSetBlend = hwSym("SetBlend",NULL); HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); diff --git a/src/v_video.c b/src/v_video.c index 2ec06a787..2dbb21bb3 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -112,6 +112,7 @@ static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NUL // console variables in development consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif // local copy of the palette for V_GetColor() diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index 71eda0437..ce007af25 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -102,6 +102,7 @@ static loadfunc_t hwdFuncTable[] = { {"FinishUpdate@4", &hwdriver.pfnFinishUpdate}, {"Draw2DLine@12", &hwdriver.pfnDraw2DLine}, {"DrawPolygon@16", &hwdriver.pfnDrawPolygon}, + {"RenderSkyDome@16", &hwdriver.pfnRenderDome}, {"SetBlend@4", &hwdriver.pfnSetBlend}, {"ClearBuffer@12", &hwdriver.pfnClearBuffer}, {"SetTexture@4", &hwdriver.pfnSetTexture}, @@ -133,6 +134,7 @@ static loadfunc_t hwdFuncTable[] = { {"FinishUpdate", &hwdriver.pfnFinishUpdate}, {"Draw2DLine", &hwdriver.pfnDraw2DLine}, {"DrawPolygon", &hwdriver.pfnDrawPolygon}, + {"RenderSkyDome", &hwdriver.pfnRenderDome}, {"SetBlend", &hwdriver.pfnSetBlend}, {"ClearBuffer", &hwdriver.pfnClearBuffer}, {"SetTexture", &hwdriver.pfnSetTexture}, From f0b4a609a819d7925e0aaba3f86a57dcb2fb9fd9 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 3 Sep 2019 23:44:04 -0300 Subject: [PATCH 045/133] Very tiny fix --- src/hardware/r_opengl/r_opengl.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index ae6ff7d09..a44556f1d 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1649,26 +1649,15 @@ static void RenderDomeForReal(INT32 skytexture) EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform) { - GLint shading_mode = GL_FLAT; - pglGetIntegerv(GL_SHADE_MODEL, &shading_mode); - pglShadeModel(GL_SMOOTH); - - pglDepthMask(false); - pglDisable(GL_DEPTH_TEST); - pglDisable(GL_ALPHA_TEST); - - SetBlend(PF_Translucent|PF_Clip|PF_NoZClip|PF_NoDepthTest|PF_Modulated); + SetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated); + SetTransform(&transform); texw = texture_width; texh = texture_height; - SetTransform(&transform); RenderDomeForReal(tex); - pglEnable(GL_ALPHA_TEST); - pglEnable(GL_DEPTH_TEST); - pglDepthMask(true); - - pglShadeModel(shading_mode); + // HWR_DrawSkyBackground left no blend flags after rendering the sky + SetBlend(0); } // ========================================================================== From 7177d76cfd64760a6a9e39df10b7f450e6a7f49a Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 4 Sep 2019 15:21:00 +0100 Subject: [PATCH 046/133] Seperate "Game" and "Over" assets, per Sev's request and design. https://cdn.discordapp.com/attachments/428262628893261828/618812279127015475/srb20069.gif --- src/st_stuff.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 0db72efd1..caa91120c 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -66,6 +66,9 @@ patch_t *sboperiod; // Period for time centiseconds patch_t *livesback; // Lives icon background static patch_t *nrec_timer; // Timer for NiGHTS records static patch_t *sborings; +static patch_t *slidgame; +static patch_t *slidtime; +static patch_t *slidover; static patch_t *stlivex; static patch_t *sboredrings; static patch_t *sboredtime; @@ -251,6 +254,10 @@ void ST_LoadGraphics(void) sbocolon = W_CachePatchName("STTCOLON", PU_HUDGFX); // Colon for time sboperiod = W_CachePatchName("STTPERIO", PU_HUDGFX); // Period for time centiseconds + slidgame = W_CachePatchName("SLIDGAME", PU_HUDGFX); + slidtime = W_CachePatchName("SLIDTIME", PU_HUDGFX); + slidover = W_CachePatchName("SLIDOVER", PU_HUDGFX); + stlivex = W_CachePatchName("STLIVEX", PU_HUDGFX); livesback = W_CachePatchName("STLIVEBK", PU_HUDGFX); nrec_timer = W_CachePatchName("NGRTIMER", PU_HUDGFX); // Timer for NiGHTS @@ -2417,7 +2424,7 @@ static void ST_overlayDrawer(void) && (netgame || multiplayer) && (cv_cooplives.value == 0)) ; - else if (G_GametypeUsesLives() && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer))) + else if ((G_GametypeUsesLives() || gametype == GT_RACE) && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer))) { INT32 i = MAXPLAYERS; INT32 deadtimer = stplyr->spectator ? TICRATE : (stplyr->deadtimer-(TICRATE<<1)); @@ -2441,14 +2448,11 @@ static void ST_overlayDrawer(void) if (i == MAXPLAYERS && deadtimer >= 0) { - const char *first = (countdown == 1) ? "TIME" : "GAME"; - const char *second = "OVER"; - INT32 w1 = V_LevelNameWidth(first), w2 = (w1 + 16 + V_LevelNameWidth(second))>>1; - INT32 lvlttlx1 = min(6*deadtimer, BASEVIDWIDTH/2), lvlttlx2 = BASEVIDWIDTH - lvlttlx1; + INT32 lvlttlx = min(6*deadtimer, BASEVIDWIDTH/2); UINT32 flags = V_PERPLAYER|(stplyr->spectator ? V_HUDTRANSHALF : V_HUDTRANS); - V_DrawLevelTitle(lvlttlx1 - w2, (BASEVIDHEIGHT-16)>>1, flags, first); - V_DrawLevelTitle(lvlttlx2 + w1 + 16 - w2, (BASEVIDHEIGHT-16)>>1, flags, "OVER"); + V_DrawScaledPatch(lvlttlx - 8, BASEVIDHEIGHT/2, flags, (countdown == 1 ? slidtime : slidgame)); + V_DrawScaledPatch(BASEVIDWIDTH + 8 - lvlttlx, BASEVIDHEIGHT/2, flags, slidover); } } From 0986195d21ed346a2902b48c3026ca35313558a8 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 4 Sep 2019 15:51:14 +0100 Subject: [PATCH 047/133] Bunch of fixes for dying in MP special stages. * Don't allow the stage to be reloaded in G_DoReborn. * If you do ANY spawn after the very beginning moment, you're forced to be a spectator. * Have the "%d player%s remaining" Co-op exiting count visible at the same time as spectator controls. --- src/g_game.c | 2 +- src/p_mobj.c | 2 +- src/p_user.c | 2 +- src/st_stuff.c | 126 ++++++++++++++++++++++++------------------------- 4 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 1630f085b..1bbf8aa4a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2606,7 +2606,7 @@ void G_DoReborn(INT32 playernum) if (countdowntimeup || (!(netgame || multiplayer) && gametype == GT_COOP)) resetlevel = true; - else if (gametype == GT_COOP && (netgame || multiplayer)) + else if (gametype == GT_COOP && (netgame || multiplayer) && !G_IsSpecialStage(gamemap)) { boolean notgameover = true; diff --git a/src/p_mobj.c b/src/p_mobj.c index abf5de87d..61c021cfb 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10395,7 +10395,7 @@ void P_SpawnPlayer(INT32 playernum) p->spectator = p->outofcoop = (((multiplayer || netgame) && gametype == GT_COOP) // only question status in coop && ((leveltime > 0 - && ((G_IsSpecialStage(gamemap) && (maptol & TOL_NIGHTS)) // late join special stage + && ((G_IsSpecialStage(gamemap)) // late join special stage || (cv_coopstarposts.value == 2 && (p->jointime < 1 || p->outofcoop)))) // late join or die in new coop || (!P_GetLives(p) && p->lives <= 0))); // game over and can't redistribute lives } diff --git a/src/p_user.c b/src/p_user.c index 08579e48d..5da17ee24 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9173,7 +9173,7 @@ static void P_DeathThink(player_t *player) // Force respawn if idle for more than 30 seconds in shooter modes. if (player->deadtimer > 30*TICRATE && !G_PlatformGametype()) player->playerstate = PST_REBORN; - else if ((player->lives > 0 || j != MAXPLAYERS) && !(G_IsSpecialStage(gamemap))) // Don't allow "click to respawn" in special stages! + else if ((player->lives > 0 || j != MAXPLAYERS) && !(!(netgame || multiplayer) && G_IsSpecialStage(gamemap))) // Don't allow "click to respawn" in special stages! { if (gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2) { diff --git a/src/st_stuff.c b/src/st_stuff.c index caa91120c..b59d18143 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2039,7 +2039,68 @@ static void ST_drawTextHUD(void) textHUDdraw(va("Lap:""\x82 %u/%d", stplyr->laps+1, cv_numlaps.value)) } - if (!stplyr->spectator && stplyr->exiting && cv_playersforexit.value && gametype == GT_COOP) + if (gametype != GT_COOP && (stplyr->exiting || (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1))) + { + if (!splitscreen && !donef12) + { + textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) + donef12 = true; + } + } + else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) // Death overrides spectator text. + { + INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE; + + if (respawntime > 0 && !stplyr->spectator) + textHUDdraw(va(M_GetText("Respawn in %d..."), respawntime)) + else + textHUDdraw(M_GetText("\x82""JUMP:""\x80 Respawn")) + } + else if (stplyr->spectator && (gametype != GT_COOP || stplyr->playerstate == PST_LIVE)) + { + if (!splitscreen && !donef12) + { + textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) + donef12 = true; + } + + textHUDdraw(M_GetText("\x82""JUMP:""\x80 Rise")) + textHUDdraw(M_GetText("\x82""SPIN:""\x80 Lower")) + + if (G_IsSpecialStage(gamemap)) + textHUDdraw(M_GetText("\x82""Wait for the stage to end...")) + else if (gametype == GT_COOP) + { + if (stplyr->lives <= 0 + && cv_cooplives.value == 2 + && (netgame || multiplayer)) + { + INT32 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (&players[i] == stplyr) + continue; + + if (players[i].lives > 1) + break; + } + + if (i != MAXPLAYERS) + textHUDdraw(M_GetText("You'll steal a life on respawn...")) + else + textHUDdraw(M_GetText("Wait to respawn...")) + } + else + textHUDdraw(M_GetText("Wait to respawn...")) + } + else + textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) + } + + if (gametype == GT_COOP && (!stplyr->spectator || (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))) && stplyr->exiting && cv_playersforexit.value) { INT32 i, total = 0, exiting = 0; @@ -2074,68 +2135,7 @@ static void ST_drawTextHUD(void) textHUDdraw(va(M_GetText("%d player%s remaining"), total, ((total == 1) ? "" : "s"))) } } - else if (gametype != GT_COOP && (stplyr->exiting || (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1))) - { - if (!splitscreen && !donef12) - { - textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) - donef12 = true; - } - } - else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text. - { - INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE; - - if (respawntime > 0 && !stplyr->spectator) - textHUDdraw(va(M_GetText("Respawn in %d..."), respawntime)) - else - textHUDdraw(M_GetText("\x82""JUMP:""\x80 Respawn")) - } - else if (stplyr->spectator && (gametype != GT_COOP || stplyr->playerstate == PST_LIVE)) - { - if (!splitscreen && !donef12) - { - textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) - donef12 = true; - } - - textHUDdraw(M_GetText("\x82""JUMP:""\x80 Rise")) - textHUDdraw(M_GetText("\x82""SPIN:""\x80 Lower")) - - if (G_IsSpecialStage(gamemap) && (maptol & TOL_NIGHTS)) - textHUDdraw(M_GetText("\x82""Wait for the stage to end...")) - else if (gametype == GT_COOP) - { - if (stplyr->lives <= 0 - && cv_cooplives.value == 2 - && (netgame || multiplayer)) - { - INT32 i; - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - if (&players[i] == stplyr) - continue; - - if (players[i].lives > 1) - break; - } - - if (i != MAXPLAYERS) - textHUDdraw(M_GetText("You'll steal a life on respawn...")) - else - textHUDdraw(M_GetText("Wait to respawn...")) - } - else - textHUDdraw(M_GetText("Wait to respawn...")) - } - else - textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) - } - - if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator)) + else if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator)) { if (leveltime < hidetime * TICRATE) { From 5bc034bc3e1c4117838f9bf44d860501ff231561 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 4 Sep 2019 15:52:25 +0100 Subject: [PATCH 048/133] [slightly off-topic commit] don't allow MP Special Stages to be selectable via the MP level platter --- src/m_menu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index 128b15a76..cb1fa03d7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4510,6 +4510,9 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) return false; + if (G_IsSpecialStage(mapnum+1)) + return false; + if (gt == GT_COOP && (mapheaderinfo[mapnum]->typeoflevel & TOL_COOP)) return true; From c6f3e4d53dd3bbd9b330e9930bf3a1f572d8d327 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 4 Sep 2019 13:59:09 -0300 Subject: [PATCH 049/133] Make sky dome look a bit better --- src/hardware/r_opengl/r_opengl.c | 33 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index a44556f1d..5b2dffc1a 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1456,7 +1456,7 @@ typedef struct static int rows, columns; static boolean yflip; static int texw, texh; -static float yAdd; +static float yMult, yAdd; static boolean foglayer; static float delta = 0.0f; static int gl_sky_detail = 16; @@ -1487,30 +1487,24 @@ static void SkyVertex(vbo_vertex_t *vbo, int r, int c) if (!foglayer) { + boolean flip = yflip; vbo->r = 255; vbo->g = 255; vbo->b = 255; vbo->a = (r == 0 ? 0 : 255); + // Flip Y coordinate anyway for the top part of the hemisphere + if (r <= 1) + flip = !flip; + // And the texture coordinates. - if (!yflip) // Flipped Y is for the lower hemisphere. - { - vbo->u = (-timesRepeat * c / (float)columns); - vbo->v = (r / (float)rows) * 1.f + yAdd; - } + vbo->u = (-timesRepeat * c / (float)columns); + if (!flip) // Flipped Y is for the lower hemisphere. + vbo->v = (r / (float)rows) * 1.f * yMult + yAdd; else - { - vbo->u = (-timesRepeat * c / (float)columns); - vbo->v = ((rows-r)/(float)rows) * 1.f + yAdd; - } - - //if (SkyBox.wall.flag == GLDWF_SKYFLIP) - // vbo->u = -vbo->u; + vbo->v = ((rows-r)/(float)rows) * 1.f * yMult + yAdd; } - if (r != 4) - y += FRACUNIT * 300; - // And finally the vertex. vbo->x = (float)x/(float)MAP_SCALE; vbo->y = (float)y/(float)MAP_SCALE + delta; @@ -1550,7 +1544,8 @@ static void gld_BuildSky(int row_count, int col_count) memset(&SkyColor, 0xFF, sizeof(SkyColor)); - for (yflip = 0; yflip < 2; yflip++) + // Why not? + for (yflip = false; yflip <= true; yflip++) { vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_FAN; vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0]; @@ -1559,6 +1554,7 @@ static void gld_BuildSky(int row_count, int col_count) vbo->loopcount++; yAdd = 0.5f; + yMult = 1.0f; /*if (yflip == 0) SkyColor = &sky->CeilingSkyColor[vbo_idx]; else @@ -1584,7 +1580,7 @@ static void gld_BuildSky(int row_count, int col_count) vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_STRIP; vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0]; vbo->loops[vbo->loopcount].vertexcount = 2 * col_count + 2; - vbo->loops[vbo->loopcount].use_texture = true; + vbo->loops[vbo->loopcount].use_texture = true; //(r > 1) ? true : false; vbo->loopcount++; for (c = 0; c <= col_count; c++) @@ -1617,7 +1613,6 @@ static void RenderDomeForReal(INT32 skytexture) for (j = 0; j < 2; j++) { - //gld_EnableTexture2D(GL_TEXTURE0_ARB, j != 0); for (i = 0; i < vbo->loopcount; i++) { GLSkyLoopDef *loop = &vbo->loops[i]; From 6aedca899f7410633050462b841dd9b2c96dc176 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 5 Sep 2019 17:42:36 -0300 Subject: [PATCH 050/133] 2.2 skies aren't flipped --- src/hardware/r_opengl/r_opengl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 5b2dffc1a..2fe6741e2 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1597,8 +1597,7 @@ static void RenderDomeForReal(INT32 skytexture) int i, j; GLSkyVBO *vbo = &sky_vbo; - //pglRotatef(-180.0f + sky->x_offset, 0.f, 1.f, 0.f); - pglRotatef(-180.0f, 0.f, 1.f, 0.f); + pglRotatef(270.f, 0.f, 1.f, 0.f); rows = 4; columns = 4 * gl_sky_detail; From bb2012a8d046702e445962b5f299c2e0c7102bcb Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 6 Sep 2019 19:01:46 +0100 Subject: [PATCH 051/133] Clean up an ungodly amount of shit relating to abilities. * Put everything in P_DoJumpStuff, instead of half in that function and half spread across the player thinker. * Have a proper if else cascade that first tries shield abilities, then super transformation, then random abilities like CA_TELEKINESIS. * Use this new arrangement to allow CA_TWINSPIN users to use their ability on spin if their secondary ability is CA2_MELEE (resolves #195). * Random bugfixing. Didn't keep track of what I'd caused while working on this and what was already there, but there was a lot of it. The only two abilities which have spin-button properties outside of the else block is CA_AIRDRILL and CA_FLY/CA_SWIM (which now also prevents you from swimming down in goowater). --- src/p_inter.c | 1 + src/p_mobj.c | 2 +- src/p_user.c | 432 ++++++++++++++++++++++++++------------------------ 3 files changed, 228 insertions(+), 207 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 0030e8e58..d3cfe1567 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1583,6 +1583,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Buenos Dias Mandy P_SetPlayerMobjState(toucher, S_PLAY_STUN); player->pflags &= ~PF_APPLYAUTOBRAKE; + P_ResetPlayer(player); player->drawangle = special->angle + ANGLE_180; P_InstaThrust(toucher, special->angle, FixedMul(3*special->info->speed, special->scale/2)); toucher->z += P_MobjFlip(toucher); diff --git a/src/p_mobj.c b/src/p_mobj.c index 1ee90d250..64df86813 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2954,7 +2954,7 @@ static void P_PlayerZMovement(mobj_t *mo) } // Get up if you fell. if (mo->player->panim == PA_PAIN) - P_SetPlayerMobjState(mo, S_PLAY_STND); + P_SetPlayerMobjState(mo, S_PLAY_WALK); #ifdef ESLOPE if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) { diff --git a/src/p_user.c b/src/p_user.c index a69bd5b93..0550c7f69 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4886,56 +4886,185 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) // static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { - mobj_t *lockon = NULL; + mobj_t *lockonthok = NULL, *lockonshield = NULL, *visual = NULL; if (player->pflags & PF_JUMPSTASIS) return; - if ((player->charability == CA_HOMINGTHOK) && !player->homing && (player->pflags & PF_JUMPED) && (!(player->pflags & PF_THOKKED) || (player->charflags & SF_MULTIABILITY)) && (lockon = P_LookForEnemies(player, true, false))) + if ((player->charability == CA_HOMINGTHOK) && !player->homing && (player->pflags & PF_JUMPED) && (!(player->pflags & PF_THOKKED) || (player->charflags & SF_MULTIABILITY)) && (lockonthok = P_LookForEnemies(player, true, false))) { if (P_IsLocalPlayer(player)) // Only display it on your own view. { - mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - P_SetTarget(&visual->target, lockon); + visual = P_SpawnMobj(lockonthok->x, lockonthok->y, lockonthok->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + P_SetTarget(&visual->target, lockonthok); } } - if (cmd->buttons & BT_USE && !(player->pflags & PF_JUMPDOWN) && !player->exiting && !P_PlayerInPain(player)) + ////////////////// + //SHIELD ACTIVES// + //& SUPER FLOAT!// + ////////////////// + + if ((player->pflags & PF_JUMPED) && !player->exiting && !P_PlayerInPain(player)) { - if (player->mo->tracer && player->powers[pw_carry] == CR_MACESPIN) - {} - else if (onground || player->climbing || (player->mo->tracer && player->powers[pw_carry])) - {} - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND - && !(player->pflags & PF_JUMPED) - && !(player->pflags & PF_USEDOWN)) - P_DoJumpShield(player); - else if (!(player->pflags & PF_SLIDING) && ((gametype != GT_CTF) || (!player->gotflag))) + if (onground || player->climbing || player->powers[pw_carry]) + ; + else if (gametype == GT_CTF && player->gotflag) + ; + else if (player->pflags & (PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player has used an ability previously + ; + else if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_USEDOWN) + && ((!(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX)))) // thokked is optional if you're bubblewrapped { + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) + { + if ((lockonshield = P_LookForEnemies(player, false, false))) + { + if (P_IsLocalPlayer(player)) // Only display it on your own view. + { + boolean dovis = true; + if (lockonshield == lockonthok) + { + if (leveltime & 2) + dovis = false; + else if (visual) + P_RemoveMobj(visual); + } + if (dovis) + { + visual = P_SpawnMobj(lockonshield->x, lockonshield->y, lockonshield->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + P_SetTarget(&visual->target, lockonshield); + P_SetMobjStateNF(visual, visual->info->spawnstate+1); + } + } + } + } + if (cmd->buttons & BT_USE // Spin button effects + #ifdef HAVE_BLUA + && !LUAh_ShieldSpecial(player) + #endif + ) + { + // Force stop + if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) + { + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->mo->momx = player->mo->momy = player->mo->momz = 0; + S_StartSound(player->mo, sfx_ngskid); + } + else + { + switch (player->powers[pw_shield] & SH_NOSTACK) + { + // Whirlwind jump/Thunder jump + case SH_WHIRLWIND: + case SH_THUNDERCOIN: + P_DoJumpShield(player); + break; + // Armageddon pow + case SH_ARMAGEDDON: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + P_BlackOw(player); + break; + // Attraction blast + case SH_ATTRACT: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->homing = 2; + P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockonshield)); + if (lockonshield) + { + player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockonshield->x, lockonshield->y); + player->pflags &= ~PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_s3k40); + player->homing = 3*TICRATE; + } + else + S_StartSound(player->mo, sfx_s3ka6); + break; + // Elemental stomp/Bubble bounce + case SH_ELEMENTAL: + case SH_BUBBLEWRAP: + { + boolean elem = ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL); + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + if (elem) + { + player->pflags |= PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + S_StartSound(player->mo, sfx_s3k43); + } + else + { + player->pflags &= ~PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_s3k44); + } + player->secondjump = 0; + player->mo->momx = player->mo->momy = 0; + P_SetObjectMomZ(player->mo, -24*FRACUNIT, false); + break; + } + // Flame burst + case SH_FLAMEAURA: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); + player->drawangle = player->mo->angle; + S_StartSound(player->mo, sfx_s3k43); + default: + break; + } + } + } + } + else if ((cmd->buttons & BT_USE)) + { + if (!(player->pflags & PF_USEDOWN) && P_SuperReady(player)) + { + // If you can turn super and aren't already, + // and you don't have a shield, do it! + P_DoSuperTransformation(player, false); + } + else #ifdef HAVE_BLUA if (!LUAh_JumpSpinSpecial(player)) #endif switch (player->charability) { - case CA_TELEKINESIS: - if (player->pflags & PF_JUMPED) + case CA_THOK: + if (player->powers[pw_super]) // Super Sonic float { - if (!(player->pflags & PF_THOKKED) || (player->charflags & SF_MULTIABILITY)) + if ((player->speed > 5*player->mo->scale) // FixedMul(5<mo->scale), but scale is FRACUNIT-based + && (P_MobjFlip(player->mo)*player->mo->momz <= 0)) { - P_Telekinesis(player, - -FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player) - FixedMul(384*FRACUNIT, player->mo->scale)); + if (player->panim != PA_RUN && player->panim != PA_WALK) + { + if (player->speed >= FixedMul(player->runspeed, player->mo->scale)) + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT_RUN); + else + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT); + } + + player->mo->momz = 0; + player->pflags &= ~(PF_STARTJUMP|PF_SPINNING); } } break; - case CA_AIRDRILL: - if (player->pflags & PF_JUMPED) + case CA_TELEKINESIS: + if (!(player->pflags & (PF_THOKKED|PF_USEDOWN)) || (player->charflags & SF_MULTIABILITY)) { - if (player->pflags & PF_THOKKED) // speed up falling down - { - if (player->secondjump < 42) - player->secondjump ++; - } + P_Telekinesis(player, + -FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player) + FixedMul(384*FRACUNIT, player->mo->scale)); + } + break; + case CA_TWINSPIN: + if ((player->charability2 == CA2_MELEE) && (!(player->pflags & (PF_THOKKED|PF_USEDOWN)) || player->charflags & SF_MULTIABILITY)) + { + player->pflags |= PF_THOKKED; + S_StartSound(player->mo, sfx_s3k42); + player->mo->frame = 0; + P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN); } break; default: @@ -4948,6 +5077,9 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { if (player->pflags & PF_JUMPED) { + if (cmd->buttons & BT_USE && player->secondjump < 42) // speed up falling down + player->secondjump++; + if (player->flyangle > 0 && player->pflags & PF_THOKKED) { player->flyangle--; @@ -4966,6 +5098,11 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } } + /////////////// + // CHARACTER // + // ABILITIES!// + /////////////// + if (cmd->buttons & BT_JUMP && !player->exiting && !P_PlayerInPain(player)) { #ifdef HAVE_BLUA @@ -5035,7 +5172,6 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } P_InstaThrust(player->mo, player->mo->angle, FixedMul(actionspd, player->mo->scale)); - player->drawangle = player->mo->angle; if (maptol & TOL_2D) { @@ -5050,11 +5186,11 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if (player->charability == CA_HOMINGTHOK) { - P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon)); - if (lockon) + P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockonthok)); + if (lockonthok) { P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockon->x, lockon->y); + player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockonthok->x, lockonthok->y); player->homing = 3*TICRATE; } else @@ -5066,6 +5202,8 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->pflags &= ~PF_NOJUMPDAMAGE; } + player->drawangle = player->mo->angle; + if (player->mo->info->attacksound && !player->spectator) S_StartSound(player->mo, player->mo->info->attacksound); // Play the THOK sound @@ -5212,6 +5350,60 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) P_DoJumpShield(player); } + // HOMING option. + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT // Sonic 3D Blast. + && player->pflags & PF_SHIELDABILITY) + { + if (player->homing && player->mo->tracer) + { + if (!P_HomingAttack(player->mo, player->mo->tracer)) + { + P_SetObjectMomZ(player->mo, 6*FRACUNIT, false); + if (player->mo->eflags & MFE_UNDERWATER) + player->mo->momz = FixedMul(player->mo->momz, FRACUNIT/3); + player->homing = 0; + } + } + + // If you're not jumping, then you obviously wouldn't be homing. + if (!(player->pflags & PF_JUMPED)) + player->homing = 0; + } + else if (player->charability == CA_HOMINGTHOK) // Sonic Adventure. + { + // If you've got a target, chase after it! + if (player->homing && player->mo->tracer) + { + P_SpawnThokMobj(player); + + // But if you don't, then stop homing. + if (!P_HomingAttack(player->mo, player->mo->tracer)) + { + if (player->mo->eflags & MFE_UNDERWATER) + P_SetObjectMomZ(player->mo, FixedDiv(457*FRACUNIT,72*FRACUNIT), false); + else + P_SetObjectMomZ(player->mo, 10*FRACUNIT, false); + + player->mo->momx = player->mo->momy = player->homing = 0; + + if (player->mo->tracer->flags2 & MF2_FRET) + P_InstaThrust(player->mo, player->mo->angle, -(player->speed>>3)); + + if (!(player->mo->tracer->flags & MF_BOSS)) + player->pflags &= ~PF_THOKKED; + + P_SetPlayerMobjState(player->mo, S_PLAY_SPRING); + player->pflags |= PF_NOJUMPDAMAGE; + } + } + + // If you're not jumping, then you obviously wouldn't be homing. + if (!(player->pflags & PF_JUMPED)) + player->homing = 0; + } + else + player->homing = 0; + if (cmd->buttons & BT_JUMP) { player->pflags |= PF_JUMPDOWN; @@ -5238,7 +5430,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->pflags &= ~PF_JUMPDOWN; // Repeat abilities, but not double jump! - if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP) + if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP && player->charability != CA_AIRDRILL) { if (player->charflags & SF_MULTIABILITY) { @@ -8000,7 +8192,7 @@ static void P_MovePlayer(player_t *player) S_StartSound(player->mo, sfx_putput); // Descend - if (cmd->buttons & BT_USE && !(player->pflags & PF_STASIS) && !player->exiting) + if (cmd->buttons & BT_USE && !(player->pflags & PF_STASIS) && !player->exiting && !(player->mo->eflags & MFE_GOOWATER)) if (P_MobjFlip(player->mo)*player->mo->momz > -FixedMul(5*actionspd, player->mo->scale)) P_SetObjectMomZ(player->mo, -actionspd/2, true); @@ -8117,178 +8309,6 @@ static void P_MovePlayer(player_t *player) localangle2 = player->mo->angle; } - ////////////////// - //SHIELD ACTIVES// - //& SUPER FLOAT!// - ////////////////// - - if (player->pflags & PF_JUMPED && !player->exiting && player->mo->health) - { - mobj_t *lockon = NULL; - if (!player->powers[pw_super] && player->powers[pw_shield] == SH_ATTRACT && !(player->pflags & PF_THOKKED)) - { - if ((lockon = P_LookForEnemies(player, false, false))) - { - if (P_IsLocalPlayer(player)) // Only display it on your own view. - { - mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - P_SetTarget(&visual->target, lockon); - P_SetMobjStateNF(visual, visual->info->spawnstate+1); - } - } - } - if (cmd->buttons & BT_USE) // Spin button effects - { - if (player->powers[pw_super]) // Super can't use shield actives, only passives - { - if ((player->charability == CA_THOK) // Super Sonic float - && (player->speed > 5*player->mo->scale) // FixedMul(5<mo->scale), but scale is FRACUNIT-based - && (P_MobjFlip(player->mo)*player->mo->momz <= 0)) - { - if (player->panim != PA_RUN && player->panim != PA_WALK) - { - if (player->speed >= FixedMul(player->runspeed, player->mo->scale)) - P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT_RUN); - else - P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT); - } - - player->mo->momz = 0; - player->pflags &= ~(PF_STARTJUMP|PF_SPINNING); - } - } - else -#ifdef HAVE_BLUA - if (!LUAh_ShieldSpecial(player)) -#endif - { - if (!(player->pflags & (PF_USEDOWN|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player is not holding down BT_USE, or having used an ability previously - && (!(player->powers[pw_shield] & SH_NOSTACK) || !(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped/turning super - { - // Force stop - if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) - { - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - player->mo->momx = player->mo->momy = player->mo->momz = 0; - S_StartSound(player->mo, sfx_ngskid); - } - else - { - switch (player->powers[pw_shield] & SH_NOSTACK) - { - // Super! - case SH_NONE: - if (P_SuperReady(player)) - P_DoSuperTransformation(player, false); - break; - // Whirlwind jump/Thunder jump - case SH_WHIRLWIND: - case SH_THUNDERCOIN: - P_DoJumpShield(player); - break; - // Armageddon pow - case SH_ARMAGEDDON: - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - P_BlackOw(player); - break; - // Attraction blast - case SH_ATTRACT: - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - player->homing = 2; - P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon)); - if (lockon) - { - player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockon->x, lockon->y); - player->pflags &= ~PF_NOJUMPDAMAGE; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_s3k40); - player->homing = 3*TICRATE; - } - else - S_StartSound(player->mo, sfx_s3ka6); - break; - // Elemental stomp/Bubble bounce - case SH_ELEMENTAL: - case SH_BUBBLEWRAP: - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - player->pflags &= ~PF_NOJUMPDAMAGE; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - player->secondjump = 0; - player->mo->momx = player->mo->momy = 0; - P_SetObjectMomZ(player->mo, -24*FRACUNIT, false); - S_StartSound(player->mo, - ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) - ? sfx_s3k43 - : sfx_s3k44); - break; - // Flame burst - case SH_FLAMEAURA: - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); - player->drawangle = player->mo->angle; - S_StartSound(player->mo, sfx_s3k43); - default: - break; - } - } - } - } - } - } - - // HOMING option. - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT // Sonic 3D Blast. - && player->pflags & PF_SHIELDABILITY) - { - if (player->homing && player->mo->tracer) - { - if (!P_HomingAttack(player->mo, player->mo->tracer)) - { - P_SetObjectMomZ(player->mo, 6*FRACUNIT, false); - if (player->mo->eflags & MFE_UNDERWATER) - player->mo->momz = FixedMul(player->mo->momz, FRACUNIT/3); - player->homing = 0; - } - } - - // If you're not jumping, then you obviously wouldn't be homing. - if (!(player->pflags & PF_JUMPED)) - player->homing = 0; - } - else if (player->charability == CA_HOMINGTHOK) // Sonic Adventure. - { - // If you've got a target, chase after it! - if (player->homing && player->mo->tracer) - { - P_SpawnThokMobj(player); - - // But if you don't, then stop homing. - if (!P_HomingAttack(player->mo, player->mo->tracer)) - { - if (player->mo->eflags & MFE_UNDERWATER) - P_SetObjectMomZ(player->mo, FixedDiv(457*FRACUNIT,72*FRACUNIT), false); - else - P_SetObjectMomZ(player->mo, 10*FRACUNIT, false); - - player->mo->momx = player->mo->momy = player->homing = 0; - - if (player->mo->tracer->flags2 & MF2_FRET) - P_InstaThrust(player->mo, player->mo->angle, -(player->speed>>3)); - - if (!(player->mo->tracer->flags & MF_BOSS)) - player->pflags &= ~PF_THOKKED; - - // P_SetPlayerMobjState(player->mo, S_PLAY_SPRING); -- Speed didn't like it, RIP - } - } - - // If you're not jumping, then you obviously wouldn't be homing. - if (!(player->pflags & PF_JUMPED)) - player->homing = 0; - } - else - player->homing = 0; - if (player->climbing == 1) P_DoClimbing(player); @@ -8332,7 +8352,7 @@ static void P_MovePlayer(player_t *player) // Less height while spinning. Good for spinning under things...? if ((player->mo->state == &states[player->mo->info->painstate]) - || ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE && player->charflags & SF_NOJUMPSPIN)) + || ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE)) || (player->pflags & PF_SPINNING) || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) From 2a85ed0bdd2a9505a03d41d04871af51d6de340b Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 6 Sep 2019 19:26:05 -0300 Subject: [PATCH 052/133] test --- src/hardware/hw_main.c | 4 ++-- src/r_plane.c | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 62e77ae77..0df79c415 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3700,7 +3700,7 @@ static void HWR_Subsector(size_t num) HWR_GetTextureFlat(levelflats[*rover->bottompic].texturenum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, levelflats[*rover->bottompic].texturenum, - rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); + rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -3766,7 +3766,7 @@ static void HWR_Subsector(size_t num) HWR_GetTextureFlat(levelflats[*rover->toppic].texturenum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, levelflats[*rover->toppic].texturenum, - rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); + rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } } diff --git a/src/r_plane.c b/src/r_plane.c index 645405b53..57c8079f1 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -1010,8 +1010,6 @@ void R_DrawSinglePlane(visplane_t *pl) if (ds_powersoftwo) { - - } if (hack) { /* From 02a7d8e0a2ec70f71e0a0ac5fd22c4faeece433a Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 6 Sep 2019 19:37:07 -0300 Subject: [PATCH 053/133] Fix tilted spans. --- src/r_draw8.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/r_draw8.c b/src/r_draw8.c index 1c4527a8e..77406f83c 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -726,8 +726,8 @@ void R_DrawTiltedSpan_8(void) if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -780,8 +780,8 @@ void R_DrawTiltedSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -813,8 +813,8 @@ void R_DrawTiltedSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -851,8 +851,8 @@ void R_DrawTiltedSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -929,8 +929,8 @@ void R_DrawTiltedTranslucentSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -983,8 +983,8 @@ void R_DrawTiltedTranslucentSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1016,8 +1016,8 @@ void R_DrawTiltedTranslucentSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1054,8 +1054,8 @@ void R_DrawTiltedTranslucentSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1132,8 +1132,8 @@ void R_DrawTiltedSplat_8(void) if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1190,8 +1190,8 @@ void R_DrawTiltedSplat_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1225,8 +1225,8 @@ void R_DrawTiltedSplat_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1266,8 +1266,8 @@ void R_DrawTiltedSplat_8(void) val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (!ds_powersoftwo) { - fixed_t x = ((u-viewx) >> FRACBITS); - fixed_t y = ((v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) From d38ba4d88ca9d00b254e4728dd997454994c6847 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 6 Sep 2019 19:41:29 -0300 Subject: [PATCH 054/133] define stuff idk --- src/hardware/hw_cache.c | 4 ++++ src/r_data.c | 7 +++++++ src/r_plane.c | 8 +++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 12e43c0e5..2b458c9d9 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -664,8 +664,10 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) { size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); +#ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); +#endif HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, @@ -892,8 +894,10 @@ static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC); size_t lumplength = W_LumpLength(flatlumpnum); +#ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)patch, lumplength)) patch = R_PNGToPatch((UINT8 *)patch, lumplength); +#endif grMipmap->width = (UINT16)SHORT(patch->width); grMipmap->height = (UINT16)SHORT(patch->height); diff --git a/src/r_data.c b/src/r_data.c index d37b39315..8c6b4926a 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -376,8 +376,10 @@ static UINT8 *R_GenerateTexture(size_t texnum) lumpnum = patch->lump; lumplength = W_LumpLengthPwad(wadnum, lumpnum); realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); +#ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); +#endif // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) @@ -468,8 +470,10 @@ static UINT8 *R_GenerateTexture(size_t texnum) lumpnum = patch->lump; lumplength = W_LumpLengthPwad(wadnum, lumpnum); realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); +#ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); +#endif x1 = patch->originx; width = SHORT(realpatch->width); @@ -734,6 +738,8 @@ void R_LoadTextures(void) // Set texture properties. M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + +#ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)patchlump, lumplength)) { INT16 width, height; @@ -742,6 +748,7 @@ void R_LoadTextures(void) texture->height = height; } else +#endif { texture->width = SHORT(patchlump->width); texture->height = SHORT(patchlump->height); diff --git a/src/r_plane.c b/src/r_plane.c index 57c8079f1..92b3fe770 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -963,12 +963,14 @@ void R_DrawSinglePlane(visplane_t *pl) // Check if the flat is actually a wall texture. if (levelflat->texturenum != 0 && levelflat->texturenum != -1) flat = R_GetPatchFlat(levelflat, true, false); - // Maybe it's just a patch, then? - else if (R_CheckIfPatch(levelflat->lumpnum)) - flat = R_GetPatchFlat(levelflat, false, false); +#ifndef NO_PNG_LUMPS // Maybe it's a PNG?! else if (R_IsLumpPNG(ds_source, size)) flat = R_GetPatchFlat(levelflat, false, true); +#endif + // Maybe it's just a patch, then? + else if (R_CheckIfPatch(levelflat->lumpnum)) + flat = R_GetPatchFlat(levelflat, false, false); // It's a raw flat. else { From 99b4439b2ab2715d1ead8f28c5602de466a3f7a2 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 7 Sep 2019 11:33:26 +0100 Subject: [PATCH 055/133] * Allow CA2_GUNSLINGER users to pop monitors with their ability (as long as their weapon type isn't a pre-existing weapon ring). * Correct the position of a carried player relative to Tails. --- src/p_inter.c | 3 ++- src/p_user.c | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index d3cfe1567..13277d425 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3419,7 +3419,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; // Make sure that boxes cannot be popped by enemies, red rings, etc. - if (target->flags & MF_MONITOR && ((!source || !source->player || source->player->bot) || (inflictor && !inflictor->player))) + if (target->flags & MF_MONITOR && ((!source || !source->player || source->player->bot) + || (inflictor && inflictor->type >= MT_REDRING && inflictor->type <= MT_GRENADERING))) return false; } diff --git a/src/p_user.c b/src/p_user.c index 0550c7f69..79866adec 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8863,7 +8863,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) // Looks for something you can hit - Used for homing attack // If nonenemies is true, includes monitors and springs! // If bullet is true, you can look up and the distance is further, -// but your total angle span you can look is limited to compensate. +// but your total angle span you can look is limited to compensate. (Also, allows monitors.) // mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) { @@ -8873,6 +8873,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) const fixed_t maxdist = FixedMul((bullet ? RING_DIST*2 : RING_DIST), player->mo->scale); const angle_t span = (bullet ? ANG30 : ANGLE_90); fixed_t dist, closestdist = 0; + const mobjflag_t nonenemiesdisregard = (bullet ? 0 : MF_MONITOR)|MF_SPRING; for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { @@ -8892,7 +8893,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) if (mo->flags2 & MF2_FRET) continue; - if (!nonenemies && mo->flags & (MF_MONITOR|MF_SPRING)) + if (!nonenemies && mo->flags & nonenemiesdisregard) continue; if (!bullet && mo->type == MT_DETON) // Don't be STUPID, Sonic! @@ -11772,7 +11773,7 @@ void P_PlayerAfterThink(player_t *player) { if ((tails->z + tails->height + player->mo->height + FixedMul(FRACUNIT, player->mo->scale)) <= tails->ceilingz && (tails->eflags & MFE_VERTICALFLIP)) // Reverse gravity check for the carrier - Flame - player->mo->z = tails->z + tails->height + FixedMul(FRACUNIT, player->mo->scale); + player->mo->z = tails->z + tails->height + 12*player->mo->scale; else player->powers[pw_carry] = CR_NONE; } @@ -11780,7 +11781,7 @@ void P_PlayerAfterThink(player_t *player) { if ((tails->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale)) >= tails->floorz && !(tails->eflags & MFE_VERTICALFLIP)) // Correct gravity check for the carrier - Flame - player->mo->z = tails->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale); + player->mo->z = tails->z - player->mo->height - 12*player->mo->scale; else player->powers[pw_carry] = CR_NONE; } @@ -11789,7 +11790,7 @@ void P_PlayerAfterThink(player_t *player) player->powers[pw_carry] = CR_NONE; else { - P_TryMove(player->mo, tails->x, tails->y, true); + P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true); player->mo->momx = tails->momx; player->mo->momy = tails->momy; player->mo->momz = tails->momz; From 5640aa955ab079aed717a56290e7488604da5a84 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 7 Sep 2019 12:07:29 +0100 Subject: [PATCH 056/133] Fix the V_DrawCroppedPatch bleeding on the current charsel screen. --- src/v_video.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 2ec06a787..edea7e051 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1045,9 +1045,15 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ prevdelta = topdelta; source = (const UINT8 *)(column) + 3; dest = desttop; - dest += FixedInt(FixedMul(topdelta< 0) + { + dest += FixedInt(FixedMul((topdelta-sy)<>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) + for (; dest < deststop && (ofs>>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) { if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); From 5d85e82fa66ea58c939b7c048d05174819d03c97 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 7 Sep 2019 20:08:05 +0100 Subject: [PATCH 057/133] Fix detection of GRADE_ constants in SOC. --- src/dehacked.c | 61 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 5db61a5b5..186d36fb2 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2957,6 +2957,17 @@ static void readunlockable(MYFILE *f, INT32 num) Z_Free(s); } +static const char NIGHTSGRADE_LIST[] = { + 'F', // GRADE_F + 'E', // GRADE_E + 'D', // GRADE_D + 'C', // GRADE_C + 'B', // GRADE_B + 'A', // GRADE_A + 'S', // GRADE_S + '\0' +}; + #define PARAMCHECK(n) do { if (!params[n]) { deh_warning("Too few parameters, need %d", n); return; }} while (0) static void readcondition(UINT8 set, UINT32 id, char *word2) { @@ -3058,7 +3069,21 @@ static void readcondition(UINT8 set, UINT32 id, char *word2) PARAMCHECK(2); // one optional one ty = UC_NIGHTSSCORE + offset; - re = atoi(params[2 + !!(params[3])]); + i = (params[3] ? 3 : 2); + if (fastncmp("GRADE_",params[i],6)) + { + char *p = params[i]+6; + for (re = 0; NIGHTSGRADE_LIST[re]; re++) + if (*p == NIGHTSGRADE_LIST[re]) + break; + if (!NIGHTSGRADE_LIST[re]) + { + deh_warning("Invalid NiGHTS grade %s\n", params[i]); + return; + } + } + else + re = atoi(params[i]); // Convert to map number if it appears to be one if (params[1][0] >= 'A' && params[1][0] <= 'Z') @@ -8474,15 +8499,6 @@ struct { {"LF2_NOVISITNEEDED",LF2_NOVISITNEEDED}, {"LF2_WIDEICON",LF2_WIDEICON}, - // NiGHTS grades - {"GRADE_F",GRADE_F}, - {"GRADE_E",GRADE_E}, - {"GRADE_D",GRADE_D}, - {"GRADE_C",GRADE_C}, - {"GRADE_B",GRADE_B}, - {"GRADE_A",GRADE_A}, - {"GRADE_S",GRADE_S}, - // Emeralds {"EMERALD1",EMERALD1}, {"EMERALD2",EMERALD2}, @@ -9304,6 +9320,19 @@ static fixed_t find_const(const char **rword) free(word); return 0; } + else if (fastncmp("GRADE_",word,6)) + { + char *p = word+6; + for (i = 0; NIGHTSGRADE_LIST[i]; i++) + if (*p == NIGHTSGRADE_LIST[i]) + { + free(word); + return i; + } + const_warning("NiGHTS grade",word); + free(word); + return 0; + } for (i = 0; INT_CONST[i].n; i++) if (fastcmp(word,INT_CONST[i].n)) { free(word); @@ -9752,6 +9781,18 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "skincolor '%s' could not be found.\n", word); return 0; } + else if (fastncmp("GRADE_",word,6)) + { + p = word+6; + for (i = 0; NIGHTSGRADE_LIST[i]; i++) + if (*p == NIGHTSGRADE_LIST[i]) + { + lua_pushinteger(L, i); + return 1; + } + if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word); + return 0; + } else if (fastncmp("MN_",word,3)) { p = word+3; for (i = 0; i < NUMMENUTYPES; i++) From f461b76bb0ed9fc96f0e4cb17fd5b990ba5694f4 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 7 Sep 2019 16:54:26 -0300 Subject: [PATCH 058/133] fix translucency --- src/doomdef.h | 4 ++- src/hardware/hw_cache.c | 14 +++++++++-- src/r_data.c | 54 ++++++++--------------------------------- src/r_plane.c | 2 -- 4 files changed, 25 insertions(+), 49 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 952bea318..4a0174369 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -616,6 +616,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2CB itself ported this from PrBoom+ #define NEWCLIP -//#define NO_PNG_LUMPS +#ifndef HAVE_PNG +#define NO_PNG_LUMPS +#endif #endif // __DOOMDEF__ diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 2b458c9d9..c9a75a4f3 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -892,8 +892,10 @@ lumpnum_t gr_patchflat; static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { + UINT8 *flat; patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC); size_t lumplength = W_LumpLength(flatlumpnum); + #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)patch, lumplength)) patch = R_PNGToPatch((UINT8 *)patch, lumplength); @@ -902,7 +904,10 @@ static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) grMipmap->width = (UINT16)SHORT(patch->width); grMipmap->height = (UINT16)SHORT(patch->height); - R_PatchToFlat(patch, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); + flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data); + memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height); + + R_PatchToFlat(patch, flat); } static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) @@ -980,6 +985,8 @@ void HWR_GetFlat(lumpnum_t flatlumpnum) static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) { + UINT8 *flat; + // setup the texture info #ifdef GLIDE_API_COMPATIBILITY grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; @@ -992,7 +999,10 @@ static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) grMipmap->width = (UINT16)textures[texturenum]->width; grMipmap->height = (UINT16)textures[texturenum]->height; - R_TextureToFlat(texturenum, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data)); + flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data); + memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height); + + R_TextureToFlat(texturenum, flat); } void HWR_GetTextureFlat(INT32 texturenum) diff --git a/src/r_data.c b/src/r_data.c index 8c6b4926a..fb30005bf 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -376,9 +376,13 @@ static UINT8 *R_GenerateTexture(size_t texnum) lumpnum = patch->lump; lumplength = W_LumpLengthPwad(wadnum, lumpnum); realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) + { realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); + goto multipatch; + } #endif // Check the patch for holes. @@ -436,6 +440,9 @@ static UINT8 *R_GenerateTexture(size_t texnum) } // multi-patch textures (or 'composite') +#ifndef NO_PNG_LUMPS + multipatch: +#endif texture->holes = false; texture->flip = 0; blocksize = (texture->width * 4) + (texture->width * texture->height); @@ -2441,7 +2448,6 @@ boolean R_CheckIfPatch(lumpnum_t lump) { result = false; break; - } } } @@ -2475,8 +2481,7 @@ void R_PatchToFlat(patch_t *patch, UINT8 *flat) source = (UINT8 *)(column) + 3; for (ofs = 0; dest < deststop && ofs < column->length; ofs++) { - if (source[ofs] != TRANSPARENTPIXEL) - *dest = source[ofs]; + *dest = source[ofs]; dest += SHORT(patch->width); } column = (column_t *)((UINT8 *)column + column->length + 4); @@ -2637,7 +2642,8 @@ static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) for (x = 0; x < width; x++) { png_bytep px = &(row[x * 4]); - flat[((y * width) + x)] = NearestColor((UINT8)px[0], (UINT8)px[1], (UINT8)px[2]); + if ((UINT8)px[3]) + flat[((y * width) + x)] = NearestColor((UINT8)px[0], (UINT8)px[1], (UINT8)px[2]); } } free(row_pointers); @@ -2645,34 +2651,6 @@ static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) return flat; } -// Get the alpha mask of the image. -static UINT8 *PNG_GetAlphaMask(UINT8 *png, size_t size) -{ - UINT8 *mask; - png_uint_32 x, y; - UINT16 width, height; - png_bytep *row_pointers = PNG_Read(png, &width, &height, size); - - if (!row_pointers) - return NULL; - - // Convert the image to 8bpp - mask = Z_Malloc(width * height, PU_LEVEL, NULL); - memset(mask, 0, width * height); - for (y = 0; y < height; y++) - { - png_bytep row = row_pointers[y]; - for (x = 0; x < width; x++) - { - png_bytep px = &(row[x * 4]); - mask[((y * width) + x)] = (UINT8)px[3]; - } - } - free(row_pointers); - - return mask; -} - // Convert a PNG to a flat. UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size) { @@ -2680,13 +2658,11 @@ UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size) } // Convert a PNG to a patch. -// This is adapted from the "kartmaker" utility static unsigned char imgbuf[1<<26]; patch_t *R_PNGToPatch(UINT8 *png, size_t size) { UINT16 width, height; UINT8 *raw = PNG_RawConvert(png, &width, &height, size); - UINT8 *alphamask = PNG_GetAlphaMask(png, size); UINT32 x, y; UINT8 *img; @@ -2726,16 +2702,6 @@ patch_t *R_PNGToPatch(UINT8 *png, size_t size) for (y = 0; y < height; y++) { UINT8 paletteIndex = raw[((y * width) + x)]; - UINT8 opaque = alphamask[((y * width) + x)]; // If 1, we have a pixel - - // End span if we have a transparent pixel - if (!opaque) - { - if (startofspan) - WRITE8(imgptr, 0); - startofspan = NULL; - continue; - } // Start new column if we need to if (!startofspan || spanSize == 255) diff --git a/src/r_plane.c b/src/r_plane.c index 92b3fe770..c28405726 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -754,7 +754,6 @@ static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boole { patch = (patch_t *)ds_source; #ifndef NO_PNG_LUMPS -#ifdef HAVE_PNG if (ispng) { levelflat->flatpatch = R_PNGToFlat(levelflat, ds_source, W_LumpLength(levelflat->lumpnum)); @@ -773,7 +772,6 @@ static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boole } } else -#endif #endif { levelflat->width = ds_flatwidth = SHORT(patch->width); From d26ff197dc0bc204b3cd925778fd630ea16c5173 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 7 Sep 2019 22:11:33 +0100 Subject: [PATCH 059/133] * Store gravflip (resolves #206) and destscale in starposts. (Using the same field, taking advantage of the fact that object scale will always be positive!) * Update the function signature of P_MixUp to accomodate both it and drawangle instead of doing it outside of the function. * If the player is spawning from the start of the stage and it's from the ceiling, be in fall frames as requested (resolves #191). --- src/d_clisrv.c | 2 ++ src/d_clisrv.h | 1 + src/d_player.h | 1 + src/g_game.c | 8 +++++++- src/lua_playerlib.c | 4 ++++ src/m_cheat.c | 3 +++ src/p_enemy.c | 16 +++++++--------- src/p_inter.c | 12 ++++++++++++ src/p_local.h | 2 +- src/p_mobj.c | 33 +++++++++++++++++++++++---------- src/p_saveg.c | 2 ++ src/p_spec.c | 2 +- src/p_telept.c | 5 ++++- 13 files changed, 68 insertions(+), 23 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 01e94485d..78e07a397 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -579,6 +579,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->starpostnum = LONG(players[i].starpostnum); rsp->starposttime = (tic_t)LONG(players[i].starposttime); rsp->starpostangle = (angle_t)LONG(players[i].starpostangle); + rsp->starpostscale = (fixed_t)LONG(players[i].starpostscale); rsp->maxlink = LONG(players[i].maxlink); rsp->dashspeed = (fixed_t)LONG(players[i].dashspeed); @@ -714,6 +715,7 @@ static void resynch_read_player(resynch_pak *rsp) players[i].starpostnum = LONG(rsp->starpostnum); players[i].starposttime = (tic_t)LONG(rsp->starposttime); players[i].starpostangle = (angle_t)LONG(rsp->starpostangle); + players[i].starpostscale = (fixed_t)LONG(rsp->starpostscale); players[i].maxlink = LONG(rsp->maxlink); players[i].dashspeed = (fixed_t)LONG(rsp->dashspeed); diff --git a/src/d_clisrv.h b/src/d_clisrv.h index a2f140f33..3bfabfc03 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -228,6 +228,7 @@ typedef struct INT32 starpostnum; tic_t starposttime; angle_t starpostangle; + fixed_t starpostscale; INT32 maxlink; fixed_t dashspeed; diff --git a/src/d_player.h b/src/d_player.h index 5860cf1de..69080bd9d 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -441,6 +441,7 @@ typedef struct player_s INT32 starpostnum; // The number of the last starpost you hit tic_t starposttime; // Your time when you hit the starpost angle_t starpostangle; // Angle that the starpost is facing - you respawn facing this way + fixed_t starpostscale; // Scale of the player; if negative, player is gravflipped ///////////////// // NiGHTS Stuff// diff --git a/src/g_game.c b/src/g_game.c index d5faf6846..89a96f3d0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2083,6 +2083,7 @@ static inline void G_PlayerFinishLevel(INT32 player) p->mo->flags2 &= ~MF2_SHADOW; // cancel invisibility P_FlashPal(p, 0, 0); // Resets + p->starpostscale = 0; p->starpostangle = 0; p->starposttime = 0; p->starpostx = 0; @@ -2129,6 +2130,7 @@ void G_PlayerReborn(INT32 player) INT16 starpostz; INT32 starpostnum; INT32 starpostangle; + fixed_t starpostscale; fixed_t jumpfactor; fixed_t height; fixed_t spinheight; @@ -2184,6 +2186,7 @@ void G_PlayerReborn(INT32 player) starpostz = players[player].starpostz; starpostnum = players[player].starpostnum; starpostangle = players[player].starpostangle; + starpostscale = players[player].starpostscale; jumpfactor = players[player].jumpfactor; height = players[player].height; spinheight = players[player].spinheight; @@ -2239,6 +2242,7 @@ void G_PlayerReborn(INT32 player) p->starpostz = starpostz; p->starpostnum = starpostnum; p->starpostangle = starpostangle; + p->starpostscale = starpostscale; p->jumpfactor = jumpfactor; p->height = height; p->spinheight = spinheight; @@ -2657,6 +2661,7 @@ void G_DoReborn(INT32 playernum) { if (!playeringame[i]) continue; + players[i].starpostscale = 0; players[i].starpostangle = 0; players[i].starposttime = 0; players[i].starpostx = 0; @@ -2779,6 +2784,7 @@ void G_AddPlayer(INT32 playernum) if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum))) continue; + p->starpostscale = players[i].starpostscale; p->starposttime = players[i].starposttime; p->starpostx = players[i].starpostx; p->starposty = players[i].starposty; @@ -3866,7 +3872,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean for (i = 0; i < MAXPLAYERS; i++) { players[i].playerstate = PST_REBORN; - players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0; + players[i].starpostscale = players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0; players[i].starpostx = players[i].starposty = players[i].starpostz = 0; if (netgame || multiplayer) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index addd707e1..dd9959afb 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -262,6 +262,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->starposttime); else if (fastcmp(field,"starpostangle")) lua_pushangle(L, plr->starpostangle); + else if (fastcmp(field,"starpostscale")) + lua_pushfixed(L, plr->starpostscale); else if (fastcmp(field,"angle_pos")) lua_pushangle(L, plr->angle_pos); else if (fastcmp(field,"old_angle_pos")) @@ -570,6 +572,8 @@ static int player_set(lua_State *L) plr->starposttime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"starpostangle")) plr->starpostangle = luaL_checkangle(L, 3); + else if (fastcmp(field,"starpostscale")) + plr->starpostscale = luaL_checkfixed(L, 3); else if (fastcmp(field,"angle_pos")) plr->angle_pos = luaL_checkangle(L, 3); else if (fastcmp(field,"old_angle_pos")) diff --git a/src/m_cheat.c b/src/m_cheat.c index da449b2f7..ae2703ee2 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -831,6 +831,9 @@ void Command_Savecheckpoint_f(void) players[consoleplayer].starposty = players[consoleplayer].mo->y>>FRACBITS; players[consoleplayer].starpostz = players[consoleplayer].mo->floorz>>FRACBITS; players[consoleplayer].starpostangle = players[consoleplayer].mo->angle; + players[consoleplayer].starpostscale = players[consoleplayer].mo->destscale; + if (players[consoleplayer].mo->flags2 & MF2_OBJECTFLIP) + players[consoleplayer].starpostscale *= -1; CONS_Printf(M_GetText("Temporary checkpoint created at %d, %d, %d\n"), players[consoleplayer].starpostx, players[consoleplayer].starposty, players[consoleplayer].starpostz); } diff --git a/src/p_enemy.c b/src/p_enemy.c index b60e5e68b..6e49d165d 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -6358,6 +6358,7 @@ void A_MixUp(mobj_t *actor) INT32 starpostnum; tic_t starposttime; angle_t starpostangle; + fixed_t starpostscale; INT32 mflags2; @@ -6405,6 +6406,7 @@ void A_MixUp(mobj_t *actor) starposty = players[one].starposty; starpostz = players[one].starpostz; starpostangle = players[one].starpostangle; + starpostscale = players[one].starpostscale; starpostnum = players[one].starpostnum; starposttime = players[one].starposttime; @@ -6413,15 +6415,11 @@ void A_MixUp(mobj_t *actor) P_MixUp(players[one].mo, players[two].mo->x, players[two].mo->y, players[two].mo->z, players[two].mo->angle, players[two].starpostx, players[two].starposty, players[two].starpostz, players[two].starpostnum, players[two].starposttime, players[two].starpostangle, - players[two].mo->flags2); - - players[one].drawangle = players[two].drawangle; + players[two].starpostscale, players[two].drawangle, players[two].mo->flags2); P_MixUp(players[two].mo, x, y, z, angle, starpostx, starposty, starpostz, starpostnum, starposttime, starpostangle, - mflags2); - - players[two].drawangle = drawangle; + starpostscale, drawangle, mflags2); //carry set after mixup. Stupid P_ResetPlayer() takes away some of the stuff we look for... //but not all of it! So we need to make sure they aren't set wrong or anything. @@ -6448,6 +6446,7 @@ void A_MixUp(mobj_t *actor) INT32 starpostnum[MAXPLAYERS]; tic_t starposttime[MAXPLAYERS]; angle_t starpostangle[MAXPLAYERS]; + fixed_t starpostscale[MAXPLAYERS]; INT32 flags2[MAXPLAYERS]; @@ -6485,6 +6484,7 @@ void A_MixUp(mobj_t *actor) starpostnum[counter] = players[i].starpostnum; starposttime[counter] = players[i].starposttime; starpostangle[counter] = players[i].starpostangle; + starpostscale[counter] = players[i].starpostscale; flags2[counter] = players[i].mo->flags2; @@ -6525,9 +6525,7 @@ void A_MixUp(mobj_t *actor) P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom][0], spposition[teleportfrom][0], spposition[teleportfrom][1], spposition[teleportfrom][2], starpostnum[teleportfrom], starposttime[teleportfrom], starpostangle[teleportfrom], - flags2[teleportfrom]); - - players[i].drawangle = anglepos[teleportfrom][1]; + starpostscale[teleportfrom], anglepos[teleportfrom][1], flags2[teleportfrom]); //...carry after. same reasoning. players[i].powers[pw_carry] = transcarry[teleportfrom]; diff --git a/src/p_inter.c b/src/p_inter.c index 0030e8e58..53481d6c5 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1427,6 +1427,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) players[i].starposty = player->mo->y>>FRACBITS; players[i].starpostz = special->z>>FRACBITS; players[i].starpostangle = special->angle; + players[i].starpostscale = player->mo->destscale; + if (special->flags2 & MF2_OBJECTFLIP) + { + players[i].starpostscale *= -1; + players[i].starpostz += (special->height - P_GetPlayerHeight(player))>>FRACBITS; + } players[i].starpostnum = special->health; if (cv_coopstarposts.value == 2 && (players[i].playerstate == PST_DEAD || players[i].spectator) && P_GetLives(&players[i])) @@ -1443,6 +1449,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) player->starposty = toucher->y>>FRACBITS; player->starpostz = special->z>>FRACBITS; player->starpostangle = special->angle; + player->starpostscale = player->mo->destscale; + if (special->flags2 & MF2_OBJECTFLIP) + { + player->starpostscale *= -1; + player->starpostz += (special->height - P_GetPlayerHeight(player))>>FRACBITS; + } player->starpostnum = special->health; S_StartSound(toucher, special->info->painsound); } diff --git a/src/p_local.h b/src/p_local.h index 3a0146e54..662eb691a 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -509,7 +509,7 @@ extern INT32 ceilmovesound; void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, INT16 starpostx, INT16 starposty, INT16 starpostz, INT32 starpostnum, tic_t starposttime, angle_t starpostangle, - INT32 flags2); + fixed_t starpostscale, angle_t drawangle, INT32 flags2); boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove); boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state); boolean P_CheckMissileSpawn(mobj_t *th); diff --git a/src/p_mobj.c b/src/p_mobj.c index 1ee90d250..130808712 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10521,10 +10521,6 @@ void P_AfterPlayerSpawn(INT32 playernum) else p->viewz = p->mo->z + p->viewheight; - if (p->powers[pw_carry] != CR_NIGHTSMODE) - P_SetPlayerMobjState(p->mo, S_PLAY_STND); - p->pflags &= ~PF_SPINNING; - if (playernum == consoleplayer) { // wake up the status bar @@ -10609,6 +10605,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) mobj->eflags |= MFE_VERTICALFLIP; mobj->flags2 |= MF2_OBJECTFLIP; } + if (mthing->options & MTF_AMBUSH) + P_SetPlayerMobjState(mobj, S_PLAY_FALL); } else z = floor; @@ -10627,7 +10625,12 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) P_SetThingPosition(mobj); mobj->z = z; - if (mobj->z == mobj->floorz) + if (mobj->flags2 & MF2_OBJECTFLIP) + { + if (mobj->z + mobj->height == mobj->ceilingz) + mobj->eflags |= MFE_ONGROUND; + } + else if (mobj->z == mobj->floorz) mobj->eflags |= MFE_ONGROUND; mobj->angle = angle; @@ -10663,16 +10666,26 @@ void P_MovePlayerToStarpost(INT32 playernum) sector->ceilingheight; z = p->starpostz << FRACBITS; - if (z < floor) - z = floor; - else if (z > ceiling - mobjinfo[MT_PLAYER].height) - z = ceiling - mobjinfo[MT_PLAYER].height; + + P_SetScale(mobj, (mobj->destscale = abs(p->starpostscale))); mobj->floorz = floor; mobj->ceilingz = ceiling; + if (z <= floor) + z = floor; + else if (z >= ceiling - mobj->height) + z = ceiling - mobj->height; + mobj->z = z; - if (mobj->z == mobj->floorz) + + if (p->starpostscale < 0) + { + mobj->flags2 |= MF2_OBJECTFLIP; + if (mobj->z + mobj->height == mobj->ceilingz) + mobj->eflags |= MFE_ONGROUND; + } + else if (mobj->z == mobj->floorz) mobj->eflags |= MFE_ONGROUND; mobj->angle = p->starpostangle; diff --git a/src/p_saveg.c b/src/p_saveg.c index 7c073b151..12f14e99d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -189,6 +189,7 @@ static void P_NetArchivePlayers(void) WRITEINT16(save_p, players[i].starpostz); WRITEINT32(save_p, players[i].starpostnum); WRITEANGLE(save_p, players[i].starpostangle); + WRITEFIXED(save_p, players[i].starpostscale); WRITEANGLE(save_p, players[i].angle_pos); WRITEANGLE(save_p, players[i].old_angle_pos); @@ -397,6 +398,7 @@ static void P_NetUnArchivePlayers(void) players[i].starpostz = READINT16(save_p); players[i].starpostnum = READINT32(save_p); players[i].starpostangle = READANGLE(save_p); + players[i].starpostscale = READFIXED(save_p); players[i].angle_pos = READANGLE(save_p); players[i].old_angle_pos = READANGLE(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index 37a1652f0..fbf896a2b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4942,7 +4942,7 @@ DoneSection2: CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1); // Reset starposts (checkpoints) info - player->starpostangle = player->starposttime = player->starpostnum = 0; + player->starpostscale = player->starpostangle = player->starposttime = player->starpostnum = 0; player->starpostx = player->starposty = player->starpostz = 0; P_ResetStarposts(); diff --git a/src/p_telept.c b/src/p_telept.c index e80dd0428..632b81e04 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -33,7 +33,7 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, INT16 starpostx, INT16 starposty, INT16 starpostz, INT32 starpostnum, tic_t starposttime, angle_t starpostangle, - INT32 flags2) + fixed_t starpostscale, angle_t drawangle, INT32 flags2) { const INT32 takeflags2 = MF2_TWOD|MF2_OBJECTFLIP; @@ -89,8 +89,11 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, thing->player->starpostz = starpostz; thing->player->starposttime = starposttime; thing->player->starpostangle = starpostangle; + thing->player->starpostscale = starpostscale; thing->player->starpostnum = starpostnum; + thing->player->drawangle = drawangle; + // Reset map starposts for the player's new info. P_ResetStarposts(); P_ClearStarPost(starpostnum); From ff293c3f6fa9e193480c769184e1591ab8c86f80 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 7 Sep 2019 18:20:49 -0300 Subject: [PATCH 060/133] fix non powers of two spans --- src/r_plane.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/r_plane.c b/src/r_plane.c index c28405726..a5b167015 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -1010,6 +1010,8 @@ void R_DrawSinglePlane(visplane_t *pl) if (ds_powersoftwo) { + // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red + fudge = ((1< Date: Sat, 7 Sep 2019 18:56:08 -0300 Subject: [PATCH 061/133] probably want to Z_Free this............... --- src/r_data.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index fb30005bf..5858117a5 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2511,7 +2511,7 @@ static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length) { png_ioread *f = png_get_io_ptr(png_ptr); if (length > (f->bufsize - f->current_pos)) - png_error(png_ptr, "read error in read_data_memory (loadpng)"); + png_error(png_ptr, "PNG_IOReader: buffer overrun"); memcpy(data, f->buffer + f->current_pos, length); f->current_pos += length; } @@ -2573,11 +2573,10 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); #endif - // png_source is array which have png data + // set our own read_function png_io.buffer = (png_bytep)png; png_io.bufsize = size; png_io.current_pos = 0; - // set our own read_function png_set_read_fn(png_ptr, &png_io, PNG_IOReader); #ifdef PNG_SET_USER_LIMITS_SUPPORTED @@ -2631,7 +2630,7 @@ static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) png_uint_32 width = *w, height = *h; if (!row_pointers) - return NULL; + I_Error("PNG_RawConvert: conversion failed"); // Convert the image to 8bpp flat = Z_Malloc(width * height, PU_LEVEL, NULL); @@ -2674,7 +2673,7 @@ patch_t *R_PNGToPatch(UINT8 *png, size_t size) #define WRITE32(buf, a) ({WRITE16(buf, (a)&65535); WRITE16(buf, (a)>>16);}) if (!raw) - return NULL; + I_Error("R_PNGToPatch: conversion failed"); // Write image size and offset WRITE16(imgptr, width); @@ -2762,6 +2761,9 @@ patch_t *R_PNGToPatch(UINT8 *png, size_t size) size = imgptr-imgbuf; img = malloc(size); memcpy(img, imgbuf, size); + + Z_Free(raw); + return (patch_t *)img; } @@ -2809,11 +2811,10 @@ boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size) png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); #endif - // png_source is array which have png data + // set our own read_function png_io.buffer = (png_bytep)png; png_io.bufsize = size; png_io.current_pos = 0; - // set our own read_function png_set_read_fn(png_ptr, &png_io, PNG_IOReader); #ifdef PNG_SET_USER_LIMITS_SUPPORTED From a67dd633ffd928b5af1f15899c1b474b58a7aa55 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 7 Sep 2019 19:02:50 -0300 Subject: [PATCH 062/133] if that function can't return NULL why should i do this? --- src/r_plane.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index a5b167015..de5bf9f00 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -758,18 +758,8 @@ static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boole { levelflat->flatpatch = R_PNGToFlat(levelflat, ds_source, W_LumpLength(levelflat->lumpnum)); levelflat->topoffset = levelflat->leftoffset = 0; - if (levelflat->flatpatch == NULL) - { - lumpnum_t redflr = W_CheckNumForName("REDFLR"); - levelflat->flatpatch = (UINT8 *)W_CacheLumpNum(redflr, PU_CACHE); - R_CheckFlatLength(W_LumpLength(redflr)); - R_CheckPowersOfTwo(); - } - else - { - ds_flatwidth = levelflat->width; - ds_flatheight = levelflat->height; - } + ds_flatwidth = levelflat->width; + ds_flatheight = levelflat->height; } else #endif From 4adff344024825ccf0ed25419aca0d46030e5381 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 7 Sep 2019 22:43:29 -0300 Subject: [PATCH 063/133] opengl patch translucency --- src/hardware/hw_cache.c | 87 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 6bc2c712e..fb25dc58e 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -60,6 +60,47 @@ static const INT32 format2bpp[16] = 2, //14 GR_TEXFMT_AP_88 }; +static RGBA_t astblendpixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) +{ + RGBA_t output; + output.s.alpha = 0xFF; + + if (style == AST_TRANSLUCENT) + { + if (alpha == 0) + output.rgba = background.rgba; + else if (alpha == 0xFF) + output.rgba = foreground.rgba; + else if (alpha < 0xFF) + { + UINT8 beta = (0xFF - alpha); + output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF; + output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF; + output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF; + } + // write foreground pixel alpha + // if there's no pixel in here + if (!background.rgba) + output.s.alpha = foreground.s.alpha; + } + + return output; +} + +static UINT8 astblendpixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha) +{ + if ((style == AST_TRANSLUCENT) && (alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? + { + UINT8 *mytransmap; + if (alpha < 255/11) // Is the patch way too translucent? Don't render then. + return background; + // The equation's not exact but it works as intended. I'll call it a day for now. + mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); + if (background != 0xFF) + return *(mytransmap + (background<<8) + foreground); + } + return background; +} // This code was originally placed directly in HWR_DrawPatchInCache. // It is now split from it for my sanity! (and the sanity of others) @@ -138,18 +179,37 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm // Alam: SRB2 uses Mingw, HUGS switch (bpp) { - case 2 : texelu16 = (UINT16)((alpha<<8) | texel); + case 2 : // uhhhhhhhh.......... + if ((originPatch != NULL) && originPatch->style) + texel = astblendpixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); + texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; case 3 : colortemp = V_GetColor(texel); + if ((originPatch != NULL) && originPatch->style) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; case 4 : colortemp = V_GetColor(texel); colortemp.s.alpha = alpha; + if ((originPatch != NULL) && originPatch->style) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } memcpy(dest, &colortemp, sizeof(RGBA_t)); break; // default is 1 - default: *dest = texel; + default: + if ((originPatch != NULL) && originPatch->style) + *dest = astblendpixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); + else + *dest = texel; break; } @@ -233,18 +293,37 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, // Alam: SRB2 uses Mingw, HUGS switch (bpp) { - case 2 : texelu16 = (UINT16)((alpha<<8) | texel); + case 2 : // uhhhhhhhh.......... + if ((originPatch != NULL) && originPatch->style) + texel = astblendpixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); + texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; case 3 : colortemp = V_GetColor(texel); + if ((originPatch != NULL) && originPatch->style) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; case 4 : colortemp = V_GetColor(texel); colortemp.s.alpha = alpha; + if ((originPatch != NULL) && originPatch->style) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } memcpy(dest, &colortemp, sizeof(RGBA_t)); break; // default is 1 - default: *dest = texel; + default: + if ((originPatch != NULL) && originPatch->style) + *dest = astblendpixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); + else + *dest = texel; break; } From b7c9f15225413018b526802eecedff95e3753fbf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 7 Sep 2019 22:00:38 -0400 Subject: [PATCH 064/133] Fix NiGHTS attack menu not drawing correct background --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 128b15a76..d9a6bfea6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8479,8 +8479,8 @@ static void M_NightsAttack(INT32 choice) M_PatchSkinNameTable(); G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching - M_SetupNextMenu(&SP_NightsAttackDef); titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please + M_SetupNextMenu(&SP_NightsAttackDef); if (!M_CanShowLevelInList(cv_nextmap.value-1, -1) && levelselect.rows[0].maplist[0]) CV_SetValue(&cv_nextmap, levelselect.rows[0].maplist[0]); else From 8ee0a9309b289a1a3d1a7260a44a43c776180686 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 8 Sep 2019 01:29:09 -0400 Subject: [PATCH 065/133] Better directory structure --- src/d_main.c | 6 +++++- src/d_netcmd.c | 2 ++ src/m_menu.c | 51 ++++++++++++++++++++++++++++-------------------- src/m_menu.h | 3 +++ src/m_misc.c | 44 ++++++++++++++++++++++++++++------------- src/m_misc.h | 2 +- src/sdl/i_main.c | 36 ++++++++++++++++++++++++++++------ 7 files changed, 101 insertions(+), 43 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index eaeae4b10..c838cd2e3 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -129,6 +129,7 @@ char srb2home[256] = "."; char srb2path[256] = "."; boolean usehome = true; const char *pandf = "%s" PATHSEP "%s"; +static char addonsdir[MAX_WADPATH]; // // EVENT HANDLING @@ -1038,7 +1039,6 @@ void D_SRB2Main(void) // can't use sprintf since there is %u in savegamename strcatbf(savegamename, srb2home, PATHSEP); - I_mkdir(srb2home, 0700); #else snprintf(srb2home, sizeof srb2home, "%s", userhome); snprintf(downloaddir, sizeof downloaddir, "%s", userhome); @@ -1055,6 +1055,10 @@ void D_SRB2Main(void) configfile[sizeof configfile - 1] = '\0'; } + // Create addons dir + snprintf(addonsdir, sizeof addonsdir, "%s%s%s", srb2home, PATHSEP, "addons"); + I_mkdir(addonsdir, 0755); + // rand() needs seeded regardless of password srand((unsigned int)time(NULL)); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 590543f00..42c76389d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -630,6 +630,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_screenshot_folder); CV_RegisterVar(&cv_screenshot_colorprofile); CV_RegisterVar(&cv_moviemode); + CV_RegisterVar(&cv_movie_option); + CV_RegisterVar(&cv_movie_folder); // PNG variables CV_RegisterVar(&cv_zlib_level); CV_RegisterVar(&cv_zlib_memory); diff --git a/src/m_menu.c b/src/m_menu.c index 128b15a76..93f5aa83f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1353,36 +1353,39 @@ static menuitem_t OP_ScreenshotOptionsMenu[] = { {IT_HEADER, NULL, "General", NULL, 0}, {IT_STRING|IT_CVAR, NULL, "Use color profile", &cv_screenshot_colorprofile, 6}, - {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_screenshot_option, 11}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_screenshot_folder, 16}, - {IT_HEADER, NULL, "Screenshots (F8)", NULL, 30}, - {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memory, 36}, - {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_level, 41}, - {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategy, 46}, - {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bits, 51}, + {IT_HEADER, NULL, "Screenshots (F8)", NULL, 16}, + {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_screenshot_option, 22}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_screenshot_folder, 27}, + {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memory, 42}, + {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_level, 47}, + {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategy, 52}, + {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bits, 57}, - {IT_HEADER, NULL, "Movie Mode (F9)", NULL, 60}, - {IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 66}, + {IT_HEADER, NULL, "Movie Mode (F9)", NULL, 64}, + {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_movie_option, 70}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_movie_folder, 75}, + {IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 90}, - {IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 71}, - {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 76}, + {IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 95}, + {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 100}, - {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 71}, - {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 76}, - {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 81}, - {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 86}, + {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 95}, + {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 100}, + {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 105}, + {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 110}, }; enum { op_screenshot_colorprofile = 1, - op_screenshot_folder = 3, - op_screenshot_capture = 10, - op_screenshot_gif_start = 11, - op_screenshot_gif_end = 12, - op_screenshot_apng_start = 13, - op_screenshot_apng_end = 16, + op_screenshot_folder = 4, + op_movie_folder = 11, + op_screenshot_capture = 12, + op_screenshot_gif_start = 13, + op_screenshot_gif_end = 14, + op_screenshot_apng_start = 15, + op_screenshot_apng_end = 18, }; static menuitem_t OP_EraseDataMenu[] = @@ -2200,6 +2203,12 @@ void Addons_option_Onchange(void) (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); } +void Moviemode_option_Onchange(void) +{ + OP_ScreenshotOptionsMenu[op_movie_folder].status = + (cv_movie_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); +} + // ========================================================================== // END ORGANIZATION STUFF. // ========================================================================== diff --git a/src/m_menu.h b/src/m_menu.h index 347725e10..4292ea581 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -397,6 +397,9 @@ void Screenshot_option_Onchange(void); // Addons menu updating void Addons_option_Onchange(void); +// Moviemode menu updating +void Moviemode_option_Onchange(void); + // These defines make it a little easier to make menus #define DEFAULTMENUSTYLE(id, header, source, prev, x, y)\ {\ diff --git a/src/m_misc.c b/src/m_misc.c index 22e19df73..3ba50689c 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -108,6 +108,9 @@ consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "Yes", CV_SAV static CV_PossibleValue_t moviemode_cons_t[] = {{MM_GIF, "GIF"}, {MM_APNG, "aPNG"}, {MM_SCREENSHOT, "Screenshots"}, {0, NULL}}; consvar_t cv_moviemode = {"moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_movie_option = {"movie_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Moviemode_option_Onchange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_movie_folder = {"movie_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; + static CV_PossibleValue_t zlib_mem_level_t[] = { {1, "(Min Memory) 1"}, {2, "2"}, {3, "3"}, {4, "4"}, {5, "5"}, {6, "6"}, {7, "7"}, @@ -1124,19 +1127,25 @@ static inline moviemode_t M_StartMovieGIF(const char *pathname) void M_StartMovie(void) { #if NUMSCREENS > 2 - const char *pathname = "."; + char pathname[MAX_WADPATH]; if (moviemode) return; - if (cv_screenshot_option.value == 0) - pathname = usehome ? srb2home : srb2path; - else if (cv_screenshot_option.value == 1) - pathname = srb2home; - else if (cv_screenshot_option.value == 2) - pathname = srb2path; - else if (cv_screenshot_option.value == 3 && *cv_screenshot_folder.string != '\0') - pathname = cv_screenshot_folder.string; + if (cv_movie_option.value == 0) + strcpy(pathname, usehome ? srb2home : srb2path); + else if (cv_movie_option.value == 1) + strcpy(pathname, srb2home); + else if (cv_movie_option.value == 2) + strcpy(pathname, srb2path); + else if (cv_movie_option.value == 3 && *cv_movie_folder.string != '\0') + strcpy(pathname, cv_screenshot_folder.string); + + if (cv_movie_option.value != 3) + { + strcat(pathname, PATHSEP"movies"PATHSEP); + I_mkdir(pathname, 0755); + } if (rendermode == render_none) I_Error("Can't make a movie without a render system\n"); @@ -1474,7 +1483,8 @@ void M_ScreenShot(void) void M_DoScreenShot(void) { #if NUMSCREENS > 2 - const char *freename = NULL, *pathname = "."; + const char *freename = NULL; + char pathname[MAX_WADPATH]; boolean ret = false; UINT8 *linear = NULL; @@ -1486,13 +1496,19 @@ void M_DoScreenShot(void) return; if (cv_screenshot_option.value == 0) - pathname = usehome ? srb2home : srb2path; + strcpy(pathname, usehome ? srb2home : srb2path); else if (cv_screenshot_option.value == 1) - pathname = srb2home; + strcpy(pathname, srb2home); else if (cv_screenshot_option.value == 2) - pathname = srb2path; + strcpy(pathname, srb2path); else if (cv_screenshot_option.value == 3 && *cv_screenshot_folder.string != '\0') - pathname = cv_screenshot_folder.string; + strcpy(pathname, cv_screenshot_folder.string); + + if (cv_screenshot_option.value != 3) + { + strcat(pathname, PATHSEP"screenshots"PATHSEP); + I_mkdir(pathname, 0755); + } #ifdef USE_PNG freename = Newsnapshotfile(pathname,"png"); diff --git a/src/m_misc.h b/src/m_misc.h index 6ac92dbcc..7038e3e48 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -30,7 +30,7 @@ typedef enum { extern moviemode_t moviemode; extern consvar_t cv_screenshot_option, cv_screenshot_folder, cv_screenshot_colorprofile; -extern consvar_t cv_moviemode; +extern consvar_t cv_moviemode, cv_movie_folder, cv_movie_option; extern consvar_t cv_zlib_memory, cv_zlib_level, cv_zlib_strategy, cv_zlib_window_bits; extern consvar_t cv_zlib_memorya, cv_zlib_levela, cv_zlib_strategya, cv_zlib_window_bitsa; extern consvar_t cv_apng_delay; diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index f54f0d7c5..2a67e88fe 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -26,6 +26,8 @@ #include #endif +#include "time.h" // For log timestamps + #ifdef HAVE_SDL #ifdef HAVE_TTF @@ -114,6 +116,7 @@ int main(int argc, char **argv) #endif { const char *logdir = NULL; + char logfile[MAX_WADPATH]; myargc = argc; myargv = argv; /// \todo pull out path to exe from this string @@ -125,15 +128,35 @@ int main(int argc, char **argv) #endif #endif - logdir = D_Home(); - #ifdef LOGMESSAGES + if (!M_CheckParm("-nolog")) + { + logdir = D_Home(); + + time_t my_time; + struct tm * timeinfo; + char buf[26]; + my_time = time(NULL); + timeinfo = localtime(&my_time); + + strftime(buf, 26, "%Y-%m-%d %H-%M-%S", timeinfo); + strcpy(logfile, va("log-%s.txt", buf)); + #ifdef DEFAULTDIR - if (logdir) - logstream = fopen(va("%s/"DEFAULTDIR"/log.txt",logdir), "wt"); - else + if (logdir) + { + // Create dirs here because D_SRB2Main() is too late. + I_mkdir(va("%s%s"DEFAULTDIR, logdir, PATHSEP), 0755); + I_mkdir(va("%s%s"DEFAULTDIR"%slogs",logdir, PATHSEP, PATHSEP), 0755); + logstream = fopen(va("%s%s"DEFAULTDIR"%slogs%s%s",logdir, PATHSEP, PATHSEP, PATHSEP, logfile), "wt"); + } + else #endif - logstream = fopen("./log.txt", "wt"); + { + I_mkdir("."PATHSEP"logs"PATHSEP, 0755); + logstream = fopen(va("."PATHSEP"logs"PATHSEP"%s", logfile), "wt"); + } + } #endif //I_OutputMsg("I_StartupSystem() ...\n"); @@ -161,6 +184,7 @@ int main(int argc, char **argv) CONS_Printf("Setting up SRB2...\n"); D_SRB2Main(); CONS_Printf("Entering main game loop...\n"); + CONS_Printf("%s\n", logfile); // never return D_SRB2Loop(); From ff1fa3f92babee4290ebadc1578e8525c9213008 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sun, 8 Sep 2019 13:21:00 -0300 Subject: [PATCH 066/133] Implement all the other alpha blend styles --- src/hardware/hw_cache.c | 85 +++++-------------------- src/r_data.c | 133 ++++++++++++++++++++++++++++++++++------ src/r_data.h | 7 ++- 3 files changed, 138 insertions(+), 87 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index fb25dc58e..5eb6d9104 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -60,48 +60,6 @@ static const INT32 format2bpp[16] = 2, //14 GR_TEXFMT_AP_88 }; -static RGBA_t astblendpixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) -{ - RGBA_t output; - output.s.alpha = 0xFF; - - if (style == AST_TRANSLUCENT) - { - if (alpha == 0) - output.rgba = background.rgba; - else if (alpha == 0xFF) - output.rgba = foreground.rgba; - else if (alpha < 0xFF) - { - UINT8 beta = (0xFF - alpha); - output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF; - output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF; - output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF; - } - // write foreground pixel alpha - // if there's no pixel in here - if (!background.rgba) - output.s.alpha = foreground.s.alpha; - } - - return output; -} - -static UINT8 astblendpixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha) -{ - if ((style == AST_TRANSLUCENT) && (alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? - { - UINT8 *mytransmap; - if (alpha < 255/11) // Is the patch way too translucent? Don't render then. - return background; - // The equation's not exact but it works as intended. I'll call it a day for now. - mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); - if (background != 0xFF) - return *(mytransmap + (background<<8) + foreground); - } - return background; -} - // This code was originally placed directly in HWR_DrawPatchInCache. // It is now split from it for my sanity! (and the sanity of others) // -- Monster Iestyn (13/02/19) @@ -180,34 +138,34 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm switch (bpp) { case 2 : // uhhhhhhhh.......... - if ((originPatch != NULL) && originPatch->style) - texel = astblendpixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; case 3 : colortemp = V_GetColor(texel); - if ((originPatch != NULL) && originPatch->style) + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; case 4 : colortemp = V_GetColor(texel); colortemp.s.alpha = alpha; - if ((originPatch != NULL) && originPatch->style) + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)); break; // default is 1 default: - if ((originPatch != NULL) && originPatch->style) - *dest = astblendpixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); else *dest = texel; break; @@ -294,34 +252,34 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, switch (bpp) { case 2 : // uhhhhhhhh.......... - if ((originPatch != NULL) && originPatch->style) - texel = astblendpixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; case 3 : colortemp = V_GetColor(texel); - if ((originPatch != NULL) && originPatch->style) + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; case 4 : colortemp = V_GetColor(texel); colortemp.s.alpha = alpha; - if ((originPatch != NULL) && originPatch->style) + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { RGBA_t rgbatexel; rgbatexel.rgba = *(UINT32 *)dest; - colortemp = astblendpixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + colortemp = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); } memcpy(dest, &colortemp, sizeof(RGBA_t)); break; // default is 1 default: - if ((originPatch != NULL) && originPatch->style) - *dest = astblendpixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); else *dest = texel; break; @@ -410,16 +368,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, if (texture->width <= 0 || texture->height <= 0) return; - /*if ((patch->style == AST_TRANSLUCENT) && (patch->alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? - { - if (patch->alpha < 255/11) // Is the patch way too translucent? Don't render then. - continue; - ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawTransFlippedColumnInCache : HWR_DrawTransColumnInCache; - } - else*/ - { - ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache; - } + ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache; x1 = patch->originx; width = SHORT(realpatch->width); diff --git a/src/r_data.c b/src/r_data.c index 6889bddde..335a390d0 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -220,15 +220,110 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, tex } } +RGBA_t ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) +{ + RGBA_t output; + if (style == AST_TRANSLUCENT) + { + if (alpha == 0) + output.rgba = background.rgba; + else if (alpha == 0xFF) + output.rgba = foreground.rgba; + else if (alpha < 0xFF) + { + UINT8 beta = (0xFF - alpha); + output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF; + output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF; + output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF; + } + // write foreground pixel alpha + // if there's no pixel in here + if (!background.rgba) + output.s.alpha = foreground.s.alpha; + } +#define clamp(c) max(min(c, 0xFF), 0x00); + else + { + float falpha = ((float)alpha / 256.0f); + float fr = ((float)foreground.s.red * falpha); + float fg = ((float)foreground.s.green * falpha); + float fb = ((float)foreground.s.blue * falpha); + if (style == AST_ADD) + { + output.s.red = clamp((int)(background.s.red + fr)); + output.s.green = clamp((int)(background.s.green + fg)); + output.s.blue = clamp((int)(background.s.blue + fb)); + } + else if (style == AST_SUBTRACT) + { + output.s.red = clamp((int)(background.s.red - fr)); + output.s.green = clamp((int)(background.s.green - fg)); + output.s.blue = clamp((int)(background.s.blue - fb)); + } + else if (style == AST_REVERSESUBTRACT) + { + output.s.red = clamp((int)((-background.s.red) + fr)); + output.s.green = clamp((int)((-background.s.green) + fg)); + output.s.blue = clamp((int)((-background.s.blue) + fb)); + } + else if (style == AST_MODULATE) + { + fr = ((float)foreground.s.red / 256.0f); + fg = ((float)foreground.s.green / 256.0f); + fb = ((float)foreground.s.blue / 256.0f); + output.s.red = clamp((int)(background.s.red * fr)); + output.s.green = clamp((int)(background.s.green * fg)); + output.s.blue = clamp((int)(background.s.blue * fb)); + } + // just copy the pixel + else if (style == AST_COPY) + return background; + } +#undef clamp + // unimplemented blend modes return the background pixel + output = background; + output.s.alpha = 0xFF; + return output; +} + +UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha) +{ + if ((style == AST_TRANSLUCENT) && (alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? + { + UINT8 *mytransmap; + if (alpha < 255/11) // Is the patch way too translucent? Don't render then. + return background; + // The equation's not exact but it works as intended. I'll call it a day for now. + mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); + if (background != 0xFF) + return *(mytransmap + (background<<8) + foreground); + } + // just copy the pixel + else if (style == AST_COPY) + return background; + // use ASTBlendPixel for all other blend modes + // and find the nearest colour in the palette + else if (style != AST_TRANSLUCENT) + { + RGBA_t texel; + RGBA_t bg = V_GetColor(background); + RGBA_t fg = V_GetColor(foreground); + texel = ASTBlendPixel(bg, fg, style, alpha); + return NearestColor(texel.s.red, texel.s.green, texel.s.blue); + } + // fallback if all above fails, somehow + // return the background pixel + return background; +} + // -// R_DrawTransColumnInCache +// R_DrawBlendColumnInCache // Draws a translucent column into the cache, applying a half-cooked equation to get a proper translucency value (Needs code in R_GenerateTexture()). // -static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) { INT32 count, position; UINT8 *source, *dest; - UINT8 *mytransmap = transtables + ((8*(originPatch->alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); // The equation's not exact but it works as intended. I'll call it a day for now. INT32 topdelta, prevdelta = -1; INT32 originy = originPatch->originy; @@ -258,7 +353,8 @@ static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpa if (count > 0) { for (; dest < cache + position + count; source++, dest++) - if (*dest != 0xFF) *dest = *(mytransmap + ((*dest)<<8) + (*source)); + if (*dest != 0xFF) + *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); } patch = (column_t *)((UINT8 *)patch + patch->length + 4); @@ -269,11 +365,10 @@ static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpa // R_DrawTransColumnInCache // Similar to the one above except that the column is inverted. // -static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) { INT32 count, position; UINT8 *source, *dest; - UINT8 *mytransmap = transtables + ((8*(originPatch->alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); // The equation's not exact but it works as intended. I'll call it a day for now. INT32 topdelta, prevdelta = -1; INT32 originy = originPatch->originy; @@ -302,7 +397,8 @@ static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache if (count > 0) { for (; dest < cache + position + count; --source, dest++) - if (*dest != 0xFF) *dest = *(mytransmap + ((*dest)<<8) + (*source)); + if (*dest != 0xFF) + *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); } patch = (column_t *)((UINT8 *)patch + patch->length + 4); @@ -422,16 +518,10 @@ static UINT8 *R_GenerateTexture(size_t texnum) for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { static void (*ColumnDrawerPointer)(column_t *, UINT8 *, texpatch_t *, INT32, INT32); // Column drawing function pointer. - if ((patch->style == AST_TRANSLUCENT) && (patch->alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? - { - if (patch->alpha < 255/11) // Is the patch way too translucent? Don't render then. - continue; - ColumnDrawerPointer = (patch->flip & 2) ? R_DrawTransFlippedColumnInCache : R_DrawTransColumnInCache; - } + if (patch->style != AST_COPY) + ColumnDrawerPointer = (patch->flip & 2) ? R_DrawBlendFlippedColumnInCache : R_DrawBlendColumnInCache; else - { ColumnDrawerPointer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache; - } realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); x1 = patch->originx; @@ -848,8 +938,16 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) { Z_Free(texturesToken); texturesToken = M_GetToken(NULL); - if(stricmp(texturesToken, "TRANSLUCENT")==0) + if (stricmp(texturesToken, "TRANSLUCENT")==0) style = AST_TRANSLUCENT; + else if (stricmp(texturesToken, "ADD")==0) + style = AST_ADD; + else if (stricmp(texturesToken, "SUBTRACT")==0) + style = AST_SUBTRACT; + else if (stricmp(texturesToken, "REVERSESUBTRACT")==0) + style = AST_REVERSESUBTRACT; + else if (stricmp(texturesToken, "MODULATE")==0) + style = AST_MODULATE; } else if (stricmp(texturesToken, "FLIPX")==0) flip |= 1; @@ -1615,7 +1713,6 @@ extracolormap_t *R_ColormapForName(char *name) // static double deltas[256][3], map[256][3]; -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); static int RoundUp(double number); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) @@ -2027,7 +2124,7 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex // Thanks to quake2 source! // utils3/qdata/images.c -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) { int dr, dg, db; int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i; diff --git a/src/r_data.h b/src/r_data.h index b6b0a16a1..af1c9114a 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -22,7 +22,12 @@ #endif // Possible alpha types for a patch. -enum patchalphastyle {AST_COPY, AST_TRANSLUCENT}; // , AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY}; +enum patchalphastyle {AST_COPY, AST_TRANSLUCENT, AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY}; + +RGBA_t ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha); +UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha); + +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); // moved here for r_sky.c (texpatch_t is used) From 2e90c4093429c91155761817e6425ffffcbcb018 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 6 Sep 2019 14:57:13 +0100 Subject: [PATCH 067/133] Fade time before Game Over track. Notably, can no longer use P_PlayJingle because of pre-fade. --- src/p_inter.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 9025e2664..6d1f54d5f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2469,8 +2469,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget else if (P_IsLocalPlayer(target->player)) gameovermus = true; - if (gameovermus) - P_PlayJingle(target->player, JT_GOVER); // Yousa dead now, Okieday? Tails 03-14-2000 + if (gameovermus) // Yousa dead now, Okieday? Tails 03-14-2000 + S_ChangeMusicEx("_gover", 0, 0, 0, (2*MUSICRATE) - (MUSICRATE/25), 0); // 1.96 seconds + //P_PlayJingle(target->player, JT_GOVER); // can't be used because incompatible with track fadeout if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && numgameovers < maxgameovers) { From 2c898841e978bf5fbf85c3120db4ed5948187de8 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 8 Sep 2019 18:03:51 +0100 Subject: [PATCH 068/133] Extend gameovertics again by two seconds. --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 1bbf8aa4a..ded4e6ae7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -215,7 +215,7 @@ UINT16 spacetimetics = 11*TICRATE + (TICRATE/2); UINT16 extralifetics = 4*TICRATE; UINT16 nightslinktics = 2*TICRATE; -INT32 gameovertics = 10*TICRATE; +INT32 gameovertics = 12*TICRATE; UINT8 ammoremovaltics = 2*TICRATE; From 11e3f5ec964112a8799b08a76eb3eef994baee4f Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 8 Sep 2019 21:21:36 +0100 Subject: [PATCH 069/133] Change flipped starpostz to define the top of the player object, for cases where scale on contact with starpost is different to spawn scale. --- src/m_cheat.c | 3 +++ src/p_inter.c | 4 ++-- src/p_mobj.c | 26 ++++++++++++++------------ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/m_cheat.c b/src/m_cheat.c index ae2703ee2..bb757839a 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -833,7 +833,10 @@ void Command_Savecheckpoint_f(void) players[consoleplayer].starpostangle = players[consoleplayer].mo->angle; players[consoleplayer].starpostscale = players[consoleplayer].mo->destscale; if (players[consoleplayer].mo->flags2 & MF2_OBJECTFLIP) + { players[consoleplayer].starpostscale *= -1; + players[consoleplayer].starpostz += players[consoleplayer].mo->height; + } CONS_Printf(M_GetText("Temporary checkpoint created at %d, %d, %d\n"), players[consoleplayer].starpostx, players[consoleplayer].starposty, players[consoleplayer].starpostz); } diff --git a/src/p_inter.c b/src/p_inter.c index 53481d6c5..cc9250e42 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1431,7 +1431,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->flags2 & MF2_OBJECTFLIP) { players[i].starpostscale *= -1; - players[i].starpostz += (special->height - P_GetPlayerHeight(player))>>FRACBITS; + players[i].starpostz += special->height>>FRACBITS; } players[i].starpostnum = special->health; @@ -1453,7 +1453,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->flags2 & MF2_OBJECTFLIP) { player->starpostscale *= -1; - player->starpostz += (special->height - P_GetPlayerHeight(player))>>FRACBITS; + player->starpostz += special->height>>FRACBITS; } player->starpostnum = special->health; S_StartSound(toucher, special->info->painsound); diff --git a/src/p_mobj.c b/src/p_mobj.c index 130808712..5843b9f43 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10669,24 +10669,26 @@ void P_MovePlayerToStarpost(INT32 playernum) P_SetScale(mobj, (mobj->destscale = abs(p->starpostscale))); - mobj->floorz = floor; - mobj->ceilingz = ceiling; - - if (z <= floor) - z = floor; - else if (z >= ceiling - mobj->height) - z = ceiling - mobj->height; - - mobj->z = z; - if (p->starpostscale < 0) { mobj->flags2 |= MF2_OBJECTFLIP; - if (mobj->z + mobj->height == mobj->ceilingz) + if (z >= ceiling) + { mobj->eflags |= MFE_ONGROUND; + z = ceiling; + } + z -= mobj->height; } - else if (mobj->z == mobj->floorz) + else if (z <= floor) + { mobj->eflags |= MFE_ONGROUND; + z = floor; + } + + mobj->floorz = floor; + mobj->ceilingz = ceiling; + + mobj->z = z; mobj->angle = p->starpostangle; From ba50a03d9c13328124769006fd99d7dec2e6c939 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 8 Sep 2019 21:28:02 +0100 Subject: [PATCH 070/133] Update SPR2_XTRA references for adjusted player.dta content. --- src/f_finale.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 056b7f815..e44add4d1 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1584,15 +1584,15 @@ void F_StartEnding(void) UINT8 skinnum = players[consoleplayer].skin; spritedef_t *sprdef; spriteframe_t *sprframe; - if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 5) + if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 7) { sprdef = &skins[skinnum].sprites[SPR2_XTRA]; // character head, skin specific - sprframe = &sprdef->spriteframes[2]; - endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); - sprframe = &sprdef->spriteframes[3]; - endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); sprframe = &sprdef->spriteframes[4]; + endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); + sprframe = &sprdef->spriteframes[5]; + endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); + sprframe = &sprdef->spriteframes[6]; endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); } else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this) From cc80cd77c531d23f88ae5f7ee417a453172fdc09 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 8 Sep 2019 16:54:40 -0400 Subject: [PATCH 071/133] Fix this mistake --- src/m_misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_misc.c b/src/m_misc.c index 3ba50689c..aaaf30d67 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1139,7 +1139,7 @@ void M_StartMovie(void) else if (cv_movie_option.value == 2) strcpy(pathname, srb2path); else if (cv_movie_option.value == 3 && *cv_movie_folder.string != '\0') - strcpy(pathname, cv_screenshot_folder.string); + strcpy(pathname, cv_movie_folder.string); if (cv_movie_option.value != 3) { From 1bf78a242341c2a770690bf16b8968567d0906e6 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 8 Sep 2019 17:14:47 -0400 Subject: [PATCH 072/133] Move mobj_t declaration to top of the block --- src/p_spec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 014a09845..74bea7266 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3956,6 +3956,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 461: // Spawns an object on the map based on texture offsets { const mobjtype_t type = (mobjtype_t)(sides[line->sidenum[0]].toptexture); + mobj_t *mobj; fixed_t x, y, z; x = sides[line->sidenum[0]].textureoffset; @@ -3977,7 +3978,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } } - mobj_t *mobj = P_SpawnMobj(x, y, z, type); + mobj = P_SpawnMobj(x, y, z, type); if (mobj) CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow. else From e5d9d3499f7691d5707519477a88f0a1f6561bfb Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 8 Sep 2019 21:07:16 +0100 Subject: [PATCH 073/133] DON'T PUSH ALONE - first dregs of continue screen --- src/info.c | 12 ++++++++++++ src/info.h | 8 +++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 18f0e838a..50f74b4d1 100644 --- a/src/info.c +++ b/src/info.c @@ -577,8 +577,14 @@ char spr2names[NUMPLAYERSPRITES][5] = "TALA", "TALB", + "CNT1", + "CNT2", + "CNT3", + "CNT4", + "SIGN", "LIFE", + "XTRA", }; playersprite_t free_spr2 = SPR2_FIRSTFREESLOT; @@ -674,8 +680,14 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_TAL9, // SPR2_TALA, SPR2_TAL0, // SPR2_TALB, + 0, // SPR2_CNT1, + SPR2_FALL, // SPR2_CNT2, + SPR2_SPNG, // SPR2_CNT3, + SPR2_CNT1, // SPR2_CNT4, + 0, // SPR2_SIGN, 0, // SPR2_LIFE, + 0, // SPR2_XTRA (should never be referenced) }; diff --git a/src/info.h b/src/info.h index 593c1fb7c..e1adbe070 100644 --- a/src/info.h +++ b/src/info.h @@ -833,9 +833,15 @@ typedef enum playersprite SPR2_TALA, SPR2_TALB, + SPR2_CNT1, // continue disappointment + SPR2_CNT2, // continue lift + SPR2_CNT3, // continue spin + SPR2_CNT4, // continue "soooooooniiic!" tugging + SPR2_SIGN, // end sign head SPR2_LIFE, // life monitor icon - SPR2_XTRA, // stuff that isn't in-game - keep this last in the list + + SPR2_XTRA, // stuff that isn't in-map - "would this ever need an md2 or variable length animation?" SPR2_FIRSTFREESLOT, SPR2_LASTFREESLOT = 0x7f, From 0a69190848f196103840c5ba255a198144fcb439 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 9 Sep 2019 15:39:10 -0300 Subject: [PATCH 074/133] Missing arguments --- src/hardware/hw_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 07ae7ed2b..4a075d376 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3400,7 +3400,7 @@ static void HWR_AddPolyObjectPlanes(void) FBITFIELD blendmode; memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); - HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, po_ptrs[i], false, polyobjsector->floorheight, + HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], false, polyobjsector->floorheight, (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else @@ -3408,7 +3408,7 @@ static void HWR_AddPolyObjectPlanes(void) HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum); HWR_GetTextureFlat(levelflats[polyobjsector->floorpic].texturenum); HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, - (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } } @@ -3424,7 +3424,7 @@ static void HWR_AddPolyObjectPlanes(void) FBITFIELD blendmode; memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); - HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, po_ptrs[i], true, polyobjsector->ceilingheight, + HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], true, polyobjsector->ceilingheight, (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else @@ -3432,7 +3432,7 @@ static void HWR_AddPolyObjectPlanes(void) HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum); HWR_GetTextureFlat(levelflats[polyobjsector->ceilingpic].texturenum); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, - (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } } From 043bb86acdf81ef0ecbd388aed57fe0fa29c8747 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 9 Sep 2019 18:40:21 +0000 Subject: [PATCH 075/133] Revert "Merge branch 'flats-png_port' into 'master'" This reverts merge request !322 --- src/doomdef.h | 4 - src/hardware/hw_cache.c | 114 +---- src/hardware/hw_glide.h | 2 - src/hardware/hw_glob.h | 3 - src/hardware/hw_light.c | 2 - src/hardware/hw_main.c | 207 ++++----- src/hardware/hw_md2.c | 4 - src/p_setup.c | 10 - src/p_setup.h | 7 - src/p_spec.c | 30 +- src/r_data.c | 643 ++-------------------------- src/r_data.h | 27 +- src/r_draw.c | 2 - src/r_draw.h | 13 +- src/r_draw8.c | 913 +++++++++++----------------------------- src/r_plane.c | 450 +++++++++----------- src/r_plane.h | 2 - src/screen.c | 2 +- src/w_wad.c | 2 + 19 files changed, 582 insertions(+), 1855 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 4a0174369..6e7db2143 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -616,8 +616,4 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2CB itself ported this from PrBoom+ #define NEWCLIP -#ifndef HAVE_PNG -#define NO_PNG_LUMPS -#endif - #endif // __DOOMDEF__ diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index c9a75a4f3..6bc2c712e 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -30,7 +30,6 @@ #include "../z_zone.h" #include "../v_video.h" #include "../r_draw.h" -#include "../p_setup.h" //Hurdler: 25/04/2000: used for new colormap code in hardware mode //static UINT8 *gr_colormap = NULL; // by default it must be NULL ! (because colormap tables are not initialized) @@ -421,7 +420,6 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, GrTexInfo *grInfo) { -#ifdef GLIDE_API_COMPATIBILITY // Build the full textures from patches. static const GrLOD_t gr_lods[9] = { @@ -458,9 +456,6 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, INT32 j,k; INT32 max,min; -#else - (void)grInfo; -#endif // find a power of 2 width/height if (cv_grrounddown.value) @@ -516,7 +511,6 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, } else { -#ifdef GLIDE_API_COMPATIBILITY //size up to nearest power of 2 blockwidth = 1; while (blockwidth < originalwidth) @@ -534,14 +528,9 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, if (blockheight > 2048) blockheight = 2048; //I_Error("3D GenerateTexture : too big"); -#else - blockwidth = originalwidth; - blockheight = originalheight; -#endif } // do the boring LOD stuff.. blech! -#ifdef GLIDE_API_COMPATIBILITY if (blockwidth >= blockheight) { max = blockwidth; @@ -573,7 +562,6 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, if (blockwidth < blockheight) j += 4; grInfo->aspectRatioLog2 = gr_aspects[j].aspect; -#endif blocksize = blockwidth * blockheight; @@ -662,12 +650,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { - size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); -#ifndef NO_PNG_LUMPS - if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) - realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); -#endif HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, @@ -773,13 +756,11 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm static size_t gr_numtextures; static GLTexture_t *gr_textures; // for ALL Doom textures -static GLTexture_t *gr_textures2; void HWR_InitTextureCache(void) { gr_numtextures = 0; gr_textures = NULL; - gr_textures2 = NULL; } @@ -818,10 +799,7 @@ void HWR_FreeTextureCache(void) // texturecache info, we can free it if (gr_textures) free(gr_textures); - if (gr_textures2) - free(gr_textures2); gr_textures = NULL; - gr_textures2 = NULL; gr_numtextures = 0; } @@ -839,9 +817,6 @@ void HWR_PrepLevelCache(size_t pnumtextures) gr_textures = calloc(pnumtextures, sizeof (*gr_textures)); if (gr_textures == NULL) I_Error("3D can't alloc gr_textures"); - gr_textures2 = calloc(pnumtextures, sizeof (*gr_textures2)); - if (gr_textures2 == NULL) - I_Error("3D can't alloc gr_textures2"); } void HWR_SetPalette(RGBA_t *palette) @@ -872,7 +847,7 @@ GLTexture_t *HWR_GetTexture(INT32 tex) GLTexture_t *grtex; #ifdef PARANOIA if ((unsigned)tex >= gr_numtextures) - I_Error("HWR_GetTexture: tex >= numtextures\n"); + I_Error(" HWR_GetTexture: tex >= numtextures\n"); #endif grtex = &gr_textures[tex]; @@ -887,39 +862,15 @@ GLTexture_t *HWR_GetTexture(INT32 tex) return grtex; } -// HWR_RenderPlane and HWR_RenderPolyObjectPlane need this to get the flat dimensions from a patch. -lumpnum_t gr_patchflat; - -static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) -{ - UINT8 *flat; - patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC); - size_t lumplength = W_LumpLength(flatlumpnum); - -#ifndef NO_PNG_LUMPS - if (R_IsLumpPNG((UINT8 *)patch, lumplength)) - patch = R_PNGToPatch((UINT8 *)patch, lumplength); -#endif - - grMipmap->width = (UINT16)SHORT(patch->width); - grMipmap->height = (UINT16)SHORT(patch->height); - - flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data); - memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height); - - R_PatchToFlat(patch, flat); -} static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { size_t size, pflatsize; // setup the texture info -#ifdef GLIDE_API_COMPATIBILITY grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif grMipmap->grInfo.format = GR_TEXFMT_P_8; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; @@ -949,20 +900,15 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) pflatsize = 64; break; } + grMipmap->width = (UINT16)pflatsize; + grMipmap->height = (UINT16)pflatsize; - if (R_CheckIfPatch(flatlumpnum)) - HWR_LoadPatchFlat(grMipmap, flatlumpnum); - else - { - grMipmap->width = (UINT16)pflatsize; - grMipmap->height = (UINT16)pflatsize; - - // the flat raw data needn't be converted with palettized textures - W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), - PU_HWRCACHE, &grMipmap->grInfo.data)); - } + // the flat raw data needn't be converted with palettized textures + W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), + PU_HWRCACHE, &grMipmap->grInfo.data)); } + // Download a Doom 'flat' to the hardware cache and make it ready for use void HWR_GetFlat(lumpnum_t flatlumpnum) { @@ -977,52 +923,6 @@ void HWR_GetFlat(lumpnum_t flatlumpnum) // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); - - gr_patchflat = 0; - if (R_CheckIfPatch(flatlumpnum)) - gr_patchflat = flatlumpnum; -} - -static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) -{ - UINT8 *flat; - - // setup the texture info -#ifdef GLIDE_API_COMPATIBILITY - grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif - grMipmap->grInfo.format = GR_TEXFMT_P_8; - grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; - - grMipmap->width = (UINT16)textures[texturenum]->width; - grMipmap->height = (UINT16)textures[texturenum]->height; - - flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data); - memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height); - - R_TextureToFlat(texturenum, flat); -} - -void HWR_GetTextureFlat(INT32 texturenum) -{ - GLTexture_t *grtex; -#ifdef PARANOIA - if ((unsigned)texturenum >= gr_numtextures) - I_Error("HWR_GetTextureFlat: texturenum >= numtextures\n"); -#endif - if (texturenum == 0 || texturenum == -1) - return; - grtex = &gr_textures2[texturenum]; - - if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) - HWR_LoadTextureFlat(&grtex->mipmap, texturenum); - - HWD.pfnSetTexture(&grtex->mipmap); - - // The system-memory data can be purged now. - Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); } // diff --git a/src/hardware/hw_glide.h b/src/hardware/hw_glide.h index bf91229ef..2625d5864 100644 --- a/src/hardware/hw_glide.h +++ b/src/hardware/hw_glide.h @@ -59,11 +59,9 @@ typedef FxI32 GrTextureFormat_t; typedef struct { -#ifdef GLIDE_API_COMPATIBILITY GrLOD_t smallLodLog2; GrLOD_t largeLodLog2; GrAspectRatio_t aspectRatioLog2; -#endif GrTextureFormat_t format; void *data; } GrTexInfo; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index c7b06edfd..9656e54e9 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -101,7 +101,6 @@ void HWR_FreeTextureCache(void); void HWR_FreeExtraSubsectors(void); void HWR_GetFlat(lumpnum_t flatlumpnum); -void HWR_GetTextureFlat(INT32 texturenum); GLTexture_t *HWR_GetTexture(INT32 tex); void HWR_GetPatch(GLPatch_t *gpatch); void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap); @@ -115,8 +114,6 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum); // -------- // hw_draw.c // -------- -extern lumpnum_t gr_patchflat; - extern float gr_patch_scalex; extern float gr_patch_scaley; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 1de20cad7..edfe328b8 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1225,11 +1225,9 @@ static void HWR_SetLight(void) lightmappatch.height = 128; lightmappatch.mipmap.width = 128; lightmappatch.mipmap.height = 128; -#ifdef GLIDE_API_COMPATIBILITY lightmappatch.mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_128; lightmappatch.mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_128; lightmappatch.mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif lightmappatch.mipmap.flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw ! } HWD.pfnSetTexture(&lightmappatch.mipmap); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 07ae7ed2b..c6a8b16e5 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -70,9 +70,9 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); #endif #ifdef SORTING -void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, +void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, +void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); #else static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight, @@ -522,7 +522,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c // HWR_RenderPlane : Render a floor or ceiling convex polygon // -----------------+ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, - FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) + FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) { polyvertex_t * pv; float height; //constant y for all points on the convex flat polygon @@ -530,9 +530,8 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is INT32 nrPlaneVerts; //verts original define of convex flat polygon INT32 i; float flatxref,flatyref; - float fflatwidth, fflatheight; + float fflatsize; INT32 flatflag; - boolean texflat = true; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; @@ -541,7 +540,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is #ifdef ESLOPE pslope_t *slope = NULL; #endif - patch_t *patch; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; @@ -582,10 +580,9 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is if (nrPlaneVerts < 3) //not even a triangle ? return; - // This check is so inconsistent between functions, it hurts. - if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size + if (nrPlaneVerts > (INT32)UINT16_MAX) // FIXME: exceeds plVerts size { - CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, INT16_MAX); + CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX); return; } @@ -602,47 +599,38 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is switch (len) { case 4194304: // 2048x2048 lump - fflatwidth = fflatheight = 2048.0f; + fflatsize = 2048.0f; + flatflag = 2047; break; case 1048576: // 1024x1024 lump - fflatwidth = fflatheight = 1024.0f; + fflatsize = 1024.0f; + flatflag = 1023; break; case 262144:// 512x512 lump - fflatwidth = fflatheight = 512.0f; + fflatsize = 512.0f; + flatflag = 511; break; case 65536: // 256x256 lump - fflatwidth = fflatheight = 256.0f; + fflatsize = 256.0f; + flatflag = 255; break; case 16384: // 128x128 lump - fflatwidth = fflatheight = 128.0f; + fflatsize = 128.0f; + flatflag = 127; break; case 1024: // 32x32 lump - fflatwidth = fflatheight = 32.0f; + fflatsize = 32.0f; + flatflag = 31; break; default: // 64x64 lump - fflatwidth = fflatheight = 64.0f; + fflatsize = 64.0f; + flatflag = 63; break; } - flatflag = ((INT32)fflatwidth)-1; - - if (texturenum != 0 && texturenum != -1) - { - fflatwidth = textures[texturenum]->width; - fflatheight = textures[texturenum]->height; - } - else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? - { - patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); - fflatwidth = SHORT(patch->width); - fflatheight = SHORT(patch->height); - } - else - texflat = false; - // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth); - flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatheight); + flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatsize); + flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatsize); // transform v3d = planeVerts; @@ -651,14 +639,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; angle = FOFsector->floorpic_angle; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; angle = FOFsector->ceilingpic_angle; } } @@ -666,14 +654,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; angle = gr_frontsector->floorpic_angle; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; angle = gr_frontsector->ceilingpic_angle; } } @@ -692,24 +680,17 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) { // Hurdler: add scrolling texture on floor/ceiling - if (texflat) - { - v3d->sow = (float)(pv->x / fflatwidth) + scrollx; - v3d->tow = -(float)(pv->y / fflatheight) + scrolly; - } - else - { - v3d->sow = (float)((pv->x / fflatwidth) - flatxref + scrollx); - v3d->tow = (float)(flatyref - (pv->y / fflatheight) + scrolly); - } + v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx); + v3d->tow = (float)(-(pv->y / fflatsize) + flatyref + scrolly); + + //v3d->sow = (float)(pv->x / fflatsize); + //v3d->tow = (float)(pv->y / fflatsize); // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { tempxsow = FLOAT_TO_FIXED(v3d->sow); tempytow = FLOAT_TO_FIXED(v3d->tow); - if (texflat) - tempytow = -tempytow; v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); } @@ -3183,23 +3164,21 @@ static inline void HWR_AddPolyObjectSegs(void) #ifdef POLYOBJECTS_PLANES static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, - FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, + FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) { float height; //constant y for all points on the convex flat polygon FOutVector *v3d; INT32 i; float flatxref,flatyref; - float fflatwidth, fflatheight; + float fflatsize; INT32 flatflag; - boolean texflat = true; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; FSurfaceInfo Surf; fixed_t tempxsow, tempytow; size_t nrPlaneVerts; - patch_t *patch; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; @@ -3230,47 +3209,38 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, switch (len) { case 4194304: // 2048x2048 lump - fflatwidth = fflatheight = 2048.0f; + fflatsize = 2048.0f; + flatflag = 2047; break; case 1048576: // 1024x1024 lump - fflatwidth = fflatheight = 1024.0f; + fflatsize = 1024.0f; + flatflag = 1023; break; case 262144:// 512x512 lump - fflatwidth = fflatheight = 512.0f; + fflatsize = 512.0f; + flatflag = 511; break; case 65536: // 256x256 lump - fflatwidth = fflatheight = 256.0f; + fflatsize = 256.0f; + flatflag = 255; break; case 16384: // 128x128 lump - fflatwidth = fflatheight = 128.0f; + fflatsize = 128.0f; + flatflag = 127; break; case 1024: // 32x32 lump - fflatwidth = fflatheight = 32.0f; + fflatsize = 32.0f; + flatflag = 31; break; default: // 64x64 lump - fflatwidth = fflatheight = 64.0f; + fflatsize = 64.0f; + flatflag = 63; break; } - flatflag = ((INT32)fflatwidth)-1; - - if (texturenum != 0 && texturenum != -1) - { - fflatwidth = textures[texturenum]->width; - fflatheight = textures[texturenum]->height; - } - else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? - { - patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); - fflatwidth = SHORT(patch->width); - fflatheight = SHORT(patch->height); - } - else - texflat = false; - // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth); - flatyref = (float)((polysector->origVerts[0].y & (~flatflag)) / fflatheight); + flatxref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].x) & (~flatflag)) / fflatsize); + flatyref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].y) & (~flatflag)) / fflatsize); // transform v3d = planeVerts; @@ -3279,14 +3249,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT; } } @@ -3294,14 +3264,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT; } } @@ -3324,26 +3294,15 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++) { - // Go from the polysector's original vertex locations - // Means the flat is offset based on the original vertex locations - if (texflat) - { - v3d->sow = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx; - v3d->tow = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly; - } - else - { - v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx); - v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly); - } + // Hurdler: add scrolling texture on floor/ceiling + v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatsize) - flatxref + scrollx); // Go from the polysector's original vertex locations + v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatsize) + scrolly); // Means the flat is offset based on the original vertex locations // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { tempxsow = FLOAT_TO_FIXED(v3d->sow); tempytow = FLOAT_TO_FIXED(v3d->tow); - if (texflat) - tempytow = -tempytow; v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle)))); } @@ -3406,7 +3365,6 @@ static void HWR_AddPolyObjectPlanes(void) else { HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum); - HWR_GetTextureFlat(levelflats[polyobjsector->floorpic].texturenum); HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); @@ -3430,7 +3388,6 @@ static void HWR_AddPolyObjectPlanes(void) else { HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum); - HWR_GetTextureFlat(levelflats[polyobjsector->ceilingpic].texturenum); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); @@ -3584,12 +3541,11 @@ static void HWR_Subsector(size_t num) if (sub->validcount != validcount) { HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum); - HWR_GetTextureFlat(levelflats[gr_frontsector->floorpic].texturenum); HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false, // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, levelflats[gr_frontsector->floorpic].texturenum, NULL, 255, false, floorcolormap); + PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap); } } else @@ -3607,12 +3563,11 @@ static void HWR_Subsector(size_t num) if (sub->validcount != validcount) { HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum); - HWR_GetTextureFlat(levelflats[gr_frontsector->ceilingpic].texturenum); HWR_RenderPlane(NULL, &extrasubsectors[num], true, // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum, levelflats[gr_frontsector->ceilingpic].texturenum, NULL, 255, false, ceilingcolormap); + PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap); } } else @@ -3671,7 +3626,7 @@ static void HWR_Subsector(size_t num) else alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - HWR_AddTransparentFloor(0, 0, + HWR_AddTransparentFloor(0, &extrasubsectors[num], false, *rover->bottomheight, @@ -3690,7 +3645,6 @@ static void HWR_Subsector(size_t num) rover->alpha-1, rover->master->frontsector); #else HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum, - levelflats[*rover->bottompic].texturenum, &extrasubsectors[num], false, *rover->bottomheight, @@ -3702,9 +3656,8 @@ static void HWR_Subsector(size_t num) else { HWR_GetFlat(levelflats[*rover->bottompic].lumpnum); - HWR_GetTextureFlat(levelflats[*rover->bottompic].texturenum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, levelflats[*rover->bottompic].texturenum, + HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -3736,7 +3689,7 @@ static void HWR_Subsector(size_t num) else alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - HWR_AddTransparentFloor(0, 0, + HWR_AddTransparentFloor(0, &extrasubsectors[num], true, *rover->topheight, @@ -3755,7 +3708,6 @@ static void HWR_Subsector(size_t num) rover->alpha-1, rover->master->frontsector); #else HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum, - levelflats[*rover->bottompic].texturenum, &extrasubsectors[num], true, *rover->topheight, @@ -3768,9 +3720,8 @@ static void HWR_Subsector(size_t num) else { HWR_GetFlat(levelflats[*rover->toppic].lumpnum); - HWR_GetTextureFlat(levelflats[*rover->toppic].texturenum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, levelflats[*rover->toppic].texturenum, + HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -5099,7 +5050,6 @@ typedef struct fixed_t fixedheight; INT32 lightlevel; lumpnum_t lumpnum; - INT32 texturenum; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -5118,7 +5068,6 @@ typedef struct fixed_t fixedheight; INT32 lightlevel; lumpnum_t lumpnum; - INT32 texturenum; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -5149,7 +5098,7 @@ static INT32 drawcount = 0; #define MAX_TRANSPARENTFLOOR 512 // This will likely turn into a copy of HWR_Add3DWater and replace it. -void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, +void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) { static size_t allocedplanes = 0; @@ -5168,7 +5117,6 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector planeinfo[numplanes].fixedheight = fixedheight; planeinfo[numplanes].lightlevel = lightlevel; planeinfo[numplanes].lumpnum = lumpnum; - planeinfo[numplanes].texturenum = texturenum; planeinfo[numplanes].xsub = xsub; planeinfo[numplanes].alpha = alpha; planeinfo[numplanes].FOFSector = FOFSector; @@ -5182,7 +5130,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector // Adding this for now until I can create extrasubsector info for polyobjects // When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, +void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) { static size_t allocedpolyplanes = 0; @@ -5201,7 +5149,6 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, poly polyplaneinfo[numpolyplanes].fixedheight = fixedheight; polyplaneinfo[numpolyplanes].lightlevel = lightlevel; polyplaneinfo[numpolyplanes].lumpnum = lumpnum; - polyplaneinfo[numpolyplanes].texturenum = texturenum; polyplaneinfo[numpolyplanes].polysector = polysector; polyplaneinfo[numpolyplanes].alpha = alpha; polyplaneinfo[numpolyplanes].FOFSector = FOFSector; @@ -5363,12 +5310,9 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) - { HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum); - HWR_GetTextureFlat(sortnode[sortindex[i]].plane->texturenum); - } HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, - sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->texturenum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); + sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); } else if (sortnode[sortindex[i]].polyplane) { @@ -5376,12 +5320,9 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture)) - { HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum); - HWR_GetTextureFlat(sortnode[sortindex[i]].polyplane->texturenum); - } HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, - sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->texturenum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); + sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); } else if (sortnode[sortindex[i]].wall) { diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 7b6367cf3..d4728315a 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -747,12 +747,10 @@ static void md2_loadTexture(md2_t *model) grpatch->mipmap.width = (UINT16)w; grpatch->mipmap.height = (UINT16)h; -#ifdef GLIDE_API_COMPATIBILITY // not correct! grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif } HWD.pfnSetTexture(&grpatch->mipmap); HWR_UnlockCachedPatch(grpatch); @@ -800,12 +798,10 @@ static void md2_loadBlendTexture(md2_t *model) grpatch->mipmap.width = (UINT16)w; grpatch->mipmap.height = (UINT16)h; -#ifdef GLIDE_API_COMPATIBILITY // not correct! grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif } HWD.pfnSetTexture(&grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary HWR_UnlockCachedPatch(grpatch); diff --git a/src/p_setup.c b/src/p_setup.c index 60e036a87..65335be3f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -573,11 +573,6 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) // store the flat lump number levelflat->lumpnum = R_GetFlatNumForName(flatname); - 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); @@ -622,11 +617,6 @@ INT32 P_AddLevelFlatRuntime(const char *flatname) // store the flat lump number levelflat->lumpnum = R_GetFlatNumForName(flatname); - 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 7e3a149eb..7e8a5d7e6 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -37,19 +37,12 @@ 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; - - // for patchflats - UINT8 *flatpatch; } levelflat_t; extern size_t numlevelflats; diff --git a/src/p_spec.c b/src/p_spec.c index 256ca3453..7742554cd 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -205,8 +205,8 @@ void P_InitPicAnims(void) if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR) continue; - lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname); - lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname); + lastanim->picnum = R_FlatNumForName(animdefs[i].endname); + lastanim->basepic = R_FlatNumForName(animdefs[i].startname); } lastanim->istexture = animdefs[i].istexture; @@ -464,19 +464,7 @@ static inline void P_FindAnimatedFlat(INT32 animnum) for (i = 0; i < numlevelflats; i++, foundflats++) { // is that levelflat from the flat anim sequence ? - 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) + if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum) { foundflats->baselumpnum = startflatnum; foundflats->animseq = foundflats->lumpnum - startflatnum; @@ -500,7 +488,10 @@ void P_SetupLevelFlatAnims(void) // the original game flat anim sequences for (i = 0; anims[i].istexture != -1; i++) - P_FindAnimatedFlat(i); + { + if (!anims[i].istexture) + P_FindAnimatedFlat(i); + } } // @@ -5678,12 +5669,9 @@ 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 - else if (foundflats->baselumpnum != LUMPERROR) - foundflats->lumpnum = foundflats->baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); + foundflats->lumpnum = foundflats->baselumpnum + + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); } } } diff --git a/src/r_data.c b/src/r_data.c index 5858117a5..6889bddde 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -40,28 +40,6 @@ #include #endif -#ifdef HAVE_PNG - -#ifndef _MSC_VER -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE -#endif -#endif - -#ifndef _LFS64_LARGEFILE -#define _LFS64_LARGEFILE -#endif - -#ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 0 -#endif - -#include "png.h" -#ifndef PNG_READ_SUPPORTED -#undef HAVE_PNG -#endif -#endif - // // Texture definition. // Each texture is composed of one or more patches, @@ -120,11 +98,12 @@ 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 -INT32 *texturewidth; +// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask +INT32 *texturewidthmask; + fixed_t *textureheight; // needed for texture pegging INT32 *texturetranslation; @@ -336,7 +315,7 @@ static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache // Allocate space for full size texture, either single patch or 'composite' // Build the full textures from patches. // The texture caching system is a little more hungry of memory, but has -// been simplified for the sake of highcolor (lol), dynamic ligthing, & speed. +// been simplified for the sake of highcolor, dynamic ligthing, & speed. // // This is not optimised, but it's supposed to be executed only once // per level, when enough memory is available. @@ -353,10 +332,6 @@ static UINT8 *R_GenerateTexture(size_t texnum) column_t *patchcol; UINT32 *colofs; - UINT16 wadnum; - lumpnum_t lumpnum; - size_t lumplength; - I_Assert(texnum <= (size_t)numtextures); texture = textures[texnum]; I_Assert(texture != NULL); @@ -371,19 +346,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) { boolean holey = false; patch = texture->patches; - - wadnum = patch->wad; - lumpnum = patch->lump; - lumplength = W_LumpLengthPwad(wadnum, lumpnum); - realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); - -#ifndef NO_PNG_LUMPS - if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) - { - realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); - goto multipatch; - } -#endif + realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) @@ -413,7 +376,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) { texture->holes = true; texture->flip = patch->flip; - blocksize = lumplength; + blocksize = W_LumpLengthPwad(patch->wad, patch->lump); block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function &texturecache[texnum]); M_Memcpy(block, realpatch, blocksize); @@ -440,9 +403,6 @@ static UINT8 *R_GenerateTexture(size_t texnum) } // multi-patch textures (or 'composite') -#ifndef NO_PNG_LUMPS - multipatch: -#endif texture->holes = false; texture->flip = 0; blocksize = (texture->width * 4) + (texture->width * texture->height); @@ -473,15 +433,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) ColumnDrawerPointer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache; } - wadnum = patch->wad; - lumpnum = patch->lump; - lumplength = W_LumpLengthPwad(wadnum, lumpnum); - realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); -#ifndef NO_PNG_LUMPS - if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) - realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); -#endif - + realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); x1 = patch->originx; width = SHORT(realpatch->width); height = SHORT(realpatch->height); @@ -557,14 +509,10 @@ void R_CheckTextureCache(INT32 tex) UINT8 *R_GetColumn(fixed_t tex, INT32 col) { UINT8 *data; - INT32 width = texturewidth[tex]; - - if (width & (width - 1)) - col = (UINT32)col % width; - else - col &= (width - 1); + col &= texturewidthmask[tex]; data = texturecache[tex]; + if (!data) data = R_GenerateTexture(tex); @@ -602,7 +550,7 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index); #define TX_END "TX_END" void R_LoadTextures(void) { - INT32 i, w; + INT32 i, k, w; UINT16 j; UINT16 texstart, texend, texturesLumpPos; patch_t *patchlump; @@ -619,7 +567,6 @@ void R_LoadTextures(void) } Z_Free(texturetranslation); Z_Free(textures); - Z_Free(texflats); } // Load patches and textures. @@ -680,16 +627,15 @@ 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 *))); // Allocate texture referencing cache. - texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); - // Allocate texture width table. - texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); - // Allocate texture height table. - textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); + texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); + // Allocate texture width mask table. + texturewidthmask = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); + // Allocate texture height mask table. + textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); // Create translation table for global animation. texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); @@ -727,39 +673,20 @@ void R_LoadTextures(void) // Work through each lump between the markers in the WAD. for (j = 0; j < (texend - texstart); j++) { - UINT16 wadnum = (UINT16)w; - lumpnum_t lumpnum = texstart + j; - size_t lumplength; - if (wadfiles[w]->type == RET_PK3) { - if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder + if (W_IsLumpFolder((UINT16)w, texstart + j)) // Check if lump is a folder continue; // If it is then SKIP IT } - - lumplength = W_LumpLengthPwad(wadnum, lumpnum); - patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE); //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); // Set texture properties. - M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); - -#ifndef NO_PNG_LUMPS - if (R_IsLumpPNG((UINT8 *)patchlump, lumplength)) - { - INT16 width, height; - R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength); - texture->width = width; - texture->height = height; - } - else -#endif - { - texture->width = SHORT(patchlump->width); - texture->height = SHORT(patchlump->height); - } + M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name)); + texture->width = SHORT(patchlump->width); + texture->height = SHORT(patchlump->height); texture->patchcount = 1; texture->holes = false; texture->flip = 0; @@ -774,7 +701,11 @@ void R_LoadTextures(void) Z_Unlock(patchlump); - texturewidth[i] = texture->width; + k = 1; + while (k << 1 <= texture->width) + k <<= 1; + + texturewidthmask[i] = k - 1; textureheight[i] = texture->height << FRACBITS; i++; } @@ -1166,7 +1097,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) texturesToken = M_GetToken(texturesText); while (texturesToken != NULL) { - if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0) + if (stricmp(texturesToken, "WALLTEXTURE")==0) { numTexturesInLump++; Z_Free(texturesToken); @@ -1174,7 +1105,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) } else { - I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken); + I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); } texturesToken = M_GetToken(NULL); } @@ -1215,21 +1146,21 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) texturesToken = M_GetToken(texturesText); while (texturesToken != NULL) { - if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0) + if (stricmp(texturesToken, "WALLTEXTURE")==0) { Z_Free(texturesToken); // Get the new texture newTexture = R_ParseTexture(true); // Store the new texture textures[*texindex] = newTexture; - texturewidth[*texindex] = newTexture->width; + texturewidthmask[*texindex] = newTexture->width - 1; textureheight[*texindex] = newTexture->height << FRACBITS; // Increment i back in R_LoadTextures() (*texindex)++; } else { - I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken); + I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); } texturesToken = M_GetToken(NULL); } @@ -1336,41 +1267,6 @@ lumpnum_t R_GetFlatNumForName(const char *name) lump = LUMPERROR; } - // Detect textures - if (lump == LUMPERROR) - { - // Scan wad files backwards so patched textures take preference. - for (i = numwadfiles - 1; i >= 0; i--) - { - switch (wadfiles[i]->type) - { - case RET_WAD: - if ((start = W_CheckNumForNamePwad("TX_START", (UINT16)i, 0)) == INT16_MAX) - continue; - if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX) - continue; - break; - case RET_PK3: - if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX) - continue; - if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX) - continue; - break; - default: - continue; - } - - // Now find lump with specified name in that range. - lump = W_CheckNumForNamePwad(name, (UINT16)i, start); - if (lump < end) - { - lump += (i<<16); // found it, in our constraints - break; - } - lump = LUMPERROR; - } - } - if (lump == LUMPERROR) { if (strcmp(name, SKYFLATNAME)) @@ -1719,6 +1615,7 @@ extracolormap_t *R_ColormapForName(char *name) // static double deltas[256][3], map[256][3]; +static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); static int RoundUp(double number); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) @@ -2130,7 +2027,7 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex // Thanks to quake2 source! // utils3/qdata/images.c -UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) +static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) { int dr, dg, db; int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i; @@ -2409,479 +2306,3 @@ void R_PrecacheLevel(void) "texturememory: %s k\n" "spritememory: %s k\n", sizeu1(flatmemory>>10), sizeu2(texturememory>>10), sizeu3(spritememory>>10)); } - -// https://github.com/coelckers/prboom-plus/blob/master/prboom2/src/r_patch.c#L350 -boolean R_CheckIfPatch(lumpnum_t lump) -{ - size_t size; - INT16 width, height; - patch_t *patch; - boolean result; - - size = W_LumpLength(lump); - - // minimum length of a valid Doom patch - if (size < 13) - return false; - - patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC); - - width = SHORT(patch->width); - height = SHORT(patch->height); - - result = (height > 0 && height <= 16384 && width > 0 && width <= 16384 && width < (INT16)(size / 4)); - - if (result) - { - // The dimensions seem like they might be valid for a patch, so - // check the column directory for extra security. All columns - // must begin after the column directory, and none of them must - // point past the end of the patch. - INT16 x; - - for (x = 0; x < width; x++) - { - UINT32 ofs = LONG(patch->columnofs[x]); - - // Need one byte for an empty column (but there's patches that don't know that!) - if (ofs < (UINT32)width * 4 + 8 || ofs >= (UINT32)size) - { - result = false; - break; - } - } - } - - return result; -} - -void R_PatchToFlat(patch_t *patch, UINT8 *flat) -{ - fixed_t col, ofs; - column_t *column; - UINT8 *desttop, *dest, *deststop; - UINT8 *source; - - desttop = flat; - deststop = desttop + (SHORT(patch->width) * SHORT(patch->height)); - - for (col = 0; col < SHORT(patch->width); col++, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[col])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - - dest = desttop + (topdelta * SHORT(patch->width)); - source = (UINT8 *)(column) + 3; - for (ofs = 0; dest < deststop && ofs < column->length; ofs++) - { - *dest = source[ofs]; - dest += SHORT(patch->width); - } - column = (column_t *)((UINT8 *)column + column->length + 4); - } - } -} - -#ifndef NO_PNG_LUMPS -boolean R_IsLumpPNG(UINT8 *d, size_t s) -{ - if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/ - return false; - // Check for PNG file signature using memcmp - // As it may be faster on CPUs with slow unaligned memory access - // Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature - return (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0); -} - -#ifdef HAVE_PNG -typedef struct { - png_bytep buffer; - png_uint_32 bufsize; - png_uint_32 current_pos; -} png_ioread; - -static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_ioread *f = png_get_io_ptr(png_ptr); - if (length > (f->bufsize - f->current_pos)) - png_error(png_ptr, "PNG_IOReader: buffer overrun"); - memcpy(data, f->buffer + f->current_pos, length); - f->current_pos += length; -} - -static void PNG_error(png_structp PNG, png_const_charp pngtext) -{ - CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext); - //I_Error("libpng error at %p: %s", PNG, pngtext); -} - -static void PNG_warn(png_structp PNG, png_const_charp pngtext) -{ - CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext); -} - -static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) -{ - png_structp png_ptr; - png_infop png_info_ptr; - png_uint_32 width, height; - int bit_depth, color_type; - png_uint_32 y; -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - jmp_buf jmpbuf; -#endif -#endif - - png_ioread png_io; - png_bytep *row_pointers; - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, - PNG_error, PNG_warn); - if (!png_ptr) - { - CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n"); - return NULL; - } - - png_info_ptr = png_create_info_struct(png_ptr); - if (!png_info_ptr) - { - CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n"); - png_destroy_read_struct(&png_ptr, NULL, NULL); - return NULL; - } - -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) -#else - if (setjmp(png_jmpbuf(png_ptr))) -#endif - { - //CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename); - png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); - return NULL; - } -#ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); -#endif - - // set our own read_function - png_io.buffer = (png_bytep)png; - png_io.bufsize = size; - png_io.current_pos = 0; - png_set_read_fn(png_ptr, &png_io, PNG_IOReader); - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_set_user_limits(png_ptr, 2048, 2048); -#endif - - png_read_info(png_ptr, png_info_ptr); - - png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type, - NULL, NULL, NULL); - - if (bit_depth == 16) - png_set_strip_16(png_ptr); - - if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png_ptr); - else if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_palette_to_rgb(png_ptr); - - if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS)) - png_set_tRNS_to_alpha(png_ptr); - else if (color_type != PNG_COLOR_TYPE_RGB_ALPHA && color_type != PNG_COLOR_TYPE_GRAY_ALPHA) - { -#if PNG_LIBPNG_VER < 10207 - png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); -#else - png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER); -#endif - } - - png_read_update_info(png_ptr, png_info_ptr); - - // Read the image - row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); - for (y = 0; y < height; y++) - row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, png_info_ptr)); - png_read_image(png_ptr, row_pointers); - png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); - - *w = (INT32)width; - *h = (INT32)height; - return row_pointers; -} - -// Convert a PNG to a raw image. -static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) -{ - UINT8 *flat; - png_uint_32 x, y; - png_bytep *row_pointers = PNG_Read(png, w, h, size); - png_uint_32 width = *w, height = *h; - - if (!row_pointers) - I_Error("PNG_RawConvert: conversion failed"); - - // Convert the image to 8bpp - flat = Z_Malloc(width * height, PU_LEVEL, NULL); - memset(flat, TRANSPARENTPIXEL, width * height); - for (y = 0; y < height; y++) - { - png_bytep row = row_pointers[y]; - for (x = 0; x < width; x++) - { - png_bytep px = &(row[x * 4]); - if ((UINT8)px[3]) - flat[((y * width) + x)] = NearestColor((UINT8)px[0], (UINT8)px[1], (UINT8)px[2]); - } - } - free(row_pointers); - - return flat; -} - -// Convert a PNG to a flat. -UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size) -{ - return PNG_RawConvert(png, &levelflat->width, &levelflat->height, size); -} - -// Convert a PNG to a patch. -static unsigned char imgbuf[1<<26]; -patch_t *R_PNGToPatch(UINT8 *png, size_t size) -{ - UINT16 width, height; - UINT8 *raw = PNG_RawConvert(png, &width, &height, size); - - UINT32 x, y; - UINT8 *img; - UINT8 *imgptr = imgbuf; - UINT8 *colpointers, *startofspan; - - #define WRITE8(buf, a) ({*buf = (a); buf++;}) - #define WRITE16(buf, a) ({*buf = (a)&255; buf++; *buf = (a)>>8; buf++;}) - #define WRITE32(buf, a) ({WRITE16(buf, (a)&65535); WRITE16(buf, (a)>>16);}) - - if (!raw) - I_Error("R_PNGToPatch: conversion failed"); - - // Write image size and offset - WRITE16(imgptr, width); - WRITE16(imgptr, height); - // no offsets - WRITE16(imgptr, 0); - WRITE16(imgptr, 0); - - // Leave placeholder to column pointers - colpointers = imgptr; - imgptr += width*4; - - // Write columns - for (x = 0; x < width; x++) - { - int lastStartY = 0; - int spanSize = 0; - startofspan = NULL; - - //printf("%d ", x); - // Write column pointer (@TODO may be wrong) - WRITE32(colpointers, imgptr - imgbuf); - - // Write pixels - for (y = 0; y < height; y++) - { - UINT8 paletteIndex = raw[((y * width) + x)]; - - // Start new column if we need to - if (!startofspan || spanSize == 255) - { - int writeY = y; - - // If we reached the span size limit, finish the previous span - if (startofspan) - WRITE8(imgptr, 0); - - if (y > 254) - { - // Make sure we're aligned to 254 - if (lastStartY < 254) - { - WRITE8(imgptr, 254); - WRITE8(imgptr, 0); - imgptr += 2; - lastStartY = 254; - } - - // Write stopgap empty spans if needed - writeY = y - lastStartY; - - while (writeY > 254) - { - WRITE8(imgptr, 254); - WRITE8(imgptr, 0); - imgptr += 2; - writeY -= 254; - } - } - - startofspan = imgptr; - WRITE8(imgptr, writeY);///@TODO calculate starting y pos - imgptr += 2; - spanSize = 0; - - lastStartY = y; - } - - // Write the pixel - WRITE8(imgptr, paletteIndex); - spanSize++; - startofspan[1] = spanSize; - } - - if (startofspan) - WRITE8(imgptr, 0); - - WRITE8(imgptr, 0xFF); - } - - #undef WRITE8 - #undef WRITE16 - #undef WRITE32 - - size = imgptr-imgbuf; - img = malloc(size); - memcpy(img, imgbuf, size); - - Z_Free(raw); - - return (patch_t *)img; -} - -boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size) -{ - png_structp png_ptr; - png_infop png_info_ptr; - png_uint_32 w, h; - int bit_depth, color_type; -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - jmp_buf jmpbuf; -#endif -#endif - - png_ioread png_io; - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, - PNG_error, PNG_warn); - if (!png_ptr) - { - CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n"); - return false; - } - - png_info_ptr = png_create_info_struct(png_ptr); - if (!png_info_ptr) - { - CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n"); - png_destroy_read_struct(&png_ptr, NULL, NULL); - return false; - } - -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) -#else - if (setjmp(png_jmpbuf(png_ptr))) -#endif - { - //CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename); - png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); - return false; - } -#ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); -#endif - - // set our own read_function - png_io.buffer = (png_bytep)png; - png_io.bufsize = size; - png_io.current_pos = 0; - png_set_read_fn(png_ptr, &png_io, PNG_IOReader); - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_set_user_limits(png_ptr, 2048, 2048); -#endif - - png_read_info(png_ptr, png_info_ptr); - - png_get_IHDR(png_ptr, png_info_ptr, &w, &h, &bit_depth, &color_type, - NULL, NULL, NULL); - - // okay done. stop. - png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); - - *width = (INT32)w; - *height = (INT32)h; - return true; -} -#endif -#endif - -void R_TextureToFlat(size_t tex, UINT8 *flat) -{ - texture_t *texture = textures[tex]; - - fixed_t col, ofs; - column_t *column; - UINT8 *desttop, *dest, *deststop; - UINT8 *source; - - desttop = flat; - deststop = desttop + (texture->width * texture->height); - - for (col = 0; col < texture->width; col++, desttop++) - { - column = (column_t *)R_GetColumn(tex, col); - if (!texture->holes) - { - dest = desttop; - source = (UINT8 *)(column); - for (ofs = 0; dest < deststop && ofs < texture->height; ofs++) - { - if (source[ofs] != TRANSPARENTPIXEL) - *dest = source[ofs]; - dest += texture->width; - } - } - else - { - INT32 topdelta, prevdelta = -1; - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - - dest = desttop + (topdelta * texture->width); - source = (UINT8 *)(column) + 3; - for (ofs = 0; dest < deststop && ofs < column->length; ofs++) - { - if (source[ofs] != TRANSPARENTPIXEL) - *dest = source[ofs]; - dest += texture->width; - } - column = (column_t *)((UINT8 *)column + column->length + 4); - } - } - } -} diff --git a/src/r_data.h b/src/r_data.h index b29bf4557..b6b0a16a1 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -16,7 +16,6 @@ #include "r_defs.h" #include "r_state.h" -#include "p_setup.h" // levelflats #ifdef __GNUG__ #pragma interface @@ -56,17 +55,12 @@ typedef struct texpatch_t patches[0]; } texture_t; -typedef struct -{ - UINT8 *flat; - INT16 width, height; -} textureflat_t; - // all loaded and prepared textures from the start of the game extern texture_t **textures; -extern textureflat_t *texflats; -extern INT32 *texturewidth; +// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask +extern INT32 *texturewidthmask; + extern fixed_t *textureheight; // needed for texture pegging extern INT16 color8to16[256]; // remap color index to highcolor @@ -94,6 +88,7 @@ void R_PrecacheLevel(void); // Floor/ceiling opaque texture tiles, // lookup by name. For animation? lumpnum_t R_GetFlatNumForName(const char *name); +#define R_FlatNumForName(x) R_GetFlatNumForName(x) // Called by P_Ticker for switches and animations, // returns the texture number for the texture name. @@ -153,20 +148,6 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap); #define R_PutRgbaRGB(r, g, b) (R_PutRgbaR(r) + R_PutRgbaG(g) + R_PutRgbaB(b)) #define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a)) -boolean R_CheckIfPatch(lumpnum_t lump); -UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); - -void R_PatchToFlat(patch_t *patch, UINT8 *flat); -void R_TextureToFlat(size_t tex, UINT8 *flat); - -#ifndef NO_PNG_LUMPS -boolean R_IsLumpPNG(UINT8 *d, size_t s); - -UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size); -patch_t *R_PNGToPatch(UINT8 *png, size_t size); -boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size); -#endif - extern INT32 numtextures; #endif diff --git a/src/r_draw.c b/src/r_draw.c index 1754403c4..396ed0344 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -99,8 +99,6 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight; INT32 ds_y, ds_x1, ds_x2; lighttable_t *ds_colormap; fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; -UINT16 ds_flatwidth, ds_flatheight; -boolean ds_powersoftwo; UINT8 *ds_source; // start of a 64*64 tile image UINT8 *ds_transmap; // one of the translucency tables diff --git a/src/r_draw.h b/src/r_draw.h index 3c1429722..82498eb11 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -57,9 +57,7 @@ extern INT32 dc_texheight; extern INT32 ds_y, ds_x1, ds_x2; extern lighttable_t *ds_colormap; extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; -extern UINT16 ds_flatwidth, ds_flatheight; -extern boolean ds_powersoftwo; -extern UINT8 *ds_source; +extern UINT8 *ds_source; // start of a 64*64 tile image extern UINT8 *ds_transmap; #ifdef ESLOPE @@ -130,8 +128,6 @@ void R_FillBackScreen(void); void R_DrawViewBorder(void); #endif -#define TRANSPARENTPIXEL 255 - // ----------------- // 8bpp DRAWING CODE // ----------------- @@ -173,13 +169,6 @@ void R_DrawFogSpan_8(void); void R_DrawFogColumn_8(void); void R_DrawColumnShadowed_8(void); -#ifndef NOWATER -void R_DrawTranslucentWaterSpan_8(void); - -extern INT32 ds_bgofs; -extern INT32 ds_waterofs; -#endif - // ------------------ // 16bpp DRAWING CODE // ------------------ diff --git a/src/r_draw8.c b/src/r_draw8.c index 77406f83c..8a2d37fb3 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -105,6 +105,8 @@ void R_DrawColumn_8(void) } } +#define TRANSPARENTPIXEL 255 + void R_Draw2sMultiPatchColumn_8(void) { INT32 count; @@ -541,19 +543,16 @@ void R_DrawTranslatedColumn_8(void) */ void R_DrawSpan_8 (void) { - fixed_t xposition; - fixed_t yposition; - fixed_t xstep, ystep; + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count = (ds_x2 - ds_x1 + 1); - - xposition = ds_xfrac; yposition = ds_yfrac; - xstep = ds_xstep; ystep = ds_ystep; + size_t count; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -562,88 +561,62 @@ void R_DrawSpan_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - if (ds_powersoftwo) - { - xposition <<= nflatshiftup; yposition <<= nflatshiftup; - xstep <<= nflatshiftup; ystep <<= nflatshiftup; - } + xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; + xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1 + 1; if (dest+8 > deststop) return; - if (!ds_powersoftwo) + while (count >= 8) { - while (count-- && dest <= deststop) - { - fixed_t x = (xposition >> FRACBITS); - fixed_t y = (yposition >> FRACBITS); + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + dest[0] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + dest[1] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; - x %= ds_flatwidth; - y %= ds_flatheight; + dest[2] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; - *dest++ = colormap[source[((y * ds_flatwidth) + x)]]; - xposition += xstep; - yposition += ystep; - } + dest[3] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[4] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[5] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[6] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[7] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; } - else + while (count-- && dest <= deststop) { - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[1] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[2] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[3] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count-- && dest <= deststop) - { - *dest++ = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - } + *dest++ = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; } } @@ -724,24 +697,7 @@ void R_DrawTiltedSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - *dest = colormap[source[((y * ds_flatwidth) + x)]]; - } - else - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; iz += ds_sz.x; uz += ds_su.x; @@ -778,24 +734,7 @@ void R_DrawTiltedSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - *dest = colormap[source[((y * ds_flatwidth) + x)]]; - } - else - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; u += stepu; v += stepv; @@ -811,24 +750,7 @@ void R_DrawTiltedSpan_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - *dest = colormap[source[((y * ds_flatwidth) + x)]]; - } - else - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; } else { @@ -849,24 +771,7 @@ void R_DrawTiltedSpan_8(void) for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - *dest = colormap[source[((y * ds_flatwidth) + x)]]; - } - else - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; u += stepu; v += stepv; @@ -927,24 +832,7 @@ void R_DrawTiltedTranslucentSpan_8(void) v = (INT64)(vz*z) + viewy; colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); - } - else - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; iz += ds_sz.x; uz += ds_su.x; @@ -981,24 +869,7 @@ void R_DrawTiltedTranslucentSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); - } - else - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; u += stepu; v += stepv; @@ -1014,24 +885,7 @@ void R_DrawTiltedTranslucentSpan_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); - } - else - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); } else { @@ -1052,24 +906,7 @@ void R_DrawTiltedTranslucentSpan_8(void) for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); - } - else - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; u += stepu; v += stepv; @@ -1130,28 +967,9 @@ void R_DrawTiltedSplat_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - val = source[((y * ds_flatwidth) + x)]; - } - else - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; - + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; - dest++; iz += ds_sz.x; uz += ds_su.x; @@ -1188,24 +1006,7 @@ void R_DrawTiltedSplat_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - val = source[((y * ds_flatwidth) + x)]; - } - else - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; dest++; @@ -1223,24 +1024,7 @@ void R_DrawTiltedSplat_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - val = source[((y * ds_flatwidth) + x)]; - } - else - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; } @@ -1264,24 +1048,6 @@ void R_DrawTiltedSplat_8(void) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; - if (!ds_powersoftwo) - { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - val = source[((y * ds_flatwidth) + x)]; - } - else - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; dest++; @@ -1299,21 +1065,17 @@ void R_DrawTiltedSplat_8(void) */ void R_DrawSplat_8 (void) { - fixed_t xposition; - fixed_t yposition; - fixed_t xstep, ystep; + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count = (ds_x2 - ds_x1 + 1); + size_t count; UINT32 val; - xposition = ds_xfrac; yposition = ds_yfrac; - xstep = ds_xstep; ystep = ds_ystep; - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the // texture with two shifts, an OR and one AND. (see below) @@ -1321,125 +1083,99 @@ void R_DrawSplat_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - if (ds_powersoftwo) - { - xposition <<= nflatshiftup; yposition <<= nflatshiftup; - xstep <<= nflatshiftup; ystep <<= nflatshiftup; - } + xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; + xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1 + 1; - if (!ds_powersoftwo) + while (count >= 8) { - while (count-- && dest <= deststop) - { - fixed_t x = (xposition >> FRACBITS); - fixed_t y = (yposition >> FRACBITS); + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + // + // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) + val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[0] = colormap[val]; + xposition += xstep; + yposition += ystep; - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[1] = colormap[val]; + xposition += xstep; + yposition += ystep; - x %= ds_flatwidth; - y %= ds_flatheight; + val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[2] = colormap[val]; + xposition += xstep; + yposition += ystep; - val = source[((y * ds_flatwidth) + x)]; - if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; - dest++; - xposition += xstep; - yposition += ystep; - } + val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[3] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[4] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[5] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[6] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[7] = colormap[val]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; } - else + while (count--) { - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - // - // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[0] = colormap[val]; - xposition += xstep; - yposition += ystep; + val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[1] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[2] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[3] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[4] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[5] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[6] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[7] = colormap[val]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count-- && dest <= deststop) - { - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; - dest++; - xposition += xstep; - yposition += ystep; - } + dest++; + xposition += xstep; + yposition += ystep; } } @@ -1448,20 +1184,16 @@ void R_DrawSplat_8 (void) */ void R_DrawTranslucentSplat_8 (void) { - fixed_t xposition; - fixed_t yposition; - fixed_t xstep, ystep; + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count = (ds_x2 - ds_x1 + 1); - UINT32 val; - - xposition = ds_xfrac; yposition = ds_yfrac; - xstep = ds_xstep; ystep = ds_ystep; + size_t count; + UINT8 val; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -1470,107 +1202,79 @@ void R_DrawTranslucentSplat_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - if (ds_powersoftwo) - { - xposition <<= nflatshiftup; yposition <<= nflatshiftup; - xstep <<= nflatshiftup; ystep <<= nflatshiftup; - } + xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; + xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1 + 1; - if (!ds_powersoftwo) + while (count >= 8) { - while (count-- && dest <= deststop) - { - fixed_t x = (xposition >> FRACBITS); - fixed_t y = (yposition >> FRACBITS); + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; - x %= ds_flatwidth; - y %= ds_flatheight; + val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; - val = source[((y * ds_flatwidth) + x)]; - if (val != TRANSPARENTPIXEL) - *dest = *(ds_transmap + (colormap[val] << 8) + *dest); - dest++; - xposition += xstep; - yposition += ystep; - } + val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; } - else + while (count--) { - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; + val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count-- && dest <= deststop) - { - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - *dest = *(ds_transmap + (colormap[val] << 8) + *dest); - dest++; - xposition += xstep; - yposition += ystep; - } + dest++; + xposition += xstep; + yposition += ystep; } } @@ -1579,20 +1283,15 @@ void R_DrawTranslucentSplat_8 (void) */ void R_DrawTranslucentSpan_8 (void) { - fixed_t xposition; - fixed_t yposition; - fixed_t xstep, ystep; + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count = (ds_x2 - ds_x1 + 1); - UINT32 val; - - xposition = ds_xfrac; yposition = ds_yfrac; - xstep = ds_xstep; ystep = ds_ystep; + size_t count; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -1601,161 +1300,63 @@ void R_DrawTranslucentSpan_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - if (ds_powersoftwo) - { - xposition <<= nflatshiftup; yposition <<= nflatshiftup; - xstep <<= nflatshiftup; ystep <<= nflatshiftup; - } + xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; + xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1 + 1; - if (!ds_powersoftwo) + while (count >= 8) { - while (count-- && dest <= deststop) - { - fixed_t x = (xposition >> FRACBITS); - fixed_t y = (yposition >> FRACBITS); + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + dest[0] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + dest[1] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; - x %= ds_flatwidth; - y %= ds_flatheight; + dest[2] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; - val = ((y * ds_flatwidth) + x); - *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); - dest++; - xposition += xstep; - yposition += ystep; - } + dest[3] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + dest[4] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + dest[5] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + dest[6] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + dest[7] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; } - else + while (count--) { - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; - - dest[1] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; - - dest[2] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - dest[3] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - dest[4] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - dest[5] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - dest[6] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - dest[7] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count-- && dest <= deststop) - { - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); - dest++; - xposition += xstep; - yposition += ystep; - } + *dest = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; } } -#ifndef NOWATER -void R_DrawTranslucentWaterSpan_8(void) -{ - fixed_t xposition; - fixed_t yposition; - fixed_t xstep, ystep; - - UINT8 *source; - UINT8 *colormap; - UINT8 *dest; - UINT8 *dsrc; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - - size_t count = (ds_x2 - ds_x1 + 1); - - xposition = ds_xfrac; yposition = (ds_yfrac + ds_waterofs); - xstep = ds_xstep; ystep = ds_ystep; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - if (ds_powersoftwo) - { - xposition <<= nflatshiftup; yposition <<= nflatshiftup; - xstep <<= nflatshiftup; ystep <<= nflatshiftup; - } - - source = ds_source; - colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; - dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; - - if (!ds_powersoftwo) - { - while (count-- && dest <= deststop) - { - fixed_t x = (xposition >> FRACBITS); - fixed_t y = (yposition >> FRACBITS); - - // Carefully align all of my Friends. - if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); - if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; - - *dest++ = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - } - } - else - { - while (count-- && dest <= deststop) - { - *dest++ = colormap[*(ds_transmap + (source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - } - } -} -#endif - /** \brief The R_DrawFogSpan_8 function Draws the actual span with fogging. */ diff --git a/src/r_plane.c b/src/r_plane.c index de5bf9f00..2f6f97240 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -127,13 +127,91 @@ void R_InitPlanes(void) // viewheight #ifndef NOWATER -INT32 ds_bgofs; -INT32 ds_waterofs; - +static INT32 bgofs; static INT32 wtofs=0; +static INT32 waterofs; static boolean itswater; #endif +#ifndef NOWATER +static void R_DrawTranslucentWaterSpan_8(void) +{ + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + UINT8 *dsrc; + + size_t count; + + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? + xposition = ds_xfrac << nflatshiftup; yposition = (ds_yfrac + waterofs) << nflatshiftup; + xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + dsrc = screens[1] + (ds_y+bgofs)*vid.width + ds_x1; + count = ds_x2 - ds_x1 + 1; + + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + dest[0] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + dest[1] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + dest[2] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + dest[3] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + dest[4] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + dest[5] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + dest[6] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + dest[7] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count--) + { + *dest++ = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + } +} +#endif + void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { angle_t angle, planecos, planesin; @@ -180,17 +258,17 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { const INT32 yay = (wtofs + (distance>>9) ) & 8191; // ripples da water texture - ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; + bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; angle = (currentplane->viewangle + currentplane->plangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; angle = (angle + 2048) & 8191; // 90 degrees - ds_xfrac += FixedMul(FINECOSINE(angle), (ds_bgofs<=viewheight) - ds_bgofs = viewheight-y-1; - if (y+ds_bgofs<0) - ds_bgofs = -y; + if (y+bgofs>=viewheight) + bgofs = viewheight-y-1; + if (y+bgofs<0) + bgofs = -y; } #endif @@ -602,7 +680,7 @@ void R_DrawPlanes(void) } } #ifndef NOWATER - ds_waterofs = (leveltime & 1)*16384; + waterofs = (leveltime & 1)*16384; wtofs = leveltime * 140; #endif } @@ -650,156 +728,13 @@ static void R_DrawSkyPlane(visplane_t *pl) } } -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 UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng) -{ - UINT8 *flat; - textureflat_t *texflat = &texflats[levelflat->texturenum]; - patch_t *patch = NULL; - boolean texturechanged = (leveltexture ? (levelflat->texturenum != levelflat->lasttexturenum) : false); - - // Check if the texture changed. - if (leveltexture && (!texturechanged)) - { - if (texflat != NULL && texflat->flat) - { - flat = 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) - { - 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_TextureToFlat(levelflat->texturenum, texflat->flat); - flat = texflat->flat; - - levelflat->flatpatch = flat; - levelflat->width = ds_flatwidth; - levelflat->height = ds_flatheight; - } - else - { - patch = (patch_t *)ds_source; -#ifndef NO_PNG_LUMPS - if (ispng) - { - levelflat->flatpatch = R_PNGToFlat(levelflat, ds_source, W_LumpLength(levelflat->lumpnum)); - levelflat->topoffset = levelflat->leftoffset = 0; - ds_flatwidth = levelflat->width; - ds_flatheight = levelflat->height; - } - else -#endif - { - levelflat->width = ds_flatwidth = SHORT(patch->width); - levelflat->height = ds_flatheight = SHORT(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_PatchToFlat(patch, levelflat->flatpatch); - } - flat = levelflat->flatpatch; - } - } - else - { - flat = levelflat->flatpatch; - ds_flatwidth = levelflat->width; - ds_flatheight = levelflat->height; - - xoffs += levelflat->leftoffset; - yoffs += levelflat->topoffset; - } - - levelflat->lasttexturenum = levelflat->texturenum; - return flat; -} - void R_DrawSinglePlane(visplane_t *pl) { - UINT8 *flat; INT32 light = 0; INT32 x; INT32 stop, angle; size_t size; ffloor_t *rover; - levelflat_t *levelflat; if (!(pl->minx <= pl->maxx)) return; @@ -939,43 +874,64 @@ void R_DrawSinglePlane(visplane_t *pl) viewangle = pl->viewangle+pl->plangle; } + currentplane = pl; + + ds_source = (UINT8 *) + W_CacheLumpNum(levelflats[pl->picnum].lumpnum, + PU_STATIC); // Stay here until Z_ChangeTag + + size = W_LumpLength(levelflats[pl->picnum].lumpnum); + + switch (size) + { + 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; + } + xoffs = pl->xoffs; yoffs = pl->yoffs; planeheight = abs(pl->height - pl->viewz); - currentplane = pl; - levelflat = &levelflats[pl->picnum]; - size = W_LumpLength(levelflat->lumpnum); - ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag - - // Check if the flat is actually a wall texture. - if (levelflat->texturenum != 0 && levelflat->texturenum != -1) - flat = R_GetPatchFlat(levelflat, true, false); -#ifndef NO_PNG_LUMPS - // Maybe it's a PNG?! - else if (R_IsLumpPNG(ds_source, size)) - flat = R_GetPatchFlat(levelflat, false, true); -#endif - // Maybe it's just a patch, then? - else if (R_CheckIfPatch(levelflat->lumpnum)) - flat = R_GetPatchFlat(levelflat, false, false); - // It's a raw flat. - else - { - R_CheckFlatLength(size); - flat = ds_source; - } - - Z_ChangeTag(ds_source, PU_CACHE); - ds_source = flat; - - if (ds_source == NULL) - return; - - // 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; @@ -989,63 +945,60 @@ void R_DrawSinglePlane(visplane_t *pl) floatv3_t p, m, n; float ang; float vx, vy, vz; - float fudge = 0; // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly // use this as a temp var to store P_GetZAt's return value each time fixed_t temp; + // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red + const float fudge = ((1<plangle & (ANGLE_90-1)); yoffs *= 1; - if (ds_powersoftwo) + if (hack) { - // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red - fudge = ((1<>ANGLETOFINESHIFT); - const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); + /* + Essentially: We can't & the components along the regular axes when the plane is rotated. + This is because the distance on each regular axis in order to loop is different. + We rotate them, & the components, add them together, & them again, and then rotate them back. + These three seperate & operations are done per axis in order to prevent overflows. + toast 10/04/17 + */ + const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT); + const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); - const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); + const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); - fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); - fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); + fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); + fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); - temp = ox & modmask; - oy &= modmask; - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); + temp = ox & modmask; + oy &= modmask; + ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction + oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); - yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); + temp = xoffs; + xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); + yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); - temp = xoffs & modmask; - yoffs &= modmask; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); + temp = xoffs & modmask; + yoffs &= modmask; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); - } - else - { - xoffs &= ((1 << (32-nflatshiftup))-1); - yoffs &= ((1 << (32-nflatshiftup))-1); - xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - } - xoffs = (fixed_t)(xoffs*fudge); - yoffs = (fixed_t)(yoffs/fudge); + xoffs -= (pl->slope->o.x - ox); + yoffs += (pl->slope->o.y + oy); } + else + { + xoffs &= ((1 << (32-nflatshiftup))-1); + yoffs &= ((1 << (32-nflatshiftup))-1); + xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + } + + xoffs = (fixed_t)(xoffs*fudge); + yoffs = (fixed_t)(yoffs/fudge); vx = FIXED_TO_FLOAT(pl->viewx+xoffs); vy = FIXED_TO_FLOAT(pl->viewy-yoffs); @@ -1080,16 +1033,13 @@ void R_DrawSinglePlane(visplane_t *pl) temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang))); n.y = FIXED_TO_FLOAT(temp) - zeroheight; - if (ds_powersoftwo) - { - m.x /= fudge; - m.y /= fudge; - m.z /= fudge; + m.x /= fudge; + m.y /= fudge; + m.z /= fudge; - n.x *= fudge; - n.y *= fudge; - n.z *= fudge; - } + n.x *= fudge; + n.y *= fudge; + n.z *= fudge; // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. #define CROSS(d, v1, v2) \ @@ -1106,26 +1056,14 @@ void R_DrawSinglePlane(visplane_t *pl) ds_sz.z *= focallengthf; // Premultiply the texture vectors with the scale factors - if (ds_powersoftwo) - { #define SFMULT 65536.f*(1< Date: Mon, 9 Sep 2019 15:02:13 -0400 Subject: [PATCH 076/133] Be clear on what FALLTHRU we really want --- src/d_main.c | 2 +- src/g_game.c | 2 +- src/sdl/i_system.c | 2 +- src/win32/win_sys.c | 2 +- src/win32/win_vid.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index eaeae4b10..9fa506bee 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -287,7 +287,7 @@ static void D_Display(void) F_TitleScreenDrawer(); break; } - // Intentional fall-through + /* FALLTHRU */ case GS_LEVEL: if (!gametic) break; diff --git a/src/g_game.c b/src/g_game.c index 89a96f3d0..2b7a1c981 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4583,7 +4583,7 @@ void G_GhostTicker(void) default: case GHC_RETURNSKIN: g->mo->skin = g->oldmo.skin; - // fallthru + /* FALLTHRU */ case GHC_NORMAL: // Go back to skin color g->mo->color = g->oldmo.color; break; diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 98166a1ce..c4fb1c0fc 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -530,7 +530,7 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co) break; case VK_RETURN: entering_con_command = false; - // Fall through. + /* FALLTHRU */ default: event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char } diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index d10f73b58..93b3ff523 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -327,7 +327,7 @@ static inline VOID I_GetConsoleEvents(VOID) break; case VK_RETURN: entering_con_command = false; - // Fall through. + /* FALLTHRU */ default: ev.data1 = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char } diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index e2f32fa61..11c7a6744 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -322,9 +322,9 @@ static inline boolean I_SkipFrame(void) case GS_LEVEL: if (!paused) return false; - /* FALLTHRU */ //case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible #ifndef CLIENT_LOADINGSCREEN + /* FALLTHRU */ case GS_WAITINGPLAYERS: #endif return skip; // Skip odd frames From 470ac5fed29d7e18eae67713d06810d01c52eea2 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Mon, 9 Sep 2019 15:05:17 -0400 Subject: [PATCH 077/133] Revert "Revert "Merge branch 'flats-png_port' into 'master'"" This reverts commit 043bb86acdf81ef0ecbd388aed57fe0fa29c8747. --- src/doomdef.h | 4 + src/hardware/hw_cache.c | 114 ++++- src/hardware/hw_glide.h | 2 + src/hardware/hw_glob.h | 3 + src/hardware/hw_light.c | 2 + src/hardware/hw_main.c | 207 +++++---- src/hardware/hw_md2.c | 4 + src/p_setup.c | 10 + src/p_setup.h | 7 + src/p_spec.c | 30 +- src/r_data.c | 643 ++++++++++++++++++++++++++-- src/r_data.h | 27 +- src/r_draw.c | 2 + src/r_draw.h | 13 +- src/r_draw8.c | 913 +++++++++++++++++++++++++++++----------- src/r_plane.c | 450 +++++++++++--------- src/r_plane.h | 2 + src/screen.c | 2 +- src/w_wad.c | 2 - 19 files changed, 1855 insertions(+), 582 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 6e7db2143..4a0174369 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -616,4 +616,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2CB itself ported this from PrBoom+ #define NEWCLIP +#ifndef HAVE_PNG +#define NO_PNG_LUMPS +#endif + #endif // __DOOMDEF__ diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 6bc2c712e..c9a75a4f3 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -30,6 +30,7 @@ #include "../z_zone.h" #include "../v_video.h" #include "../r_draw.h" +#include "../p_setup.h" //Hurdler: 25/04/2000: used for new colormap code in hardware mode //static UINT8 *gr_colormap = NULL; // by default it must be NULL ! (because colormap tables are not initialized) @@ -420,6 +421,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, GrTexInfo *grInfo) { +#ifdef GLIDE_API_COMPATIBILITY // Build the full textures from patches. static const GrLOD_t gr_lods[9] = { @@ -456,6 +458,9 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, INT32 j,k; INT32 max,min; +#else + (void)grInfo; +#endif // find a power of 2 width/height if (cv_grrounddown.value) @@ -511,6 +516,7 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, } else { +#ifdef GLIDE_API_COMPATIBILITY //size up to nearest power of 2 blockwidth = 1; while (blockwidth < originalwidth) @@ -528,9 +534,14 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, if (blockheight > 2048) blockheight = 2048; //I_Error("3D GenerateTexture : too big"); +#else + blockwidth = originalwidth; + blockheight = originalheight; +#endif } // do the boring LOD stuff.. blech! +#ifdef GLIDE_API_COMPATIBILITY if (blockwidth >= blockheight) { max = blockwidth; @@ -562,6 +573,7 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, if (blockwidth < blockheight) j += 4; grInfo->aspectRatioLog2 = gr_aspects[j].aspect; +#endif blocksize = blockwidth * blockheight; @@ -650,7 +662,12 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { + size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); +#endif HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, @@ -756,11 +773,13 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm static size_t gr_numtextures; static GLTexture_t *gr_textures; // for ALL Doom textures +static GLTexture_t *gr_textures2; void HWR_InitTextureCache(void) { gr_numtextures = 0; gr_textures = NULL; + gr_textures2 = NULL; } @@ -799,7 +818,10 @@ void HWR_FreeTextureCache(void) // texturecache info, we can free it if (gr_textures) free(gr_textures); + if (gr_textures2) + free(gr_textures2); gr_textures = NULL; + gr_textures2 = NULL; gr_numtextures = 0; } @@ -817,6 +839,9 @@ void HWR_PrepLevelCache(size_t pnumtextures) gr_textures = calloc(pnumtextures, sizeof (*gr_textures)); if (gr_textures == NULL) I_Error("3D can't alloc gr_textures"); + gr_textures2 = calloc(pnumtextures, sizeof (*gr_textures2)); + if (gr_textures2 == NULL) + I_Error("3D can't alloc gr_textures2"); } void HWR_SetPalette(RGBA_t *palette) @@ -847,7 +872,7 @@ GLTexture_t *HWR_GetTexture(INT32 tex) GLTexture_t *grtex; #ifdef PARANOIA if ((unsigned)tex >= gr_numtextures) - I_Error(" HWR_GetTexture: tex >= numtextures\n"); + I_Error("HWR_GetTexture: tex >= numtextures\n"); #endif grtex = &gr_textures[tex]; @@ -862,15 +887,39 @@ GLTexture_t *HWR_GetTexture(INT32 tex) return grtex; } +// HWR_RenderPlane and HWR_RenderPolyObjectPlane need this to get the flat dimensions from a patch. +lumpnum_t gr_patchflat; + +static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) +{ + UINT8 *flat; + patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC); + size_t lumplength = W_LumpLength(flatlumpnum); + +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)patch, lumplength)) + patch = R_PNGToPatch((UINT8 *)patch, lumplength); +#endif + + grMipmap->width = (UINT16)SHORT(patch->width); + grMipmap->height = (UINT16)SHORT(patch->height); + + flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data); + memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height); + + R_PatchToFlat(patch, flat); +} static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { size_t size, pflatsize; // setup the texture info +#ifdef GLIDE_API_COMPATIBILITY grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif grMipmap->grInfo.format = GR_TEXFMT_P_8; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; @@ -900,15 +949,20 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) pflatsize = 64; break; } - grMipmap->width = (UINT16)pflatsize; - grMipmap->height = (UINT16)pflatsize; - // the flat raw data needn't be converted with palettized textures - W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), - PU_HWRCACHE, &grMipmap->grInfo.data)); + if (R_CheckIfPatch(flatlumpnum)) + HWR_LoadPatchFlat(grMipmap, flatlumpnum); + else + { + grMipmap->width = (UINT16)pflatsize; + grMipmap->height = (UINT16)pflatsize; + + // the flat raw data needn't be converted with palettized textures + W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), + PU_HWRCACHE, &grMipmap->grInfo.data)); + } } - // Download a Doom 'flat' to the hardware cache and make it ready for use void HWR_GetFlat(lumpnum_t flatlumpnum) { @@ -923,6 +977,52 @@ void HWR_GetFlat(lumpnum_t flatlumpnum) // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); + + gr_patchflat = 0; + if (R_CheckIfPatch(flatlumpnum)) + gr_patchflat = flatlumpnum; +} + +static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) +{ + UINT8 *flat; + + // setup the texture info +#ifdef GLIDE_API_COMPATIBILITY + grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; + grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; + grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif + grMipmap->grInfo.format = GR_TEXFMT_P_8; + grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; + + grMipmap->width = (UINT16)textures[texturenum]->width; + grMipmap->height = (UINT16)textures[texturenum]->height; + + flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data); + memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height); + + R_TextureToFlat(texturenum, flat); +} + +void HWR_GetTextureFlat(INT32 texturenum) +{ + GLTexture_t *grtex; +#ifdef PARANOIA + if ((unsigned)texturenum >= gr_numtextures) + I_Error("HWR_GetTextureFlat: texturenum >= numtextures\n"); +#endif + if (texturenum == 0 || texturenum == -1) + return; + grtex = &gr_textures2[texturenum]; + + if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) + HWR_LoadTextureFlat(&grtex->mipmap, texturenum); + + HWD.pfnSetTexture(&grtex->mipmap); + + // The system-memory data can be purged now. + Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); } // diff --git a/src/hardware/hw_glide.h b/src/hardware/hw_glide.h index 2625d5864..bf91229ef 100644 --- a/src/hardware/hw_glide.h +++ b/src/hardware/hw_glide.h @@ -59,9 +59,11 @@ typedef FxI32 GrTextureFormat_t; typedef struct { +#ifdef GLIDE_API_COMPATIBILITY GrLOD_t smallLodLog2; GrLOD_t largeLodLog2; GrAspectRatio_t aspectRatioLog2; +#endif GrTextureFormat_t format; void *data; } GrTexInfo; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 9656e54e9..c7b06edfd 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -101,6 +101,7 @@ void HWR_FreeTextureCache(void); void HWR_FreeExtraSubsectors(void); void HWR_GetFlat(lumpnum_t flatlumpnum); +void HWR_GetTextureFlat(INT32 texturenum); GLTexture_t *HWR_GetTexture(INT32 tex); void HWR_GetPatch(GLPatch_t *gpatch); void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap); @@ -114,6 +115,8 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum); // -------- // hw_draw.c // -------- +extern lumpnum_t gr_patchflat; + extern float gr_patch_scalex; extern float gr_patch_scaley; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index edfe328b8..1de20cad7 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1225,9 +1225,11 @@ static void HWR_SetLight(void) lightmappatch.height = 128; lightmappatch.mipmap.width = 128; lightmappatch.mipmap.height = 128; +#ifdef GLIDE_API_COMPATIBILITY lightmappatch.mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_128; lightmappatch.mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_128; lightmappatch.mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif lightmappatch.mipmap.flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw ! } HWD.pfnSetTexture(&lightmappatch.mipmap); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c6a8b16e5..07ae7ed2b 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -70,9 +70,9 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); #endif #ifdef SORTING -void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, +void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, +void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); #else static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight, @@ -522,7 +522,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c // HWR_RenderPlane : Render a floor or ceiling convex polygon // -----------------+ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, - FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) + FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) { polyvertex_t * pv; float height; //constant y for all points on the convex flat polygon @@ -530,8 +530,9 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is INT32 nrPlaneVerts; //verts original define of convex flat polygon INT32 i; float flatxref,flatyref; - float fflatsize; + float fflatwidth, fflatheight; INT32 flatflag; + boolean texflat = true; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; @@ -540,6 +541,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is #ifdef ESLOPE pslope_t *slope = NULL; #endif + patch_t *patch; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; @@ -580,9 +582,10 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is if (nrPlaneVerts < 3) //not even a triangle ? return; - if (nrPlaneVerts > (INT32)UINT16_MAX) // FIXME: exceeds plVerts size + // This check is so inconsistent between functions, it hurts. + if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size { - CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX); + CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, INT16_MAX); return; } @@ -599,38 +602,47 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is switch (len) { case 4194304: // 2048x2048 lump - fflatsize = 2048.0f; - flatflag = 2047; + fflatwidth = fflatheight = 2048.0f; break; case 1048576: // 1024x1024 lump - fflatsize = 1024.0f; - flatflag = 1023; + fflatwidth = fflatheight = 1024.0f; break; case 262144:// 512x512 lump - fflatsize = 512.0f; - flatflag = 511; + fflatwidth = fflatheight = 512.0f; break; case 65536: // 256x256 lump - fflatsize = 256.0f; - flatflag = 255; + fflatwidth = fflatheight = 256.0f; break; case 16384: // 128x128 lump - fflatsize = 128.0f; - flatflag = 127; + fflatwidth = fflatheight = 128.0f; break; case 1024: // 32x32 lump - fflatsize = 32.0f; - flatflag = 31; + fflatwidth = fflatheight = 32.0f; break; default: // 64x64 lump - fflatsize = 64.0f; - flatflag = 63; + fflatwidth = fflatheight = 64.0f; break; } + flatflag = ((INT32)fflatwidth)-1; + + if (texturenum != 0 && texturenum != -1) + { + fflatwidth = textures[texturenum]->width; + fflatheight = textures[texturenum]->height; + } + else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? + { + patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); + fflatwidth = SHORT(patch->width); + fflatheight = SHORT(patch->height); + } + else + texflat = false; + // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatsize); - flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatsize); + flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth); + flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatheight); // transform v3d = planeVerts; @@ -639,14 +651,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; angle = FOFsector->floorpic_angle; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; angle = FOFsector->ceilingpic_angle; } } @@ -654,14 +666,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight; angle = gr_frontsector->floorpic_angle; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight; angle = gr_frontsector->ceilingpic_angle; } } @@ -680,17 +692,24 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) { // Hurdler: add scrolling texture on floor/ceiling - v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx); - v3d->tow = (float)(-(pv->y / fflatsize) + flatyref + scrolly); - - //v3d->sow = (float)(pv->x / fflatsize); - //v3d->tow = (float)(pv->y / fflatsize); + if (texflat) + { + v3d->sow = (float)(pv->x / fflatwidth) + scrollx; + v3d->tow = -(float)(pv->y / fflatheight) + scrolly; + } + else + { + v3d->sow = (float)((pv->x / fflatwidth) - flatxref + scrollx); + v3d->tow = (float)(flatyref - (pv->y / fflatheight) + scrolly); + } // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { tempxsow = FLOAT_TO_FIXED(v3d->sow); tempytow = FLOAT_TO_FIXED(v3d->tow); + if (texflat) + tempytow = -tempytow; v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); } @@ -3164,21 +3183,23 @@ static inline void HWR_AddPolyObjectSegs(void) #ifdef POLYOBJECTS_PLANES static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, - FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, + FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) { float height; //constant y for all points on the convex flat polygon FOutVector *v3d; INT32 i; float flatxref,flatyref; - float fflatsize; + float fflatwidth, fflatheight; INT32 flatflag; + boolean texflat = true; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; FSurfaceInfo Surf; fixed_t tempxsow, tempytow; size_t nrPlaneVerts; + patch_t *patch; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; @@ -3209,38 +3230,47 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, switch (len) { case 4194304: // 2048x2048 lump - fflatsize = 2048.0f; - flatflag = 2047; + fflatwidth = fflatheight = 2048.0f; break; case 1048576: // 1024x1024 lump - fflatsize = 1024.0f; - flatflag = 1023; + fflatwidth = fflatheight = 1024.0f; break; case 262144:// 512x512 lump - fflatsize = 512.0f; - flatflag = 511; + fflatwidth = fflatheight = 512.0f; break; case 65536: // 256x256 lump - fflatsize = 256.0f; - flatflag = 255; + fflatwidth = fflatheight = 256.0f; break; case 16384: // 128x128 lump - fflatsize = 128.0f; - flatflag = 127; + fflatwidth = fflatheight = 128.0f; break; case 1024: // 32x32 lump - fflatsize = 32.0f; - flatflag = 31; + fflatwidth = fflatheight = 32.0f; break; default: // 64x64 lump - fflatsize = 64.0f; - flatflag = 63; + fflatwidth = fflatheight = 64.0f; break; } + flatflag = ((INT32)fflatwidth)-1; + + if (texturenum != 0 && texturenum != -1) + { + fflatwidth = textures[texturenum]->width; + fflatheight = textures[texturenum]->height; + } + else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? + { + patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); + fflatwidth = SHORT(patch->width); + fflatheight = SHORT(patch->height); + } + else + texflat = false; + // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].x) & (~flatflag)) / fflatsize); - flatyref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].y) & (~flatflag)) / fflatsize); + flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth); + flatyref = (float)((polysector->origVerts[0].y & (~flatflag)) / fflatheight); // transform v3d = planeVerts; @@ -3249,14 +3279,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT; } } @@ -3264,14 +3294,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight; angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight; angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT; } } @@ -3294,15 +3324,26 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++) { - // Hurdler: add scrolling texture on floor/ceiling - v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatsize) - flatxref + scrollx); // Go from the polysector's original vertex locations - v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatsize) + scrolly); // Means the flat is offset based on the original vertex locations + // Go from the polysector's original vertex locations + // Means the flat is offset based on the original vertex locations + if (texflat) + { + v3d->sow = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx; + v3d->tow = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly; + } + else + { + v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx); + v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly); + } // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { tempxsow = FLOAT_TO_FIXED(v3d->sow); tempytow = FLOAT_TO_FIXED(v3d->tow); + if (texflat) + tempytow = -tempytow; v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle)))); } @@ -3365,6 +3406,7 @@ static void HWR_AddPolyObjectPlanes(void) else { HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum); + HWR_GetTextureFlat(levelflats[polyobjsector->floorpic].texturenum); HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); @@ -3388,6 +3430,7 @@ static void HWR_AddPolyObjectPlanes(void) else { HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum); + HWR_GetTextureFlat(levelflats[polyobjsector->ceilingpic].texturenum); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); @@ -3541,11 +3584,12 @@ static void HWR_Subsector(size_t num) if (sub->validcount != validcount) { HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum); + HWR_GetTextureFlat(levelflats[gr_frontsector->floorpic].texturenum); HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false, // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap); + PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, levelflats[gr_frontsector->floorpic].texturenum, NULL, 255, false, floorcolormap); } } else @@ -3563,11 +3607,12 @@ static void HWR_Subsector(size_t num) if (sub->validcount != validcount) { HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum); + HWR_GetTextureFlat(levelflats[gr_frontsector->ceilingpic].texturenum); HWR_RenderPlane(NULL, &extrasubsectors[num], true, // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap); + PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum, levelflats[gr_frontsector->ceilingpic].texturenum, NULL, 255, false, ceilingcolormap); } } else @@ -3626,7 +3671,7 @@ static void HWR_Subsector(size_t num) else alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - HWR_AddTransparentFloor(0, + HWR_AddTransparentFloor(0, 0, &extrasubsectors[num], false, *rover->bottomheight, @@ -3645,6 +3690,7 @@ static void HWR_Subsector(size_t num) rover->alpha-1, rover->master->frontsector); #else HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum, + levelflats[*rover->bottompic].texturenum, &extrasubsectors[num], false, *rover->bottomheight, @@ -3656,8 +3702,9 @@ static void HWR_Subsector(size_t num) else { HWR_GetFlat(levelflats[*rover->bottompic].lumpnum); + HWR_GetTextureFlat(levelflats[*rover->bottompic].texturenum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, + HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, levelflats[*rover->bottompic].texturenum, rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -3689,7 +3736,7 @@ static void HWR_Subsector(size_t num) else alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - HWR_AddTransparentFloor(0, + HWR_AddTransparentFloor(0, 0, &extrasubsectors[num], true, *rover->topheight, @@ -3708,6 +3755,7 @@ static void HWR_Subsector(size_t num) rover->alpha-1, rover->master->frontsector); #else HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum, + levelflats[*rover->bottompic].texturenum, &extrasubsectors[num], true, *rover->topheight, @@ -3720,8 +3768,9 @@ static void HWR_Subsector(size_t num) else { HWR_GetFlat(levelflats[*rover->toppic].lumpnum); + HWR_GetTextureFlat(levelflats[*rover->toppic].texturenum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, + HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, levelflats[*rover->toppic].texturenum, rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -5050,6 +5099,7 @@ typedef struct fixed_t fixedheight; INT32 lightlevel; lumpnum_t lumpnum; + INT32 texturenum; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -5068,6 +5118,7 @@ typedef struct fixed_t fixedheight; INT32 lightlevel; lumpnum_t lumpnum; + INT32 texturenum; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -5098,7 +5149,7 @@ static INT32 drawcount = 0; #define MAX_TRANSPARENTFLOOR 512 // This will likely turn into a copy of HWR_Add3DWater and replace it. -void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, +void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) { static size_t allocedplanes = 0; @@ -5117,6 +5168,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean planeinfo[numplanes].fixedheight = fixedheight; planeinfo[numplanes].lightlevel = lightlevel; planeinfo[numplanes].lumpnum = lumpnum; + planeinfo[numplanes].texturenum = texturenum; planeinfo[numplanes].xsub = xsub; planeinfo[numplanes].alpha = alpha; planeinfo[numplanes].FOFSector = FOFSector; @@ -5130,7 +5182,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean // Adding this for now until I can create extrasubsector info for polyobjects // When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, +void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) { static size_t allocedpolyplanes = 0; @@ -5149,6 +5201,7 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, polyplaneinfo[numpolyplanes].fixedheight = fixedheight; polyplaneinfo[numpolyplanes].lightlevel = lightlevel; polyplaneinfo[numpolyplanes].lumpnum = lumpnum; + polyplaneinfo[numpolyplanes].texturenum = texturenum; polyplaneinfo[numpolyplanes].polysector = polysector; polyplaneinfo[numpolyplanes].alpha = alpha; polyplaneinfo[numpolyplanes].FOFSector = FOFSector; @@ -5310,9 +5363,12 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) + { HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum); + HWR_GetTextureFlat(sortnode[sortindex[i]].plane->texturenum); + } HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, - sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); + sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->texturenum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); } else if (sortnode[sortindex[i]].polyplane) { @@ -5320,9 +5376,12 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture)) + { HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum); + HWR_GetTextureFlat(sortnode[sortindex[i]].polyplane->texturenum); + } HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, - sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); + sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->texturenum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); } else if (sortnode[sortindex[i]].wall) { diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index d4728315a..7b6367cf3 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -747,10 +747,12 @@ static void md2_loadTexture(md2_t *model) grpatch->mipmap.width = (UINT16)w; grpatch->mipmap.height = (UINT16)h; +#ifdef GLIDE_API_COMPATIBILITY // not correct! grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif } HWD.pfnSetTexture(&grpatch->mipmap); HWR_UnlockCachedPatch(grpatch); @@ -798,10 +800,12 @@ static void md2_loadBlendTexture(md2_t *model) grpatch->mipmap.width = (UINT16)w; grpatch->mipmap.height = (UINT16)h; +#ifdef GLIDE_API_COMPATIBILITY // not correct! grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif } HWD.pfnSetTexture(&grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary HWR_UnlockCachedPatch(grpatch); diff --git a/src/p_setup.c b/src/p_setup.c index 65335be3f..60e036a87 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -573,6 +573,11 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) // store the flat lump number levelflat->lumpnum = R_GetFlatNumForName(flatname); + 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); @@ -617,6 +622,11 @@ INT32 P_AddLevelFlatRuntime(const char *flatname) // store the flat lump number levelflat->lumpnum = R_GetFlatNumForName(flatname); + 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 7e8a5d7e6..7e3a149eb 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -37,12 +37,19 @@ 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; + + // for patchflats + UINT8 *flatpatch; } levelflat_t; extern size_t numlevelflats; diff --git a/src/p_spec.c b/src/p_spec.c index 7742554cd..256ca3453 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -205,8 +205,8 @@ void P_InitPicAnims(void) if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR) continue; - lastanim->picnum = R_FlatNumForName(animdefs[i].endname); - lastanim->basepic = R_FlatNumForName(animdefs[i].startname); + lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname); + lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname); } lastanim->istexture = animdefs[i].istexture; @@ -464,7 +464,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; @@ -488,10 +500,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); } // @@ -5669,9 +5678,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 6889bddde..5858117a5 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -40,6 +40,28 @@ #include #endif +#ifdef HAVE_PNG + +#ifndef _MSC_VER +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#endif + +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif + +#include "png.h" +#ifndef PNG_READ_SUPPORTED +#undef HAVE_PNG +#endif +#endif + // // Texture definition. // Each texture is composed of one or more patches, @@ -98,12 +120,11 @@ 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 -// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask -INT32 *texturewidthmask; - +INT32 *texturewidth; fixed_t *textureheight; // needed for texture pegging INT32 *texturetranslation; @@ -315,7 +336,7 @@ static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache // Allocate space for full size texture, either single patch or 'composite' // Build the full textures from patches. // The texture caching system is a little more hungry of memory, but has -// been simplified for the sake of highcolor, dynamic ligthing, & speed. +// been simplified for the sake of highcolor (lol), dynamic ligthing, & speed. // // This is not optimised, but it's supposed to be executed only once // per level, when enough memory is available. @@ -332,6 +353,10 @@ static UINT8 *R_GenerateTexture(size_t texnum) column_t *patchcol; UINT32 *colofs; + UINT16 wadnum; + lumpnum_t lumpnum; + size_t lumplength; + I_Assert(texnum <= (size_t)numtextures); texture = textures[texnum]; I_Assert(texture != NULL); @@ -346,7 +371,19 @@ static UINT8 *R_GenerateTexture(size_t texnum) { boolean holey = false; patch = texture->patches; - realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); + + wadnum = patch->wad; + lumpnum = patch->lump; + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) + { + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); + goto multipatch; + } +#endif // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) @@ -376,7 +413,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) { texture->holes = true; texture->flip = patch->flip; - blocksize = W_LumpLengthPwad(patch->wad, patch->lump); + blocksize = lumplength; block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function &texturecache[texnum]); M_Memcpy(block, realpatch, blocksize); @@ -403,6 +440,9 @@ static UINT8 *R_GenerateTexture(size_t texnum) } // multi-patch textures (or 'composite') +#ifndef NO_PNG_LUMPS + multipatch: +#endif texture->holes = false; texture->flip = 0; blocksize = (texture->width * 4) + (texture->width * texture->height); @@ -433,7 +473,15 @@ static UINT8 *R_GenerateTexture(size_t texnum) ColumnDrawerPointer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache; } - realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); + wadnum = patch->wad; + lumpnum = patch->lump; + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); +#endif + x1 = patch->originx; width = SHORT(realpatch->width); height = SHORT(realpatch->height); @@ -509,10 +557,14 @@ void R_CheckTextureCache(INT32 tex) UINT8 *R_GetColumn(fixed_t tex, INT32 col) { UINT8 *data; + INT32 width = texturewidth[tex]; + + if (width & (width - 1)) + col = (UINT32)col % width; + else + col &= (width - 1); - col &= texturewidthmask[tex]; data = texturecache[tex]; - if (!data) data = R_GenerateTexture(tex); @@ -550,7 +602,7 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index); #define TX_END "TX_END" void R_LoadTextures(void) { - INT32 i, k, w; + INT32 i, w; UINT16 j; UINT16 texstart, texend, texturesLumpPos; patch_t *patchlump; @@ -567,6 +619,7 @@ void R_LoadTextures(void) } Z_Free(texturetranslation); Z_Free(textures); + Z_Free(texflats); } // Load patches and textures. @@ -627,15 +680,16 @@ 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 *))); // Allocate texture referencing cache. - texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); - // Allocate texture width mask table. - texturewidthmask = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); - // Allocate texture height mask table. - textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); + texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); + // Allocate texture width table. + texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); + // Allocate texture height table. + textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); // Create translation table for global animation. texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); @@ -673,20 +727,39 @@ void R_LoadTextures(void) // Work through each lump between the markers in the WAD. for (j = 0; j < (texend - texstart); j++) { + UINT16 wadnum = (UINT16)w; + lumpnum_t lumpnum = texstart + j; + size_t lumplength; + if (wadfiles[w]->type == RET_PK3) { - if (W_IsLumpFolder((UINT16)w, texstart + j)) // Check if lump is a folder + if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder continue; // If it is then SKIP IT } - patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE); + + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); // Set texture properties. - M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name)); - texture->width = SHORT(patchlump->width); - texture->height = SHORT(patchlump->height); + M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)patchlump, lumplength)) + { + INT16 width, height; + R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength); + texture->width = width; + texture->height = height; + } + else +#endif + { + texture->width = SHORT(patchlump->width); + texture->height = SHORT(patchlump->height); + } texture->patchcount = 1; texture->holes = false; texture->flip = 0; @@ -701,11 +774,7 @@ void R_LoadTextures(void) Z_Unlock(patchlump); - k = 1; - while (k << 1 <= texture->width) - k <<= 1; - - texturewidthmask[i] = k - 1; + texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; i++; } @@ -1097,7 +1166,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) texturesToken = M_GetToken(texturesText); while (texturesToken != NULL) { - if (stricmp(texturesToken, "WALLTEXTURE")==0) + if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0) { numTexturesInLump++; Z_Free(texturesToken); @@ -1105,7 +1174,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) } else { - I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); + I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken); } texturesToken = M_GetToken(NULL); } @@ -1146,21 +1215,21 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) texturesToken = M_GetToken(texturesText); while (texturesToken != NULL) { - if (stricmp(texturesToken, "WALLTEXTURE")==0) + if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0) { Z_Free(texturesToken); // Get the new texture newTexture = R_ParseTexture(true); // Store the new texture textures[*texindex] = newTexture; - texturewidthmask[*texindex] = newTexture->width - 1; + texturewidth[*texindex] = newTexture->width; textureheight[*texindex] = newTexture->height << FRACBITS; // Increment i back in R_LoadTextures() (*texindex)++; } else { - I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); + I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken); } texturesToken = M_GetToken(NULL); } @@ -1267,6 +1336,41 @@ lumpnum_t R_GetFlatNumForName(const char *name) lump = LUMPERROR; } + // Detect textures + if (lump == LUMPERROR) + { + // Scan wad files backwards so patched textures take preference. + for (i = numwadfiles - 1; i >= 0; i--) + { + switch (wadfiles[i]->type) + { + case RET_WAD: + if ((start = W_CheckNumForNamePwad("TX_START", (UINT16)i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX) + continue; + break; + case RET_PK3: + if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX) + continue; + break; + default: + continue; + } + + // Now find lump with specified name in that range. + lump = W_CheckNumForNamePwad(name, (UINT16)i, start); + if (lump < end) + { + lump += (i<<16); // found it, in our constraints + break; + } + lump = LUMPERROR; + } + } + if (lump == LUMPERROR) { if (strcmp(name, SKYFLATNAME)) @@ -1615,7 +1719,6 @@ extracolormap_t *R_ColormapForName(char *name) // static double deltas[256][3], map[256][3]; -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); static int RoundUp(double number); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) @@ -2027,7 +2130,7 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex // Thanks to quake2 source! // utils3/qdata/images.c -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) { int dr, dg, db; int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i; @@ -2306,3 +2409,479 @@ void R_PrecacheLevel(void) "texturememory: %s k\n" "spritememory: %s k\n", sizeu1(flatmemory>>10), sizeu2(texturememory>>10), sizeu3(spritememory>>10)); } + +// https://github.com/coelckers/prboom-plus/blob/master/prboom2/src/r_patch.c#L350 +boolean R_CheckIfPatch(lumpnum_t lump) +{ + size_t size; + INT16 width, height; + patch_t *patch; + boolean result; + + size = W_LumpLength(lump); + + // minimum length of a valid Doom patch + if (size < 13) + return false; + + patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC); + + width = SHORT(patch->width); + height = SHORT(patch->height); + + result = (height > 0 && height <= 16384 && width > 0 && width <= 16384 && width < (INT16)(size / 4)); + + if (result) + { + // The dimensions seem like they might be valid for a patch, so + // check the column directory for extra security. All columns + // must begin after the column directory, and none of them must + // point past the end of the patch. + INT16 x; + + for (x = 0; x < width; x++) + { + UINT32 ofs = LONG(patch->columnofs[x]); + + // Need one byte for an empty column (but there's patches that don't know that!) + if (ofs < (UINT32)width * 4 + 8 || ofs >= (UINT32)size) + { + result = false; + break; + } + } + } + + return result; +} + +void R_PatchToFlat(patch_t *patch, UINT8 *flat) +{ + fixed_t col, ofs; + column_t *column; + UINT8 *desttop, *dest, *deststop; + UINT8 *source; + + desttop = flat; + deststop = desttop + (SHORT(patch->width) * SHORT(patch->height)); + + for (col = 0; col < SHORT(patch->width); col++, desttop++) + { + INT32 topdelta, prevdelta = -1; + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[col])); + + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + + dest = desttop + (topdelta * SHORT(patch->width)); + source = (UINT8 *)(column) + 3; + for (ofs = 0; dest < deststop && ofs < column->length; ofs++) + { + *dest = source[ofs]; + dest += SHORT(patch->width); + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } +} + +#ifndef NO_PNG_LUMPS +boolean R_IsLumpPNG(UINT8 *d, size_t s) +{ + if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/ + return false; + // Check for PNG file signature using memcmp + // As it may be faster on CPUs with slow unaligned memory access + // Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature + return (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0); +} + +#ifdef HAVE_PNG +typedef struct { + png_bytep buffer; + png_uint_32 bufsize; + png_uint_32 current_pos; +} png_ioread; + +static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_ioread *f = png_get_io_ptr(png_ptr); + if (length > (f->bufsize - f->current_pos)) + png_error(png_ptr, "PNG_IOReader: buffer overrun"); + memcpy(data, f->buffer + f->current_pos, length); + f->current_pos += length; +} + +static void PNG_error(png_structp PNG, png_const_charp pngtext) +{ + CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext); + //I_Error("libpng error at %p: %s", PNG, pngtext); +} + +static void PNG_warn(png_structp PNG, png_const_charp pngtext) +{ + CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext); +} + +static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) +{ + png_structp png_ptr; + png_infop png_info_ptr; + png_uint_32 width, height; + int bit_depth, color_type; + png_uint_32 y; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + png_ioread png_io; + png_bytep *row_pointers; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, + PNG_error, PNG_warn); + if (!png_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n"); + return NULL; + } + + png_info_ptr = png_create_info_struct(png_ptr); + if (!png_info_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n"); + png_destroy_read_struct(&png_ptr, NULL, NULL); + return NULL; + } + +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) +#endif + { + //CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename); + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + return NULL; + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); +#endif + + // set our own read_function + png_io.buffer = (png_bytep)png; + png_io.bufsize = size; + png_io.current_pos = 0; + png_set_read_fn(png_ptr, &png_io, PNG_IOReader); + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_set_user_limits(png_ptr, 2048, 2048); +#endif + + png_read_info(png_ptr, png_info_ptr); + + png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type, + NULL, NULL, NULL); + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + else if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + else if (color_type != PNG_COLOR_TYPE_RGB_ALPHA && color_type != PNG_COLOR_TYPE_GRAY_ALPHA) + { +#if PNG_LIBPNG_VER < 10207 + png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); +#else + png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER); +#endif + } + + png_read_update_info(png_ptr, png_info_ptr); + + // Read the image + row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); + for (y = 0; y < height; y++) + row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, png_info_ptr)); + png_read_image(png_ptr, row_pointers); + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + + *w = (INT32)width; + *h = (INT32)height; + return row_pointers; +} + +// Convert a PNG to a raw image. +static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) +{ + UINT8 *flat; + png_uint_32 x, y; + png_bytep *row_pointers = PNG_Read(png, w, h, size); + png_uint_32 width = *w, height = *h; + + if (!row_pointers) + I_Error("PNG_RawConvert: conversion failed"); + + // Convert the image to 8bpp + flat = Z_Malloc(width * height, PU_LEVEL, NULL); + memset(flat, TRANSPARENTPIXEL, width * height); + for (y = 0; y < height; y++) + { + png_bytep row = row_pointers[y]; + for (x = 0; x < width; x++) + { + png_bytep px = &(row[x * 4]); + if ((UINT8)px[3]) + flat[((y * width) + x)] = NearestColor((UINT8)px[0], (UINT8)px[1], (UINT8)px[2]); + } + } + free(row_pointers); + + return flat; +} + +// Convert a PNG to a flat. +UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size) +{ + return PNG_RawConvert(png, &levelflat->width, &levelflat->height, size); +} + +// Convert a PNG to a patch. +static unsigned char imgbuf[1<<26]; +patch_t *R_PNGToPatch(UINT8 *png, size_t size) +{ + UINT16 width, height; + UINT8 *raw = PNG_RawConvert(png, &width, &height, size); + + UINT32 x, y; + UINT8 *img; + UINT8 *imgptr = imgbuf; + UINT8 *colpointers, *startofspan; + + #define WRITE8(buf, a) ({*buf = (a); buf++;}) + #define WRITE16(buf, a) ({*buf = (a)&255; buf++; *buf = (a)>>8; buf++;}) + #define WRITE32(buf, a) ({WRITE16(buf, (a)&65535); WRITE16(buf, (a)>>16);}) + + if (!raw) + I_Error("R_PNGToPatch: conversion failed"); + + // Write image size and offset + WRITE16(imgptr, width); + WRITE16(imgptr, height); + // no offsets + WRITE16(imgptr, 0); + WRITE16(imgptr, 0); + + // Leave placeholder to column pointers + colpointers = imgptr; + imgptr += width*4; + + // Write columns + for (x = 0; x < width; x++) + { + int lastStartY = 0; + int spanSize = 0; + startofspan = NULL; + + //printf("%d ", x); + // Write column pointer (@TODO may be wrong) + WRITE32(colpointers, imgptr - imgbuf); + + // Write pixels + for (y = 0; y < height; y++) + { + UINT8 paletteIndex = raw[((y * width) + x)]; + + // Start new column if we need to + if (!startofspan || spanSize == 255) + { + int writeY = y; + + // If we reached the span size limit, finish the previous span + if (startofspan) + WRITE8(imgptr, 0); + + if (y > 254) + { + // Make sure we're aligned to 254 + if (lastStartY < 254) + { + WRITE8(imgptr, 254); + WRITE8(imgptr, 0); + imgptr += 2; + lastStartY = 254; + } + + // Write stopgap empty spans if needed + writeY = y - lastStartY; + + while (writeY > 254) + { + WRITE8(imgptr, 254); + WRITE8(imgptr, 0); + imgptr += 2; + writeY -= 254; + } + } + + startofspan = imgptr; + WRITE8(imgptr, writeY);///@TODO calculate starting y pos + imgptr += 2; + spanSize = 0; + + lastStartY = y; + } + + // Write the pixel + WRITE8(imgptr, paletteIndex); + spanSize++; + startofspan[1] = spanSize; + } + + if (startofspan) + WRITE8(imgptr, 0); + + WRITE8(imgptr, 0xFF); + } + + #undef WRITE8 + #undef WRITE16 + #undef WRITE32 + + size = imgptr-imgbuf; + img = malloc(size); + memcpy(img, imgbuf, size); + + Z_Free(raw); + + return (patch_t *)img; +} + +boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size) +{ + png_structp png_ptr; + png_infop png_info_ptr; + png_uint_32 w, h; + int bit_depth, color_type; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + png_ioread png_io; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, + PNG_error, PNG_warn); + if (!png_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n"); + return false; + } + + png_info_ptr = png_create_info_struct(png_ptr); + if (!png_info_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n"); + png_destroy_read_struct(&png_ptr, NULL, NULL); + return false; + } + +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) +#endif + { + //CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename); + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + return false; + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); +#endif + + // set our own read_function + png_io.buffer = (png_bytep)png; + png_io.bufsize = size; + png_io.current_pos = 0; + png_set_read_fn(png_ptr, &png_io, PNG_IOReader); + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_set_user_limits(png_ptr, 2048, 2048); +#endif + + png_read_info(png_ptr, png_info_ptr); + + png_get_IHDR(png_ptr, png_info_ptr, &w, &h, &bit_depth, &color_type, + NULL, NULL, NULL); + + // okay done. stop. + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + + *width = (INT32)w; + *height = (INT32)h; + return true; +} +#endif +#endif + +void R_TextureToFlat(size_t tex, UINT8 *flat) +{ + texture_t *texture = textures[tex]; + + fixed_t col, ofs; + column_t *column; + UINT8 *desttop, *dest, *deststop; + UINT8 *source; + + desttop = flat; + deststop = desttop + (texture->width * texture->height); + + for (col = 0; col < texture->width; col++, desttop++) + { + column = (column_t *)R_GetColumn(tex, col); + if (!texture->holes) + { + dest = desttop; + source = (UINT8 *)(column); + for (ofs = 0; dest < deststop && ofs < texture->height; ofs++) + { + if (source[ofs] != TRANSPARENTPIXEL) + *dest = source[ofs]; + dest += texture->width; + } + } + else + { + INT32 topdelta, prevdelta = -1; + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + + dest = desttop + (topdelta * texture->width); + source = (UINT8 *)(column) + 3; + for (ofs = 0; dest < deststop && ofs < column->length; ofs++) + { + if (source[ofs] != TRANSPARENTPIXEL) + *dest = source[ofs]; + dest += texture->width; + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } + } +} diff --git a/src/r_data.h b/src/r_data.h index b6b0a16a1..b29bf4557 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -16,6 +16,7 @@ #include "r_defs.h" #include "r_state.h" +#include "p_setup.h" // levelflats #ifdef __GNUG__ #pragma interface @@ -55,12 +56,17 @@ typedef struct texpatch_t patches[0]; } texture_t; +typedef struct +{ + UINT8 *flat; + INT16 width, height; +} textureflat_t; + // all loaded and prepared textures from the start of the game extern texture_t **textures; +extern textureflat_t *texflats; -// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask -extern INT32 *texturewidthmask; - +extern INT32 *texturewidth; extern fixed_t *textureheight; // needed for texture pegging extern INT16 color8to16[256]; // remap color index to highcolor @@ -88,7 +94,6 @@ void R_PrecacheLevel(void); // Floor/ceiling opaque texture tiles, // lookup by name. For animation? lumpnum_t R_GetFlatNumForName(const char *name); -#define R_FlatNumForName(x) R_GetFlatNumForName(x) // Called by P_Ticker for switches and animations, // returns the texture number for the texture name. @@ -148,6 +153,20 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap); #define R_PutRgbaRGB(r, g, b) (R_PutRgbaR(r) + R_PutRgbaG(g) + R_PutRgbaB(b)) #define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a)) +boolean R_CheckIfPatch(lumpnum_t lump); +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); + +void R_PatchToFlat(patch_t *patch, UINT8 *flat); +void R_TextureToFlat(size_t tex, UINT8 *flat); + +#ifndef NO_PNG_LUMPS +boolean R_IsLumpPNG(UINT8 *d, size_t s); + +UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size); +patch_t *R_PNGToPatch(UINT8 *png, size_t size); +boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size); +#endif + extern INT32 numtextures; #endif diff --git a/src/r_draw.c b/src/r_draw.c index 396ed0344..1754403c4 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -99,6 +99,8 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight; INT32 ds_y, ds_x1, ds_x2; lighttable_t *ds_colormap; fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; +UINT16 ds_flatwidth, ds_flatheight; +boolean ds_powersoftwo; UINT8 *ds_source; // start of a 64*64 tile image UINT8 *ds_transmap; // one of the translucency tables diff --git a/src/r_draw.h b/src/r_draw.h index 82498eb11..3c1429722 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -57,7 +57,9 @@ extern INT32 dc_texheight; extern INT32 ds_y, ds_x1, ds_x2; extern lighttable_t *ds_colormap; extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; -extern UINT8 *ds_source; // start of a 64*64 tile image +extern UINT16 ds_flatwidth, ds_flatheight; +extern boolean ds_powersoftwo; +extern UINT8 *ds_source; extern UINT8 *ds_transmap; #ifdef ESLOPE @@ -128,6 +130,8 @@ void R_FillBackScreen(void); void R_DrawViewBorder(void); #endif +#define TRANSPARENTPIXEL 255 + // ----------------- // 8bpp DRAWING CODE // ----------------- @@ -169,6 +173,13 @@ void R_DrawFogSpan_8(void); void R_DrawFogColumn_8(void); void R_DrawColumnShadowed_8(void); +#ifndef NOWATER +void R_DrawTranslucentWaterSpan_8(void); + +extern INT32 ds_bgofs; +extern INT32 ds_waterofs; +#endif + // ------------------ // 16bpp DRAWING CODE // ------------------ diff --git a/src/r_draw8.c b/src/r_draw8.c index 8a2d37fb3..77406f83c 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -105,8 +105,6 @@ void R_DrawColumn_8(void) } } -#define TRANSPARENTPIXEL 255 - void R_Draw2sMultiPatchColumn_8(void) { INT32 count; @@ -543,16 +541,19 @@ void R_DrawTranslatedColumn_8(void) */ void R_DrawSpan_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; + size_t count = (ds_x2 - ds_x1 + 1); + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -561,62 +562,88 @@ void R_DrawSpan_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; if (dest+8 > deststop) return; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - dest[1] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - dest[2] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + x %= ds_flatwidth; + y %= ds_flatheight; - dest[3] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + *dest++ = colormap[source[((y * ds_flatwidth) + x)]]; + xposition += xstep; + yposition += ystep; + } } - while (count-- && dest <= deststop) + else { - *dest++ = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + dest[0] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[1] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[2] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[3] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[4] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[5] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[6] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[7] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count-- && dest <= deststop) + { + *dest++ = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + } } } @@ -697,7 +724,24 @@ void R_DrawTiltedSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; iz += ds_sz.x; uz += ds_su.x; @@ -734,7 +778,24 @@ void R_DrawTiltedSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; u += stepu; v += stepv; @@ -750,7 +811,24 @@ void R_DrawTiltedSpan_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; } else { @@ -771,7 +849,24 @@ void R_DrawTiltedSpan_8(void) for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; u += stepu; v += stepv; @@ -832,7 +927,24 @@ void R_DrawTiltedTranslucentSpan_8(void) v = (INT64)(vz*z) + viewy; colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; iz += ds_sz.x; uz += ds_su.x; @@ -869,7 +981,24 @@ void R_DrawTiltedTranslucentSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; u += stepu; v += stepv; @@ -885,7 +1014,24 @@ void R_DrawTiltedTranslucentSpan_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); } else { @@ -906,7 +1052,24 @@ void R_DrawTiltedTranslucentSpan_8(void) for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; u += stepu; v += stepv; @@ -967,9 +1130,28 @@ void R_DrawTiltedSplat_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) *dest = colormap[val]; + dest++; iz += ds_sz.x; uz += ds_su.x; @@ -1006,7 +1188,24 @@ void R_DrawTiltedSplat_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; dest++; @@ -1024,7 +1223,24 @@ void R_DrawTiltedSplat_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; } @@ -1048,6 +1264,24 @@ void R_DrawTiltedSplat_8(void) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; dest++; @@ -1065,17 +1299,21 @@ void R_DrawTiltedSplat_8(void) */ void R_DrawSplat_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; + size_t count = (ds_x2 - ds_x1 + 1); UINT32 val; + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the // texture with two shifts, an OR and one AND. (see below) @@ -1083,99 +1321,125 @@ void R_DrawSplat_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - // - // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[0] = colormap[val]; - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[1] = colormap[val]; - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[2] = colormap[val]; - xposition += xstep; - yposition += ystep; + x %= ds_flatwidth; + y %= ds_flatheight; - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[3] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[4] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[5] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[6] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[7] = colormap[val]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + val = source[((y * ds_flatwidth) + x)]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest++; + xposition += xstep; + yposition += ystep; + } } - while (count--) + else { - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + // + // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[0] = colormap[val]; + xposition += xstep; + yposition += ystep; - dest++; - xposition += xstep; - yposition += ystep; + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[1] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[2] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[3] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[4] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[5] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[6] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[7] = colormap[val]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count-- && dest <= deststop) + { + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest++; + xposition += xstep; + yposition += ystep; + } } } @@ -1184,16 +1448,20 @@ void R_DrawSplat_8 (void) */ void R_DrawTranslucentSplat_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; - UINT8 val; + size_t count = (ds_x2 - ds_x1 + 1); + UINT32 val; + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -1202,79 +1470,107 @@ void R_DrawTranslucentSplat_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; + x %= ds_flatwidth; + y %= ds_flatheight; - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + val = source[((y * ds_flatwidth) + x)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } - while (count--) + else { - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; - dest++; - xposition += xstep; - yposition += ystep; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count-- && dest <= deststop) + { + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } } @@ -1283,15 +1579,20 @@ void R_DrawTranslucentSplat_8 (void) */ void R_DrawTranslucentSpan_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; + size_t count = (ds_x2 - ds_x1 + 1); + UINT32 val; + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -1300,63 +1601,161 @@ void R_DrawTranslucentSpan_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - dest[1] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - dest[2] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; + x %= ds_flatwidth; + y %= ds_flatheight; - dest[3] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - dest[4] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - dest[5] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - dest[6] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - dest[7] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + val = ((y * ds_flatwidth) + x); + *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } - while (count--) + else { - *dest = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + *dest); - dest++; - xposition += xstep; - yposition += ystep; + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + dest[0] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; + + dest[1] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; + + dest[2] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; + + dest[3] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + dest[4] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + dest[5] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + dest[6] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + dest[7] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count-- && dest <= deststop) + { + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } } +#ifndef NOWATER +void R_DrawTranslucentWaterSpan_8(void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + UINT8 *dsrc; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + + size_t count = (ds_x2 - ds_x1 + 1); + + xposition = ds_xfrac; yposition = (ds_yfrac + ds_waterofs); + xstep = ds_xstep; ystep = ds_ystep; + + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; + + if (!ds_powersoftwo) + { + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest++ = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + } + } + else + { + while (count-- && dest <= deststop) + { + *dest++ = colormap[*(ds_transmap + (source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + } + } +} +#endif + /** \brief The R_DrawFogSpan_8 function Draws the actual span with fogging. */ diff --git a/src/r_plane.c b/src/r_plane.c index 2f6f97240..de5bf9f00 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -127,91 +127,13 @@ void R_InitPlanes(void) // viewheight #ifndef NOWATER -static INT32 bgofs; +INT32 ds_bgofs; +INT32 ds_waterofs; + static INT32 wtofs=0; -static INT32 waterofs; static boolean itswater; #endif -#ifndef NOWATER -static void R_DrawTranslucentWaterSpan_8(void) -{ - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; - - UINT8 *source; - UINT8 *colormap; - UINT8 *dest; - UINT8 *dsrc; - - size_t count; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = (ds_yfrac + waterofs) << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; - - source = ds_source; - colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; - dsrc = screens[1] + (ds_y+bgofs)*vid.width + ds_x1; - count = ds_x2 - ds_x1 + 1; - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[1] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[2] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[3] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count--) - { - *dest++ = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - } -} -#endif - void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { angle_t angle, planecos, planesin; @@ -258,17 +180,17 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { const INT32 yay = (wtofs + (distance>>9) ) & 8191; // ripples da water texture - bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; + ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; angle = (currentplane->viewangle + currentplane->plangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; angle = (angle + 2048) & 8191; // 90 degrees - ds_xfrac += FixedMul(FINECOSINE(angle), (bgofs<=viewheight) - bgofs = viewheight-y-1; - if (y+bgofs<0) - bgofs = -y; + if (y+ds_bgofs>=viewheight) + ds_bgofs = viewheight-y-1; + if (y+ds_bgofs<0) + ds_bgofs = -y; } #endif @@ -680,7 +602,7 @@ void R_DrawPlanes(void) } } #ifndef NOWATER - waterofs = (leveltime & 1)*16384; + ds_waterofs = (leveltime & 1)*16384; wtofs = leveltime * 140; #endif } @@ -728,13 +650,156 @@ static void R_DrawSkyPlane(visplane_t *pl) } } +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 UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng) +{ + UINT8 *flat; + textureflat_t *texflat = &texflats[levelflat->texturenum]; + patch_t *patch = NULL; + boolean texturechanged = (leveltexture ? (levelflat->texturenum != levelflat->lasttexturenum) : false); + + // Check if the texture changed. + if (leveltexture && (!texturechanged)) + { + if (texflat != NULL && texflat->flat) + { + flat = 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) + { + 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_TextureToFlat(levelflat->texturenum, texflat->flat); + flat = texflat->flat; + + levelflat->flatpatch = flat; + levelflat->width = ds_flatwidth; + levelflat->height = ds_flatheight; + } + else + { + patch = (patch_t *)ds_source; +#ifndef NO_PNG_LUMPS + if (ispng) + { + levelflat->flatpatch = R_PNGToFlat(levelflat, ds_source, W_LumpLength(levelflat->lumpnum)); + levelflat->topoffset = levelflat->leftoffset = 0; + ds_flatwidth = levelflat->width; + ds_flatheight = levelflat->height; + } + else +#endif + { + levelflat->width = ds_flatwidth = SHORT(patch->width); + levelflat->height = ds_flatheight = SHORT(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_PatchToFlat(patch, levelflat->flatpatch); + } + flat = levelflat->flatpatch; + } + } + else + { + flat = levelflat->flatpatch; + ds_flatwidth = levelflat->width; + ds_flatheight = levelflat->height; + + xoffs += levelflat->leftoffset; + yoffs += levelflat->topoffset; + } + + levelflat->lasttexturenum = levelflat->texturenum; + return flat; +} + void R_DrawSinglePlane(visplane_t *pl) { + UINT8 *flat; INT32 light = 0; INT32 x; INT32 stop, angle; size_t size; ffloor_t *rover; + levelflat_t *levelflat; if (!(pl->minx <= pl->maxx)) return; @@ -874,64 +939,43 @@ void R_DrawSinglePlane(visplane_t *pl) viewangle = pl->viewangle+pl->plangle; } - currentplane = pl; - - ds_source = (UINT8 *) - W_CacheLumpNum(levelflats[pl->picnum].lumpnum, - PU_STATIC); // Stay here until Z_ChangeTag - - size = W_LumpLength(levelflats[pl->picnum].lumpnum); - - switch (size) - { - 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; - } - xoffs = pl->xoffs; yoffs = pl->yoffs; planeheight = abs(pl->height - pl->viewz); + currentplane = pl; + levelflat = &levelflats[pl->picnum]; + size = W_LumpLength(levelflat->lumpnum); + ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag + + // Check if the flat is actually a wall texture. + if (levelflat->texturenum != 0 && levelflat->texturenum != -1) + flat = R_GetPatchFlat(levelflat, true, false); +#ifndef NO_PNG_LUMPS + // Maybe it's a PNG?! + else if (R_IsLumpPNG(ds_source, size)) + flat = R_GetPatchFlat(levelflat, false, true); +#endif + // Maybe it's just a patch, then? + else if (R_CheckIfPatch(levelflat->lumpnum)) + flat = R_GetPatchFlat(levelflat, false, false); + // It's a raw flat. + else + { + R_CheckFlatLength(size); + flat = ds_source; + } + + Z_ChangeTag(ds_source, PU_CACHE); + ds_source = flat; + + if (ds_source == NULL) + return; + + // 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; @@ -945,60 +989,63 @@ void R_DrawSinglePlane(visplane_t *pl) floatv3_t p, m, n; float ang; float vx, vy, vz; + float fudge = 0; // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly // use this as a temp var to store P_GetZAt's return value each time fixed_t temp; - // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red - const float fudge = ((1<plangle & (ANGLE_90-1)); yoffs *= 1; - if (hack) + if (ds_powersoftwo) { - /* - Essentially: We can't & the components along the regular axes when the plane is rotated. - This is because the distance on each regular axis in order to loop is different. - We rotate them, & the components, add them together, & them again, and then rotate them back. - These three seperate & operations are done per axis in order to prevent overflows. - toast 10/04/17 - */ - const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT); - const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); + // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red + fudge = ((1<>ANGLETOFINESHIFT); + const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); - const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); + const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); - fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); - fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); + fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); + fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); - temp = ox & modmask; - oy &= modmask; - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); + temp = ox & modmask; + oy &= modmask; + ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction + oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); - yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); + temp = xoffs; + xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); + yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); - temp = xoffs & modmask; - yoffs &= modmask; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); + temp = xoffs & modmask; + yoffs &= modmask; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); + xoffs -= (pl->slope->o.x - ox); + yoffs += (pl->slope->o.y + oy); + } + else + { + xoffs &= ((1 << (32-nflatshiftup))-1); + yoffs &= ((1 << (32-nflatshiftup))-1); + xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + } + xoffs = (fixed_t)(xoffs*fudge); + yoffs = (fixed_t)(yoffs/fudge); } - else - { - xoffs &= ((1 << (32-nflatshiftup))-1); - yoffs &= ((1 << (32-nflatshiftup))-1); - xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - } - - xoffs = (fixed_t)(xoffs*fudge); - yoffs = (fixed_t)(yoffs/fudge); vx = FIXED_TO_FLOAT(pl->viewx+xoffs); vy = FIXED_TO_FLOAT(pl->viewy-yoffs); @@ -1033,13 +1080,16 @@ void R_DrawSinglePlane(visplane_t *pl) temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang))); n.y = FIXED_TO_FLOAT(temp) - zeroheight; - m.x /= fudge; - m.y /= fudge; - m.z /= fudge; + if (ds_powersoftwo) + { + m.x /= fudge; + m.y /= fudge; + m.z /= fudge; - n.x *= fudge; - n.y *= fudge; - n.z *= fudge; + n.x *= fudge; + n.y *= fudge; + n.z *= fudge; + } // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. #define CROSS(d, v1, v2) \ @@ -1056,14 +1106,26 @@ void R_DrawSinglePlane(visplane_t *pl) ds_sz.z *= focallengthf; // Premultiply the texture vectors with the scale factors + if (ds_powersoftwo) + { #define SFMULT 65536.f*(1< Date: Tue, 10 Sep 2019 14:44:04 +0100 Subject: [PATCH 078/133] Update SPR2 defaulting for SPR2_CNT1. --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 04a9121b8..3bee08529 100644 --- a/src/info.c +++ b/src/info.c @@ -679,7 +679,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_TAL9, // SPR2_TALA, SPR2_TAL0, // SPR2_TALB, - 0, // SPR2_CNT1, + SPR2_WAIT, // SPR2_CNT1, SPR2_FALL, // SPR2_CNT2, SPR2_SPNG, // SPR2_CNT3, SPR2_CNT1, // SPR2_CNT4, From 25e975e781a60559df7e9cd743e9f1e502dcc4f7 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 10 Sep 2019 15:06:20 +0100 Subject: [PATCH 079/133] Add the new s1, s2, cd, 3db and kc sounds to sounds.c and sounds.h! These have been in srb2.pk3 for a while, but they were inaccessible because of not having in-game references. --- src/sounds.c | 318 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/sounds.h | 301 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 619 insertions(+) diff --git a/src/sounds.c b/src/sounds.c index 11ba1e0bc..43225a615 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -35,6 +35,23 @@ sfxinfo_t S_sfx[NUMSFX] = // name, singularity, priority, pitch, volume, data, length, skinsound, usefulness, lumpnum, caption {"none" , false, 0, 0, -1, NULL, 0, -1, -1, LUMPERROR, "///////////////////////////////"}, // maximum length + // A HUMBLE REQUEST FROM YOUR FRIENDLY NEIGHBORHOOD toaster! + // + // If you see a caption that's just "" (shows the lumpname in-game), + // and you intend to use the sound associated with it in a mod, + // PLEASE give it a caption through SOC or Lua. + // + // If the first character of the caption is '/', no caption will be + // produced; only do this for "unimportant" sounds that aren't used + // to indicate gameplay. + // + // (to whomstever updates the sounds list wiki page for 2.2, please + // either copy this comment across, or make sure its desire is + // codified in the initial paragraph of the page.) + // + // Closed Captioning may be a niche feature, but it's an important one. + // Thank you! ^u^ + // Skin Sounds {"altdi1", false, 192, 16, -1, NULL, 0, SKSPLDET1, -1, LUMPERROR, "Dying"}, {"altdi2", false, 192, 16, -1, NULL, 0, SKSPLDET2, -1, LUMPERROR, "Dying"}, @@ -290,6 +307,139 @@ sfxinfo_t S_sfx[NUMSFX] = {"brakrl", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Rocket launch"}, {"brakrx", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Rocket explosion"}, + // Sonic 1 sounds + {"s1a0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1aa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1af", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1bb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1bc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1bd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1be", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1bf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ca", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ce", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + + // Sonic 2 sounds + {"s220", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s221", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s222", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s223", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s224", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s225", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s226", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s227", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s228", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s229", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s230", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s231", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s232", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s233", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s234", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s235", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s236", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s237", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s238", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s239", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s240", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s241", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s242", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s243", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s244", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s245", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s246", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s247", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s248", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s249", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s250", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s251", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s252", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s253", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s254", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s255", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s256", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s257", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s258", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s259", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s260", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s261", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s262", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s263", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s264", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s265", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s266", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s267", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s268", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s269", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s270", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + // S3&K sounds {"s3k33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // stereo in original game, identical to latter {"s3k34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // mono in original game, identical to previous @@ -492,6 +642,174 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kdbs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running on water"}, {"s3kdbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running on water"}, // ditto + // 3D Blast sounds (the "missing" ones are direct copies of S3K's, no minor differences what-so-ever) + {"3db06", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Collection"}, + {"3db09", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Peep"}, + {"3db14", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Chirp"}, + {"3db16", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + + // Sonic CD sounds + {"cdfm00", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Skid"}, + {"cdfm01", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm02", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"}, + {"cdfm03", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Dying"}, + {"cdfm04", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ring loss"}, + {"cdfm05", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, + {"cdfm06", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pop"}, + {"cdfm07", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Shield"}, + {"cdfm08", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spring"}, + {"cdfm09", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm10", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm11", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm12", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm13", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm14", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm15", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm16", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm17", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm18", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm19", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm20", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm21", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm22", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm23", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm24", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm25", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm26", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm27", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm28", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm29", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble gasp"}, + {"cdfm30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"}, + {"cdfm31", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"}, + {"cdfm32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drowning"}, + {"cdfm39", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Extra time"}, + {"cdfm45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"}, + {"cdfm50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"}, + {"cdfm57", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm64", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm70", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm74", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm75", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm76", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm77", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm78", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm79", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdpcm0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Future."}, + {"cdpcm1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Past."}, + {"cdpcm2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "All right!"}, + {"cdpcm3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "I'm outta here..."}, + {"cdpcm4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Yes!"}, + {"cdpcm5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Yeah!"}, + {"cdpcm6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Giggles"}, + {"cdpcm7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Eep!"}, + {"cdpcm8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdpcm9", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, + + // Knuckles Chaotix sounds + {"kc2a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2e", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2f", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc31", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc39", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Confirm"}, + {"kc43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc46", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Select"}, + {"kc49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc51", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc57", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Sheer terror"}, + {"kc58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc59", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Shrink"}, + {"kc5a", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Grow"}, + {"kc5b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc64", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Terrifying rumble"}, + {"kc65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ascending"}, + {"kc6c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + // skin sounds free slots to add sounds at run time (Boris HACK!!!) // initialized to NULL }; diff --git a/src/sounds.h b/src/sounds.h index 20f89d9fb..674f51d79 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -356,6 +356,139 @@ typedef enum sfx_brakrl, // Rocket launcher sfx_brakrx, // Rocket explodes + // S1 sounds + sfx_s1a0, + sfx_s1a1, + sfx_s1a2, + sfx_s1a3, + sfx_s1a4, + sfx_s1a5, + sfx_s1a6, + sfx_s1a7, + sfx_s1a8, + sfx_s1a9, + sfx_s1aa, + sfx_s1ab, + sfx_s1ac, + sfx_s1ad, + sfx_s1ae, + sfx_s1af, + sfx_s1b0, + sfx_s1b1, + sfx_s1b2, + sfx_s1b3, + sfx_s1b4, + sfx_s1b5, + sfx_s1b6, + sfx_s1b7, + sfx_s1b8, + sfx_s1b9, + sfx_s1ba, + sfx_s1bb, + sfx_s1bc, + sfx_s1bd, + sfx_s1be, + sfx_s1bf, + sfx_s1c0, + sfx_s1c1, + sfx_s1c2, + sfx_s1c3, + sfx_s1c4, + sfx_s1c5, + sfx_s1c6, + sfx_s1c7, + sfx_s1c8, + sfx_s1c9, + sfx_s1ca, + sfx_s1cb, + sfx_s1cc, + sfx_s1cd, + sfx_s1ce, + sfx_s1cf, + + // S2 sounds + sfx_s220, + sfx_s221, + sfx_s222, + sfx_s223, + sfx_s224, + sfx_s225, + sfx_s226, + sfx_s227, + sfx_s228, + sfx_s229, + sfx_s22a, + sfx_s22b, + sfx_s22c, + sfx_s22d, + sfx_s22e, + sfx_s22f, + sfx_s230, + sfx_s231, + sfx_s232, + sfx_s233, + sfx_s234, + sfx_s235, + sfx_s236, + sfx_s237, + sfx_s238, + sfx_s239, + sfx_s23a, + sfx_s23b, + sfx_s23c, + sfx_s23d, + sfx_s23e, + sfx_s23f, + sfx_s240, + sfx_s241, + sfx_s242, + sfx_s243, + sfx_s244, + sfx_s245, + sfx_s246, + sfx_s247, + sfx_s248, + sfx_s249, + sfx_s24a, + sfx_s24b, + sfx_s24c, + sfx_s24d, + sfx_s24e, + sfx_s24f, + sfx_s250, + sfx_s251, + sfx_s252, + sfx_s253, + sfx_s254, + sfx_s255, + sfx_s256, + sfx_s257, + sfx_s258, + sfx_s259, + sfx_s25a, + sfx_s25b, + sfx_s25c, + sfx_s25d, + sfx_s25e, + sfx_s25f, + sfx_s260, + sfx_s261, + sfx_s262, + sfx_s263, + sfx_s264, + sfx_s265, + sfx_s266, + sfx_s267, + sfx_s268, + sfx_s269, + sfx_s26a, + sfx_s26b, + sfx_s26c, + sfx_s26d, + sfx_s26e, + sfx_s26f, + sfx_s270, + // S3&K sounds sfx_s3k33, sfx_s3k34, @@ -558,6 +691,174 @@ typedef enum sfx_s3kdbs, sfx_s3kdbl, + // 3DB sounds + sfx_3db06, + sfx_3db09, + sfx_3db14, + sfx_3db16, + + // SCD sounds + sfx_cdfm00, + sfx_cdfm01, + sfx_cdfm02, + sfx_cdfm03, + sfx_cdfm04, + sfx_cdfm05, + sfx_cdfm06, + sfx_cdfm07, + sfx_cdfm08, + sfx_cdfm09, + sfx_cdfm10, + sfx_cdfm11, + sfx_cdfm12, + sfx_cdfm13, + sfx_cdfm14, + sfx_cdfm15, + sfx_cdfm16, + sfx_cdfm17, + sfx_cdfm18, + sfx_cdfm19, + sfx_cdfm20, + sfx_cdfm21, + sfx_cdfm22, + sfx_cdfm23, + sfx_cdfm24, + sfx_cdfm25, + sfx_cdfm26, + sfx_cdfm27, + sfx_cdfm28, + sfx_cdfm29, + sfx_cdfm30, + sfx_cdfm31, + sfx_cdfm32, + sfx_cdfm33, + sfx_cdfm34, + sfx_cdfm35, + sfx_cdfm36, + sfx_cdfm37, + sfx_cdfm38, + sfx_cdfm39, + sfx_cdfm40, + sfx_cdfm41, + sfx_cdfm42, + sfx_cdfm43, + sfx_cdfm44, + sfx_cdfm45, + sfx_cdfm46, + sfx_cdfm47, + sfx_cdfm48, + sfx_cdfm49, + sfx_cdfm50, + sfx_cdfm51, + sfx_cdfm52, + sfx_cdfm53, + sfx_cdfm54, + sfx_cdfm55, + sfx_cdfm56, + sfx_cdfm57, + sfx_cdfm58, + sfx_cdfm59, + sfx_cdfm60, + sfx_cdfm61, + sfx_cdfm62, + sfx_cdfm63, + sfx_cdfm64, + sfx_cdfm65, + sfx_cdfm66, + sfx_cdfm67, + sfx_cdfm68, + sfx_cdfm69, + sfx_cdfm70, + sfx_cdfm71, + sfx_cdfm72, + sfx_cdfm73, + sfx_cdfm74, + sfx_cdfm75, + sfx_cdfm76, + sfx_cdfm77, + sfx_cdfm78, + sfx_cdfm79, + sfx_cdpcm0, + sfx_cdpcm1, + sfx_cdpcm2, + sfx_cdpcm3, + sfx_cdpcm4, + sfx_cdpcm5, + sfx_cdpcm6, + sfx_cdpcm7, + sfx_cdpcm8, + sfx_cdpcm9, + + // KC sounds + sfx_kc2a, + sfx_kc2b, + sfx_kc2c, + sfx_kc2d, + sfx_kc2e, + sfx_kc2f, + sfx_kc30, + sfx_kc31, + sfx_kc32, + sfx_kc33, + sfx_kc34, + sfx_kc35, + sfx_kc36, + sfx_kc37, + sfx_kc38, + sfx_kc39, + sfx_kc3a, + sfx_kc3b, + sfx_kc3c, + sfx_kc3d, + sfx_kc3e, + sfx_kc3f, + sfx_kc40, + sfx_kc41, + sfx_kc42, + sfx_kc43, + sfx_kc44, + sfx_kc45, + sfx_kc46, + sfx_kc47, + sfx_kc48, + sfx_kc49, + sfx_kc4a, + sfx_kc4b, + sfx_kc4c, + sfx_kc4d, + sfx_kc4e, + sfx_kc4f, + sfx_kc50, + sfx_kc51, + sfx_kc52, + sfx_kc53, + sfx_kc54, + sfx_kc55, + sfx_kc56, + sfx_kc57, + sfx_kc58, + sfx_kc59, + sfx_kc5a, + sfx_kc5b, + sfx_kc5c, + sfx_kc5d, + sfx_kc5e, + sfx_kc5f, + sfx_kc60, + sfx_kc61, + sfx_kc62, + sfx_kc63, + sfx_kc64, + sfx_kc65, + sfx_kc66, + sfx_kc67, + sfx_kc68, + sfx_kc69, + sfx_kc6b, + sfx_kc6c, + sfx_kc6d, + sfx_kc6e, + // free slots for S_AddSoundFx() at run-time -------------------- sfx_freeslot0, // From 4be108fa76c36aa9c8934a6925bd3168cf7b887b Mon Sep 17 00:00:00 2001 From: James Date: Tue, 10 Sep 2019 10:11:03 -0400 Subject: [PATCH 080/133] Lach has blessed us with a remade cam_adjust. --- src/p_local.h | 4 ++-- src/p_user.c | 37 +++++++++++++++++++++++++++++++------ src/r_main.c | 2 ++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index c956310ef..bbece506b 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -115,10 +115,10 @@ typedef struct camera_s extern camera_t camera, camera2; extern consvar_t cv_cam_dist, cv_cam_still, cv_cam_height; -extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed, cv_cam_orbit; +extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed, cv_cam_orbit, cv_cam_adjust; extern consvar_t cv_cam2_dist, cv_cam2_still, cv_cam2_height; -extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed, cv_cam2_orbit; +extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed, cv_cam2_orbit, cv_cam2_adjust; extern fixed_t t_cam_dist, t_cam_height, t_cam_rotate; extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate; diff --git a/src/p_user.c b/src/p_user.c index 97ab5894a..53e9704ff 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9295,6 +9295,7 @@ consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NUL consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_orbit = {"cam_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_adjust = {"cam_adjust", "Off", CV_SAVE|CV_SHOWMODIF, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_height = {"cam2_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -9302,6 +9303,7 @@ consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, N consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_orbit = {"cam2_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam2_adjust = {"cam2_adjust", "Off", CV_SAVE|CV_SHOWMODIF, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; fixed_t t_cam_dist = -42; fixed_t t_cam_height = -42; @@ -9570,6 +9572,35 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (checkdist < 128*FRACUNIT) checkdist = 128*FRACUNIT; + if (!(twodlevel || (mo->flags2 & MF2_TWOD)) && !(player->powers[pw_carry] == CR_NIGHTSMODE)) // This block here is like 90% Lach's work, thanks bud + { + if (!cameranoclip && !resetcalled) + { + if ((P_AproxDistance(mo->x-thiscam->x-thiscam->momx, mo->y-thiscam->y-thiscam->momy) > FixedDiv(mo->momz+dist, camspeed)) || (abs(thiscam->z - player->mo->z) > (FixedDiv(mo->momz+dist, camspeed)))) //If the camera is too far away, + { + P_ResetCamera(player, thiscam); //Reset the camera + return true; + } + } + if ((thiscam == &camera && cv_cam_adjust.value) || (thiscam == &camera2 && cv_cam2_adjust.value)) + { + if (!(mo->eflags & MFE_JUSTHITFLOOR) && (P_IsObjectOnGround(mo)) // Check that player is grounded + && thiscam->ceilingz - thiscam->floorz >= P_GetPlayerHeight(player)) // Check that camera's sector is large enough for the player to fit into, at least + { + if (mo->eflags & MFE_VERTICALFLIP) // if player is upside-down + { + //z = min(z, thiscam->ceilingz); // solution 1: change new z coordinate to be at LEAST its ground height + z += min(thiscam->ceilingz - mo->z, 0); // solution 2: change new z coordinate by the difference between camera's ground and top of player + } + else // player is not upside-down + { + //z = max(z, thiscam->floorz); // solution 1: change new z coordinate to be at LEAST its ground height + z += max(thiscam->floorz - mo->z - mo->height, 0); // solution 2: change new z coordinate by the difference between camera's ground and top of player + } + } + } + } + if ((thiscam == &camera && cv_cam_orbit.value) || (thiscam == &camera2 && cv_cam2_orbit.value)) //Sev here, I'm guessing this is where orbital cam lives { distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); @@ -9584,12 +9615,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), distxy); y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), distxy); - if (!(twodlevel || (mo->flags2 & MF2_TWOD)) && !(player->powers[pw_carry] == CR_NIGHTSMODE) && !(player->exiting)) //Which is why I'm slapping my cam reset code in here too - { - if ((P_AproxDistance(player->mo->x-thiscam->x-thiscam->momx, player->mo->y-thiscam->y-thiscam->momy) > ((player->speed+camdist)*2)) || (abs(thiscam->z - player->mo->z) > ((player->speed+camdist)*2))) - P_ResetCamera(player, thiscam); - } - #if 0 if (twodlevel || (mo->flags2 & MF2_TWOD)) { diff --git a/src/r_main.c b/src/r_main.c index eabfa0384..9cce41288 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1183,6 +1183,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_cam_rotate); CV_RegisterVar(&cv_cam_rotspeed); CV_RegisterVar(&cv_cam_orbit); + CV_RegisterVar(&cv_cam_adjust); CV_RegisterVar(&cv_cam2_dist); CV_RegisterVar(&cv_cam2_still); @@ -1191,6 +1192,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_cam2_rotate); CV_RegisterVar(&cv_cam2_rotspeed); CV_RegisterVar(&cv_cam2_orbit); + CV_RegisterVar(&cv_cam2_adjust); CV_RegisterVar(&cv_showhud); CV_RegisterVar(&cv_translucenthud); From f1cc17ea02abdb2a2a44801c922695c7ff9400f5 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 10 Sep 2019 17:25:21 -0300 Subject: [PATCH 081/133] Enable usage of R_DrawSpan_8_MMX if drawing a flat with powers-of-two dimensions --- src/r_plane.c | 12 +++++++++++- src/screen.c | 5 +++-- src/screen.h | 1 + 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index de5bf9f00..51a69336e 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -652,7 +652,13 @@ static void R_DrawSkyPlane(visplane_t *pl) boolean R_CheckPowersOfTwo(void) { - return (ds_powersoftwo = ((!((ds_flatwidth & (ds_flatwidth - 1)) || (ds_flatheight & (ds_flatheight - 1)))) && (ds_flatwidth == ds_flatheight))); + if (ds_flatwidth & (ds_flatwidth - 1)) + ds_powersoftwo = false; + else if (ds_flatheight & (ds_flatheight - 1)) + ds_powersoftwo = false; + else if (ds_flatwidth == ds_flatheight) + ds_powersoftwo = true; + return ds_powersoftwo; } void R_CheckFlatLength(size_t size) @@ -974,7 +980,11 @@ void R_DrawSinglePlane(visplane_t *pl) // Check if the flat has dimensions that are powers-of-two numbers. if (R_CheckPowersOfTwo()) + { R_CheckFlatLength(ds_flatwidth * ds_flatheight); + if (spanfunc == basespanfunc) + spanfunc = mmxspanfunc; + } if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; diff --git a/src/screen.c b/src/screen.c index 4bace5239..547036a60 100644 --- a/src/screen.c +++ b/src/screen.c @@ -49,6 +49,7 @@ void (*fuzzcolfunc)(void); // standard fuzzy effect column drawer void (*transcolfunc)(void); // translation column drawer void (*shadecolfunc)(void); // smokie test.. void (*spanfunc)(void); // span drawer, use a 64x64 tile +void (*mmxspanfunc)(void); // span drawer in MMX assembly void (*splatfunc)(void); // span drawer w/ transparency void (*basespanfunc)(void); // default span func for color mode void (*transtransfunc)(void); // translucent translated column drawer @@ -112,7 +113,7 @@ void SCR_SetMode(void) // if (true)//vid.bpp == 1) //Always run in 8bpp. todo: remove all 16bpp code? { - spanfunc = basespanfunc = R_DrawSpan_8; + spanfunc = basespanfunc = mmxspanfunc = R_DrawSpan_8; splatfunc = R_DrawSplat_8; transcolfunc = R_DrawTranslatedColumn_8; transtransfunc = R_DrawTranslatedTranslucentColumn_8; @@ -133,7 +134,7 @@ void SCR_SetMode(void) //fuzzcolfunc = R_DrawTranslucentColumn_8_ASM; walldrawerfunc = R_DrawWallColumn_8_MMX; twosmultipatchfunc = R_Draw2sMultiPatchColumn_8_MMX; - //spanfunc = basespanfunc = R_DrawSpan_8_MMX; + mmxspanfunc = R_DrawSpan_8_MMX; } else { diff --git a/src/screen.h b/src/screen.h index 7aa6fdb63..3554b5520 100644 --- a/src/screen.h +++ b/src/screen.h @@ -123,6 +123,7 @@ extern void (*transcolfunc)(void); extern void (*shadecolfunc)(void); extern void (*spanfunc)(void); extern void (*basespanfunc)(void); +extern void (*mmxspanfunc)(void); extern void (*splatfunc)(void); extern void (*transtransfunc)(void); extern void (*twosmultipatchfunc)(void); From ed5e8c486cfceba32b548ba5b5591c2b46e70b7f Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 11 Sep 2019 00:50:51 +0100 Subject: [PATCH 082/133] Continue screen! With aaaaaall the new assets to go with it. * https://cdn.discordapp.com/attachments/428262628893261828/621129794045870108/srb20077.gif * https://cdn.discordapp.com/attachments/428262628893261828/621129785124585502/srb20078.gif * I will be accepting no further questions at this time. --- src/f_finale.c | 250 +++++++++++++++++++++++++++++++++++++++++++------ src/r_things.c | 4 + src/r_things.h | 2 + src/st_stuff.c | 2 +- src/st_stuff.h | 1 + src/v_video.c | 14 +-- src/y_inter.c | 2 +- 7 files changed, 238 insertions(+), 37 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index e44add4d1..ee22ecb2f 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2465,6 +2465,11 @@ void F_TitleDemoTicker(void) // ========== // CONTINUE // ========== + +static skin_t *contskins[2]; +static UINT8 cont_spr2[2][6]; +static UINT8 *contcolormaps[2]; + void F_StartContinue(void) { I_Assert(!netgame && !multiplayer); @@ -2488,7 +2493,44 @@ void F_StartContinue(void) S_ChangeMusicInternal("_conti", false); S_StopSounds(); - timetonext = TICRATE*11; + contskins[0] = &skins[players[consoleplayer].skin]; + cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT1, NULL); + cont_spr2[0][2] = contskins[0]->contangle & 7; + contcolormaps[0] = R_GetTranslationColormap(players[consoleplayer].skin, players[consoleplayer].skincolor, GTC_CACHE); + cont_spr2[0][4] = contskins[0]->sprites[cont_spr2[0][0]].numframes; + cont_spr2[0][5] = max(1, contskins[0]->contspeed); + + if (botskin) + { + INT32 secondplaya; + + if (secondarydisplayplayer != consoleplayer) + secondplaya = secondarydisplayplayer; + else // HACK + secondplaya = 1; + + contskins[1] = &skins[players[secondplaya].skin]; + cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT4, NULL); + cont_spr2[1][2] = (contskins[1]->contangle >> 3) & 7; + contcolormaps[1] = R_GetTranslationColormap(players[secondplaya].skin, players[secondplaya].skincolor, GTC_CACHE); + cont_spr2[1][4] = contskins[1]->sprites[cont_spr2[1][0]].numframes; + if (cont_spr2[1][0] == SPR2_CNT4) + cont_spr2[1][5] = 4; // sorry, this one is hardcoded + else + cont_spr2[1][5] = max(1, contskins[1]->contspeed); + } + else + { + contskins[1] = NULL; + contcolormaps[1] = NULL; + cont_spr2[1][0] = cont_spr2[1][2] = cont_spr2[1][4] = cont_spr2[1][5] = 0; + } + + cont_spr2[0][1] = cont_spr2[0][3] =\ + cont_spr2[1][1] = cont_spr2[1][3] = 0; + + timetonext = (11*TICRATE)+11; + continuetime = 0; } // @@ -2497,47 +2539,198 @@ void F_StartContinue(void) // void F_ContinueDrawer(void) { - patch_t *contsonic; - INT32 i, x = (BASEVIDWIDTH/2) + 4, ncontinues = players[consoleplayer].continues; - if (ncontinues > 20) - ncontinues = 20; + spritedef_t *sprdef; + spriteframe_t *sprframe; + patch_t *patch; + INT32 i, x = (BASEVIDWIDTH>>1), ncontinues = players[consoleplayer].continues; + char numbuf[9] = "CONTNUM*"; + tic_t timeleft = (timetonext/TICRATE); + INT32 offsx = 0, offsy = 0, lift[2] = {0, 0}; - if (imcontinuing) - contsonic = W_CachePatchName("CONT2", PU_CACHE); - else - contsonic = W_CachePatchName("CONT1", PU_CACHE); + if (continuetime >= 3*TICRATE) + { + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0); + return; + } V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - V_DrawCenteredString(BASEVIDWIDTH/2, 100, 0, "CONTINUE?"); - // Draw a Sonic! - V_DrawScaledPatch((BASEVIDWIDTH - SHORT(contsonic->width))/2, 32, 0, contsonic); + if (timetonext >= (11*TICRATE)+10) + return; - // Draw the continue markers! Show continues minus one. - x -= ncontinues * 6; - for (i = 0; i < ncontinues; ++i) - V_DrawContinueIcon(x + (i*12), 140, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); + V_DrawLevelTitle(x - (V_LevelNameWidth("CONTINUE")>>1), 16, 0, "CONTINUE"); - V_DrawCenteredString(BASEVIDWIDTH/2, 168, 0, va("\x82*\x80" " %02d " "\x82*\x80", timetonext/TICRATE)); + // Two stars... + patch = W_CachePatchName("CONTSTAR", PU_CACHE); + V_DrawScaledPatch(x-32, 160, 0, patch); + V_DrawScaledPatch(x+32, 160, 0, patch); + + // Time left! + if (timeleft > 9) + { + numbuf[7] = '1'; + V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_CACHE)); + numbuf[7] = '0'; + V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_CACHE)); + } + else + { + numbuf[7] = '0'+timeleft; + V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_CACHE)); + } + + // Draw the continue markers! Show continues. + if (ncontinues > 10) + { + if (!(continuetime & 1) || continuetime > 17) + V_DrawContinueIcon(x, 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); + V_DrawScaledPatch(x+12, 68-2, 0, stlivex); + V_DrawRightAlignedString(x+36, 69-5, 0, + va("%d",(imcontinuing ? ncontinues-1 : ncontinues))); + } + else + { + x += (ncontinues/2) * 30; + if (!(ncontinues & 1)) + x -= 15; + for (i = 0; i < ncontinues; ++i) + { + if (i == (ncontinues/2) && ((continuetime & 1) || continuetime > 17)) + continue; + V_DrawContinueIcon(x - (i*30), 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); + } + x = BASEVIDWIDTH>>1; + } + + // Spotlight + V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_CACHE)); + + // warping laser + if (continuetime) + { + INT32 w = min(continuetime, 28), brightness = (continuetime>>1) & 7; + if (brightness > 3) + brightness = 8-brightness; + V_DrawFadeFill(x-w, 0, w<<1, 140, 0, 0, (3+brightness)); + } + + if (contskins[1]) + { + if (continuetime > 15) + { + angle_t work = FixedAngle((10*(continuetime-15))<>ANGLETOFINESHIFT; + offsy = FINESINE(work)<<1; + offsx = (27*FINECOSINE(work))>>1; + } + else + offsx = 27<<(FRACBITS-1); + lift[1] = continuetime-10; + if (lift[1] < 0) + lift[1] = 0; + else if (lift[1] > TICRATE+5) + lift[1] = TICRATE+5; + } + + lift[0] = continuetime-5; + if (lift[0] < 0) + lift[0] = 0; + else if (lift[0] > TICRATE+5) + lift[0] = TICRATE+5; + +#define drawchar(dx, dy, n) {\ + sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\ + sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\ + patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_CACHE);\ + V_DrawFixedPatch((dx), (dy), FRACUNIT, (sprframe->flip & (1<= 0) + drawchar((BASEVIDWIDTH<<(FRACBITS-1))-offsx, ((140-lift[0])< (11*TICRATE)) + V_DrawFadeScreen(31, timetonext-(11*TICRATE)); + if (continuetime > ((3*TICRATE) - 10)) + V_DrawFadeScreen(0, (continuetime - ((3*TICRATE) - 10))); } void F_ContinueTicker(void) { if (!imcontinuing) { - // note the setup to prevent 2x reloading - if (timetonext >= 0) - timetonext--; - if (timetonext == 0) - Command_ExitGame_f(); + if (timetonext > 0) + { + if (!(--timetonext)) + { + Command_ExitGame_f(); + return; + } + } } else { - // note the setup to prevent 2x reloading - if (continuetime >= 0) - continuetime--; - if (continuetime == 0) + if (++continuetime == 3*TICRATE) + { G_Continue(); + return; + } + + if (continuetime > 5 && ((continuetime & 1) || continuetime > TICRATE) && (++cont_spr2[0][2]) >= 8) + cont_spr2[0][2] = 0; + + if (continuetime > 10 && (!(continuetime & 1) || continuetime > TICRATE+5) && (++cont_spr2[1][2]) >= 8) + cont_spr2[1][2] = 0; + + if (continuetime == (3*TICRATE)-10) + S_StartSound(NULL, sfx_cdfm56); // or 31 + else if (continuetime == 5) + { + cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT2, NULL); + cont_spr2[0][4] = contskins[0]->sprites[cont_spr2[0][0]].numframes; + cont_spr2[0][1] = cont_spr2[0][3] = 0; + cont_spr2[0][5] = 2; + } + else if (continuetime == TICRATE) + { + cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT3, NULL); + cont_spr2[0][4] = contskins[0]->sprites[cont_spr2[0][0]].numframes; + cont_spr2[0][1] = cont_spr2[0][3] = 0; + } + else if (contskins[1]) + { + if (continuetime == 10) + { + cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT2, NULL); + cont_spr2[1][4] = contskins[1]->sprites[cont_spr2[1][0]].numframes; + cont_spr2[1][1] = cont_spr2[1][3] = 0; + cont_spr2[1][5] = 2; + } + else if (continuetime == TICRATE+5) + { + cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT3, NULL); + cont_spr2[1][4] = contskins[1]->sprites[cont_spr2[1][0]].numframes; + cont_spr2[1][1] = cont_spr2[1][3] = 0; + } + } + } + + if ((++cont_spr2[0][3]) >= cont_spr2[0][5]) + { + cont_spr2[0][3] = 0; + if (++cont_spr2[0][1] >= cont_spr2[0][4]) + cont_spr2[0][1] = 0; + } + + if (contskins[1] && (++cont_spr2[1][3]) >= cont_spr2[1][5]) + { + cont_spr2[1][3] = 0; + if (++cont_spr2[1][1] >= cont_spr2[1][4]) + cont_spr2[1][1] = 0; } } @@ -2568,8 +2761,9 @@ boolean F_ContinueResponder(event_t *event) keypressed = true; imcontinuing = true; - continuetime = TICRATE; - S_StartSound(NULL, sfx_itemup); + S_StartSound(NULL, sfx_kc6b); + I_FadeSong(0, MUSICRATE, &S_StopMusic); + return true; } diff --git a/src/r_things.c b/src/r_things.c index 92f2b9460..bf4b3ca40 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2603,6 +2603,8 @@ static void Sk_SetDefaultValue(skin_t *skin) skin->followitem = 0; skin->highresscale = FRACUNIT; + skin->contspeed = 17; + skin->contangle = 0; skin->availability = 0; @@ -2907,6 +2909,8 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) GETINT(thrustfactor) GETINT(accelstart) GETINT(acceleration) + GETINT(contspeed) + GETINT(contangle) #undef GETINT #define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) skin->field = R_GetColorByName(value); diff --git a/src/r_things.h b/src/r_things.h index 9c3d16ab0..0fa9c4b94 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -122,6 +122,8 @@ typedef struct UINT8 prefoppositecolor; // if 0 use tables instead fixed_t highresscale; // scale of highres, default is 0.5 + UINT8 contspeed; // continue screen animation speed + UINT8 contangle; // initial angle on continue screen // specific sounds per skin sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table diff --git a/src/st_stuff.c b/src/st_stuff.c index b59d18143..c4f1327c0 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -64,12 +64,12 @@ patch_t *sbotime; // Time logo patch_t *sbocolon; // Colon for time patch_t *sboperiod; // Period for time centiseconds patch_t *livesback; // Lives icon background +patch_t *stlivex; static patch_t *nrec_timer; // Timer for NiGHTS records static patch_t *sborings; static patch_t *slidgame; static patch_t *slidtime; static patch_t *slidover; -static patch_t *stlivex; static patch_t *sboredrings; static patch_t *sboredtime; static patch_t *getall; // Special Stage HUD diff --git a/src/st_stuff.h b/src/st_stuff.h index 40574f46c..aaf01ca15 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -70,6 +70,7 @@ extern patch_t *sboperiod; extern patch_t *faceprefix[MAXSKINS]; // face status patches extern patch_t *superprefix[MAXSKINS]; // super face status patches extern patch_t *livesback; +extern patch_t *stlivex; extern patch_t *ngradeletters[7]; /** HUD location information (don't move this comment) diff --git a/src/v_video.c b/src/v_video.c index 082d84915..3b5a81170 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1064,17 +1064,17 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ // void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skincolor) { - if (skinnum < 0 || skinnum >= numskins || (skins[skinnum].flags & SF_HIRES)) - V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE)); - else + if (skinnum >= 0 && skinnum < numskins && skins[skinnum].sprites[SPR2_XTRA].numframes >= 4) { - spriteframe_t *sprframe = &skins[skinnum].sprites[SPR2_WAIT].spriteframes[0]; - patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spriteframe_t *sprframe = &sprdef->spriteframes[3]; + patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE); - // No variant for translucency - V_DrawTinyMappedPatch(x, y, flags, patch, colormap); + V_DrawMappedPatch(x, y, flags, patch, colormap); } + else + V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE)); } // diff --git a/src/y_inter.c b/src/y_inter.c index 975902ab0..1cb1b9cd8 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -429,7 +429,7 @@ void Y_IntermissionDrawer(void) { if ((data.spec.continues & 0x80) && i == continues-1 && (endtic < 0 || intertic%20 < 10)) break; - V_DrawContinueIcon(246 + xoffset5 - (i*12), 162+yoffset, 0, *data.spec.playerchar, *data.spec.playercolor); + V_DrawContinueIcon(246 + xoffset5 - (i*20), 162+yoffset, 0, *data.spec.playerchar, *data.spec.playercolor); } } } From ab1472bfc196f88af496e6d9300b3f670a3b136c Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 11 Sep 2019 13:30:24 +0100 Subject: [PATCH 083/133] Tweak gameovertics slightly to avoid having no sound for too long. --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 3e3e8d157..5589089b3 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -215,7 +215,7 @@ UINT16 spacetimetics = 11*TICRATE + (TICRATE/2); UINT16 extralifetics = 4*TICRATE; UINT16 nightslinktics = 2*TICRATE; -INT32 gameovertics = 12*TICRATE; +INT32 gameovertics = 11*TICRATE; UINT8 ammoremovaltics = 2*TICRATE; From fe7e374e3bf5e4983c288e662253a4cbc162d9e3 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 11 Sep 2019 13:32:12 +0100 Subject: [PATCH 084/133] Fix the Save Select platter drawing for the new player signpost art. This might LOOK like an unrelated change, but it needs a new player.dta, so might as well keep that all localised! --- src/m_menu.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 92d0fc791..b7c869539 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7055,7 +7055,7 @@ static void M_DrawLoadGameData(void) } } - y -= 13; + y -= 4; // character heads, lives, and continues { @@ -7064,7 +7064,7 @@ static void M_DrawLoadGameData(void) patch_t *patch; UINT8 *colormap = NULL; - INT32 tempx = (x+40)<highresscale, 0, patch, colormap); Z_Free(colormap); - tempx -= (15<spriteframes[0]; patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); - if ((calc = SHORT(patch->topoffset) - 42) > 0) - tempy += ((4+calc)<highresscale, flip, patch, colormap); skipsign: - y += 25; + y += 16; tempx = x + 10; if (savegameinfo[savetodraw].lives != INFLIVES From 10a0b38ab1b41731505f1025949cc493fca4ea61 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 11 Sep 2019 14:24:49 +0100 Subject: [PATCH 085/133] Fix an issue where completing a stage normally would not correctly set startrings for the next one (as opposed to warping directly or dying inside it). --- src/p_setup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 65335be3f..bb96cf89f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2242,7 +2242,7 @@ static void P_LevelInitStuff(void) } // obliteration station... - players[i].rings = players[i].spheres =\ + players[i].spheres =\ players[i].xtralife = players[i].deadtimer =\ players[i].numboxes = players[i].totalring =\ players[i].laps = players[i].aiming =\ @@ -2267,6 +2267,7 @@ static void P_LevelInitStuff(void) // aha, the first evidence this shouldn't be a memset! players[i].drillmeter = 40*20; + players[i].rings = (ultimatemode ? 0 : mapheaderinfo[gamemap-1]->startrings); P_ResetPlayer(&players[i]); // hit these too From 737690c8b87815ccb88d57caad4af72641c6b648 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 11 Sep 2019 10:45:59 -0400 Subject: [PATCH 086/133] Added cam_adjust, de-ghettoified the camera in general --- src/p_mobj.c | 15 ++++++++++++++- src/p_user.c | 18 +++++------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1ee90d250..e7a757c4d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3760,7 +3760,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled if (thiscam->momx || thiscam->momy) { - if (!P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y + thiscam->momy, thiscam)) + if (!P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y + thiscam->momy, thiscam)) // Thanks for the greatly improved camera, Lach -- Sev { // Never fails for 2D mode. mobj_t dummy; dummy.thinker.function.acp1 = (actionf_p1)P_MobjThinker; @@ -3770,9 +3770,22 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled dummy.z = thiscam->z; dummy.height = thiscam->height; if (!resetcalled && !(player->pflags & PF_NOCLIP) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. + { P_ResetCamera(player, thiscam); + resetcalled = true; + } else + { + fixed_t camspeed = P_AproxDistance(thiscam->momx, thiscam->momy); + P_SlideCameraMove(thiscam); + + if (!resetcalled && P_AproxDistance(thiscam->momx, thiscam->momy) == camspeed) + { + P_ResetCamera(player, thiscam); + resetcalled = true; + } + } if (resetcalled) // Okay this means the camera is fully reset. return true; } diff --git a/src/p_user.c b/src/p_user.c index 53e9704ff..13450bc9f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9357,7 +9357,7 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled) { angle_t angle = 0, focusangle = 0, focusaiming = 0; - fixed_t x, y, z, dist, distxy, distz, checkdist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight; + fixed_t x, y, z, dist, distxy, distz, checkdist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight, slopez = 0; INT32 camrotate; boolean camstill, cameranoclip; mobj_t *mo; @@ -9574,14 +9574,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (!(twodlevel || (mo->flags2 & MF2_TWOD)) && !(player->powers[pw_carry] == CR_NIGHTSMODE)) // This block here is like 90% Lach's work, thanks bud { - if (!cameranoclip && !resetcalled) - { - if ((P_AproxDistance(mo->x-thiscam->x-thiscam->momx, mo->y-thiscam->y-thiscam->momy) > FixedDiv(mo->momz+dist, camspeed)) || (abs(thiscam->z - player->mo->z) > (FixedDiv(mo->momz+dist, camspeed)))) //If the camera is too far away, - { - P_ResetCamera(player, thiscam); //Reset the camera - return true; - } - } if ((thiscam == &camera && cv_cam_adjust.value) || (thiscam == &camera2 && cv_cam2_adjust.value)) { if (!(mo->eflags & MFE_JUSTHITFLOOR) && (P_IsObjectOnGround(mo)) // Check that player is grounded @@ -9590,12 +9582,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (mo->eflags & MFE_VERTICALFLIP) // if player is upside-down { //z = min(z, thiscam->ceilingz); // solution 1: change new z coordinate to be at LEAST its ground height - z += min(thiscam->ceilingz - mo->z, 0); // solution 2: change new z coordinate by the difference between camera's ground and top of player + slopez += min(thiscam->ceilingz - mo->z, 0); // solution 2: change new z coordinate by the difference between camera's ground and top of player } else // player is not upside-down { //z = max(z, thiscam->floorz); // solution 1: change new z coordinate to be at LEAST its ground height - z += max(thiscam->floorz - mo->z - mo->height, 0); // solution 2: change new z coordinate by the difference between camera's ground and top of player + slopez += max(thiscam->floorz - mo->z - mo->height, 0); // solution 2: change new z coordinate by the difference between camera's ground and top of player } } } @@ -9604,12 +9596,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if ((thiscam == &camera && cv_cam_orbit.value) || (thiscam == &camera2 && cv_cam2_orbit.value)) //Sev here, I'm guessing this is where orbital cam lives { distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); - distz = -FixedMul(dist, FINESINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); + distz = -FixedMul(dist, FINESINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)) + slopez; } else { distxy = dist; - distz = 0; + distz = slopez; } x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), distxy); From 9aed6374cd9d6f54f835b2329b56efaf15ec0352 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 11 Sep 2019 17:32:25 +0100 Subject: [PATCH 087/133] Forgot to put these in Lua. (Not gonna make a fifth exe today just for this one change, though.) --- src/lua_skinlib.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index a28f6a359..7f68905aa 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -52,6 +52,8 @@ enum skin { skin_supercolor, skin_prefoppositecolor, skin_highresscale, + skin_contspeed, + skin_contangle, skin_soundsid, skin_availability }; @@ -88,6 +90,8 @@ static const char *const skin_opt[] = { "supercolor", "prefoppositecolor", "highresscale", + "contspeed", + "contangle", "soundsid", "availability", NULL}; @@ -199,6 +203,12 @@ static int skin_get(lua_State *L) case skin_highresscale: lua_pushinteger(L, skin->highresscale); break; + case skin_contspeed: + lua_pushinteger(L, skin->contspeed); + break; + case skin_contangle: + lua_pushinteger(L, skin->contangle); + break; case skin_soundsid: LUA_PushUserdata(L, skin->soundsid, META_SOUNDSID); break; From 323c7fa064d7851a3cb9cd3b9e2a9acaf6479acb Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 11 Sep 2019 14:22:56 -0400 Subject: [PATCH 088/133] Increase maximum number of Luabanks to 16 on Steel's suggestion. (Using the Web IDE 'cuz I'm tired, so no new exe; luckily I made the code flexible to constant replacement!) --- src/doomstat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doomstat.h b/src/doomstat.h index 1bf67de61..c12a6d007 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -419,7 +419,7 @@ extern UINT16 emeralds; #define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) // yes, even in non HAVE_BLUA -#define NUM_LUABANKS 8 // please only make this number go up between versions, never down. you'll break saves otherwise. also, must fit in UINT8 +#define NUM_LUABANKS 16 // please only make this number go up between versions, never down. you'll break saves otherwise. also, must fit in UINT8 extern INT32 luabanks[NUM_LUABANKS]; extern INT32 nummaprings; //keep track of spawned rings/coins From aa91627ba28fbaabe8c12da9d510c1ce8f851d84 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 11 Sep 2019 16:59:28 -0300 Subject: [PATCH 089/133] Allow PNG graphics to be used as patches Also allows them to be used as sprites. --- src/hardware/hw_cache.c | 11 +++++- src/r_data.c | 71 ++++++++++++++++++++++++++++------- src/r_data.h | 2 +- src/r_things.c | 17 ++++++++- src/w_wad.c | 83 +++++++++++++++++++++++++++++++++++++---- src/w_wad.h | 9 ++--- 6 files changed, 160 insertions(+), 33 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 77ef26506..2574bc011 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -694,7 +694,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) - realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); #endif HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, @@ -724,6 +724,13 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm { INT32 newwidth, newheight; +#ifndef NO_PNG_LUMPS + // lump is a png so convert it + size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum); + if ((patch != NULL) && R_IsLumpPNG((UINT8 *)patch, len)) + patch = R_PNGToPatch((UINT8 *)patch, len, NULL, true); +#endif + // don't do it twice (like a cache) if (grMipmap->width == 0) { @@ -926,7 +933,7 @@ static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)patch, lumplength)) - patch = R_PNGToPatch((UINT8 *)patch, lumplength); + patch = R_PNGToPatch((UINT8 *)patch, lumplength, NULL, false); #endif grMipmap->width = (UINT16)SHORT(patch->width); diff --git a/src/r_data.c b/src/r_data.c index 38dc28980..a080fa4c3 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -476,7 +476,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) { - realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); goto multipatch; } #endif @@ -569,7 +569,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) - realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength); + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); #endif x1 = patch->originx; @@ -2625,7 +2625,7 @@ static void PNG_warn(png_structp PNG, png_const_charp pngtext) CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext); } -static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) +static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size) { png_structp png_ptr; png_infop png_info_ptr; @@ -2683,8 +2683,7 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) png_read_info(png_ptr, png_info_ptr); - png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type, - NULL, NULL, NULL); + png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); if (bit_depth == 16) png_set_strip_16(png_ptr); @@ -2712,6 +2711,38 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) for (y = 0; y < height; y++) row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, png_info_ptr)); png_read_image(png_ptr, row_pointers); + + // Read grAB chunk + if (topoffset || leftoffset) + { + UINT8 *header = png; + while (size--) + { + if (!memcmp(header, "grAb", 4)) + { + // grAb stores numbers as big-endian. + #ifdef SRB2_BIG_ENDIAN + #define ENDIANESS(x) (x) + #else + #define ENDIANESS(x) ((x>>24)&0xff)|((x<<8)&0xff0000)|((x>>8)&0xff00)|((x<<24)&0xff000000) + #endif + // skip name + header += 4; + // read left offset + if (leftoffset != NULL) + *leftoffset = (INT16)ENDIANESS(*(INT32 *)header); + // read top offset + header += 4; + if (topoffset != NULL) + *topoffset = (INT16)ENDIANESS(*(INT32 *)header); + #undef ENDIANESS + break; + } + header++; + } + } + + // bye png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); *w = (INT32)width; @@ -2720,11 +2751,11 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) } // Convert a PNG to a raw image. -static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) +static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size) { UINT8 *flat; png_uint_32 x, y; - png_bytep *row_pointers = PNG_Read(png, w, h, size); + png_bytep *row_pointers = PNG_Read(png, w, h, topoffset, leftoffset, size); png_uint_32 width = *w, height = *h; if (!row_pointers) @@ -2751,15 +2782,16 @@ static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, size_t size) // Convert a PNG to a flat. UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size) { - return PNG_RawConvert(png, &levelflat->width, &levelflat->height, size); + return PNG_RawConvert(png, &levelflat->width, &levelflat->height, NULL, NULL, size); } // Convert a PNG to a patch. static unsigned char imgbuf[1<<26]; -patch_t *R_PNGToPatch(UINT8 *png, size_t size) +patch_t *R_PNGToPatch(UINT8 *png, size_t size, size_t *destsize, boolean translucency) { UINT16 width, height; - UINT8 *raw = PNG_RawConvert(png, &width, &height, size); + INT16 topoffset = 0, leftoffset = 0; + UINT8 *raw = PNG_RawConvert(png, &width, &height, &topoffset, &leftoffset, size); UINT32 x, y; UINT8 *img; @@ -2776,9 +2808,8 @@ patch_t *R_PNGToPatch(UINT8 *png, size_t size) // Write image size and offset WRITE16(imgptr, width); WRITE16(imgptr, height); - // no offsets - WRITE16(imgptr, 0); - WRITE16(imgptr, 0); + WRITE16(imgptr, leftoffset); + WRITE16(imgptr, topoffset); // Leave placeholder to column pointers colpointers = imgptr; @@ -2799,6 +2830,16 @@ patch_t *R_PNGToPatch(UINT8 *png, size_t size) for (y = 0; y < height; y++) { UINT8 paletteIndex = raw[((y * width) + x)]; + boolean opaque = translucency ? (paletteIndex != TRANSPARENTPIXEL) : true; + + // End span if we have a transparent pixel + if (!opaque) + { + if (startofspan) + WRITE8(imgptr, 0); + startofspan = NULL; + continue; + } // Start new column if we need to if (!startofspan || spanSize == 255) @@ -2857,11 +2898,13 @@ patch_t *R_PNGToPatch(UINT8 *png, size_t size) #undef WRITE32 size = imgptr-imgbuf; - img = malloc(size); + img = Z_Malloc(size, PU_STATIC, NULL); memcpy(img, imgbuf, size); Z_Free(raw); + if (destsize != NULL) + *destsize = size; return (patch_t *)img; } diff --git a/src/r_data.h b/src/r_data.h index 91301100b..38b7ba0ce 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -168,7 +168,7 @@ void R_TextureToFlat(size_t tex, UINT8 *flat); boolean R_IsLumpPNG(UINT8 *d, size_t s); UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size); -patch_t *R_PNGToPatch(UINT8 *png, size_t size); +patch_t *R_PNGToPatch(UINT8 *png, size_t size, size_t *destsize, boolean transparency); boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size); #endif diff --git a/src/r_things.c b/src/r_things.c index 92f2b9460..5940e2189 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -254,6 +254,19 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, // store sprite info in lookup tables //FIXME : numspritelumps do not duplicate sprite replacements W_ReadLumpHeaderPwad(wadnum, l, &patch, sizeof (patch_t), 0); +#ifndef NO_PNG_LUMPS + { + patch_t *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC); + size_t len = W_LumpLengthPwad(wadnum, l); + // lump is a png so convert it + if (R_IsLumpPNG((UINT8 *)png, len)) + { + png = R_PNGToPatch((UINT8 *)png, len, NULL, true); + M_Memcpy(&patch, png, sizeof(INT16)*4); + } + Z_Free(png); + } +#endif spritecachedinfo[numspritelumps].width = SHORT(patch.width)<patch, PU_CACHE); + patch_t *patch = W_CachePatchNum(vis->patch, PU_CACHE); fixed_t this_scale = vis->mobj->scale; INT32 x1, x2; INT64 overflow_test; @@ -870,7 +883,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) INT64 overflow_test; //Fab : R_InitSprites now sets a wad lump number - patch = W_CacheLumpNum(vis->patch, PU_CACHE); + patch = W_CachePatchNum(vis->patch, PU_CACHE); if (!patch) return; diff --git a/src/w_wad.c b/src/w_wad.c index 2fda8674c..9688de328 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -789,6 +789,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile) // set up caching // Z_Calloc(numlumps * sizeof (*wadfile->lumpcache), PU_STATIC, &wadfile->lumpcache); + Z_Calloc(numlumps * sizeof (*wadfile->patchcache), PU_STATIC, &wadfile->patchcache); #ifdef HWRENDER // allocates GLPatch info structures and store them in a tree @@ -1457,6 +1458,38 @@ boolean W_IsLumpCached(lumpnum_t lumpnum, void *ptr) return W_IsLumpCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); } +// +// W_IsPatchCached +// +// If a patch is already cached return true, otherwise +// return false. +// +// no outside code uses the PWAD form, for now +static inline boolean W_IsPatchCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) +{ + void *lcache; + + if (!TestValidLump(wad, lump)) + return false; + + lcache = wadfiles[wad]->patchcache[lump]; + + if (ptr) + { + if (ptr == lcache) + return true; + } + else if (lcache) + return true; + + return false; +} + +boolean W_IsPatchCached(lumpnum_t lumpnum, void *ptr) +{ + return W_IsPatchCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); +} + // ========================================================================== // W_CacheLumpName // ========================================================================== @@ -1480,18 +1513,53 @@ void *W_CacheLumpName(const char *name, INT32 tag) // Cache a patch into heap memory, convert the patch format as necessary // -// Software-only compile cache the data without conversion -#ifdef HWRENDER -static inline void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) +void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { +#ifdef HWRENDER GLPatch_t *grPatch; - - if (rendermode == render_soft || rendermode == render_none) - return W_CacheLumpNumPwad(wad, lump, tag); +#endif if (!TestValidLump(wad, lump)) return NULL; +#ifdef HWRENDER + // Software-only compile cache the data without conversion + if (rendermode == render_soft || rendermode == render_none) + { +#endif + lumpcache_t *lumpcache = wadfiles[wad]->patchcache; + if (!lumpcache[lump]) + { + size_t len = W_LumpLengthPwad(wad, lump); + void *ptr, *lumpdata, *srcdata = NULL; + + ptr = Z_Malloc(len, tag, &lumpcache[lump]); + lumpdata = Z_Malloc(len, tag, NULL); + + // read the lump in full + W_ReadLumpHeaderPwad(wad, lump, lumpdata, 0, 0); + +#ifndef NO_PNG_LUMPS + // lump is a png so convert it + if (R_IsLumpPNG((UINT8 *)lumpdata, len)) + { + size_t newlen; + srcdata = R_PNGToPatch((UINT8 *)lumpdata, len, &newlen, true); + ptr = Z_Realloc(ptr, newlen, tag, &lumpcache[lump]); + M_Memcpy(ptr, srcdata, newlen); + Z_Free(srcdata); + } + else // just copy it into the patch cache +#endif + M_Memcpy(ptr, lumpdata, len); + } + else + Z_ChangeTag(lumpcache[lump], tag); + + return lumpcache[lump]; +#ifdef HWRENDER + } + grPatch = HWR_GetCachedGLPatchPwad(wad, lump); if (grPatch->mipmap.grInfo.data) @@ -1515,6 +1583,7 @@ static inline void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) // return GLPatch_t, which can be casted to (patch_t) with valid patch header info return (void *)grPatch; +#endif } void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag) @@ -1522,8 +1591,6 @@ void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag) return W_CachePatchNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag); } -#endif // HWRENDER - void W_UnlockCachedPatch(void *patch) { // The hardware code does its own memory management, as its patches diff --git a/src/w_wad.h b/src/w_wad.h index 651738850..91d4e733e 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -102,6 +102,7 @@ typedef struct wadfile_s restype_t type; lumpinfo_t *lumpinfo; lumpcache_t *lumpcache; + lumpcache_t *patchcache; #ifdef HWRENDER aatree_t *hwrcache; // patches are cached in renderer's native format #endif @@ -167,17 +168,13 @@ void *W_CacheLumpNum(lumpnum_t lump, INT32 tag); void *W_CacheLumpNumForce(lumpnum_t lumpnum, INT32 tag); boolean W_IsLumpCached(lumpnum_t lump, void *ptr); +boolean W_IsPatchCached(lumpnum_t lump, void *ptr); void *W_CacheLumpName(const char *name, INT32 tag); void *W_CachePatchName(const char *name, INT32 tag); -#ifdef HWRENDER -//void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); // return a patch_t +void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); // return a patch_t void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag); // return a patch_t -#else -//#define W_CachePatchNumPwad(wad, lump, tag) W_CacheLumpNumPwad(wad, lump, tag) -#define W_CachePatchNum(lumpnum, tag) W_CacheLumpNum(lumpnum, tag) -#endif void W_UnlockCachedPatch(void *patch); From ed551f2536f50ea97ea8ae2a41a488359350dcfa Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 11 Sep 2019 17:03:50 -0300 Subject: [PATCH 090/133] Transparency, not translucency --- src/r_data.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index a080fa4c3..71c909b88 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2720,7 +2720,7 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, I { if (!memcmp(header, "grAb", 4)) { - // grAb stores numbers as big-endian. + // The grAb chunk stores offsets as big-endian numbers. #ifdef SRB2_BIG_ENDIAN #define ENDIANESS(x) (x) #else @@ -2787,7 +2787,7 @@ UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size) // Convert a PNG to a patch. static unsigned char imgbuf[1<<26]; -patch_t *R_PNGToPatch(UINT8 *png, size_t size, size_t *destsize, boolean translucency) +patch_t *R_PNGToPatch(UINT8 *png, size_t size, size_t *destsize, boolean transparency) { UINT16 width, height; INT16 topoffset = 0, leftoffset = 0; @@ -2830,7 +2830,7 @@ patch_t *R_PNGToPatch(UINT8 *png, size_t size, size_t *destsize, boolean translu for (y = 0; y < height; y++) { UINT8 paletteIndex = raw[((y * width) + x)]; - boolean opaque = translucency ? (paletteIndex != TRANSPARENTPIXEL) : true; + boolean opaque = transparency ? (paletteIndex != TRANSPARENTPIXEL) : true; // End span if we have a transparent pixel if (!opaque) From a5ff609873b44227430ee2399d268e31abac45bb Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 11 Sep 2019 20:18:04 -0300 Subject: [PATCH 091/133] Read user chunks --- libs/libpng-src/pngconf.h | 1 - libs/libpng-src/projects/libpng32.a | Bin 512072 -> 197156 bytes libs/libpng-src/projects/libpng64.a | Bin 424760 -> 251556 bytes src/r_data.c | 91 ++++++++++++++++++---------- 4 files changed, 59 insertions(+), 33 deletions(-) diff --git a/libs/libpng-src/pngconf.h b/libs/libpng-src/pngconf.h index 23f8313c3..5cb126197 100644 --- a/libs/libpng-src/pngconf.h +++ b/libs/libpng-src/pngconf.h @@ -62,7 +62,6 @@ #define PNG_NO_READ_iTXt #define PNG_NO_READ_APNG -#define PNG_NO_READ_UNKNOWN_CHUNKS #define PNG_NO_READ_USER_TRANSFORM #define PNG_READ_BGR_SUPPORTED #define PNG_NO_READ_SWAP_ALPHA diff --git a/libs/libpng-src/projects/libpng32.a b/libs/libpng-src/projects/libpng32.a index 74cb54e8c24dd3a924ff491086fb92d670298a83..5d2917502b9a01f0d75ca824d495d141b7ad49c7 100644 GIT binary patch literal 197156 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%0DwX+pN_53`}4 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 AqW}N^ literal 512072 zcmd?S3w&Kg)jm9X?-K~6&hEidmG}RWKmVy7^}qcKrv6#|TmQB# zR>A+xzt|1ODf{Wjw9+KpHh1>uo94Du^Kx?N+tp1S9o@|axAvw|8uq3rr@7apG&glL zXFHlQDTmaX;(dEpYj-ZzbIb z)0AbfIYH-QL}$dE1)0S~^mVP3gvL*Yd9Jm4>WMwi>lhHFavvrsn2UI!%ep z-Po1wTpAYG+1b~a&i3?l_ZqEgs+OWUJ-yv6)|9%bn&&NE*x1_MmufLJl?I$YFS%IX zkFJVs+K6R-a?S;sd49t=NsSgQxS&C!rDvaMXe>(8md#l>N29j+=bOCkr=Pw^)7me% z&}iL##u>)RdQP9SK&PfH>X~;@=z??S8!2fNZ1@(RIai}hLntpZf1%MTv-q6zb?Rzc zT2u1{ri|7IwS;x+X@afOnWoU9a^K!%Tv+Z_jZR*bpWfM&Uakuj_Lg){V?<()h-@YO zV^q_SM$5U)MOtJ--bL-gyU2pPbF7FvTCy>;AX6iI;x1}I=1fNx=AE^zq~T602G?zj zTA684tMV?B>N71H-ZdsnYcbWfj-=Wa;+@m3xQkkfXByLn#azo%sh+S`Ha54R ze>&Fd?Oy5JHFtORpvy|fT$*idMbA&SuXbd$ca2i1Dc#xF+R?Pk5yD=aX@i)y?v56R zo=rnsM?2IsM8+IP9B-kH6Qd2qVQ)s9=}L7t6!h$_rVNaxTZCC6f8^chP(j*ge$$v(JXd(F=khM{K)JIXCwJE4co+E? z?+{$Ii#Y}(t*4`Dl}j4W6(xU^u(G`+(-zs-@!qyn{xISs^)+_4w!#O;&9~}bCAOrX zBK03Pt4_7fKT6e>_H<8oI@Q>1M)y(4OFL5N@NVM2=vU0!yKE_k&}F^Q2(dDgbxij! zdkiy=>L4yDilU^l+ps5%rD6Ng>W9nKBG8MpN;B^nkCM-=@HAqobD5XFO#!-fPyh{k3^h{BK| zL~+9qqM^$WqUaHF*lB|yMDqwkh=!k#VCM~n5KR>fA#a9e=2OyQT^Ni^3w3ucZSP9a zwKSmxQ%E)~+B((S(bR1Cgx1=Q@uoN8HAJ@WD5A_XA{s}hrOQmK^QNb%d3k%6nT3ah z^vWjFkx5CnwYNH>vDK$hDwmfTdUb?TOJ;3qX=!Zg=xH;PX_7FWaf000-DRfCsHdjc zYE!331*Bs#+unn*I1&z`tp7RqJE|CqxrJAx7|#;(DKx(mEFC0 zBBLp+&JuZ|zK;egeILz(^!+GzF-#ITA}50Jb%J#Tw^j%_|Xg-;gR7)gA%aHYo z%h;QWR%gv{Y&3CC8U`8j0~yflTbm2xIcnv-d6^V!Oqw$og0<->g85HxJ7 zZ^LjHQAUOGmiA0r*vZM1>g&O1AJw&|sUwv^597m-WlJNv=F_vgipE4^6*+37beZ;z zm%ss^yrc9G{?UcFQ%L8r1%rm}Xm+${V&&cbY*R2!gwBnaC*9Mgxw(*-?c%7V>mawz zsEPaLws7_v3K}(BfZx!&_cVaW+@#=EE{?h+el$Y03;kGg{ zldsEgT{dBXw~yjAV}(*56cqDj$eLbmarO!P-+_g&Ec=) zeMHe!uhfd-5E_hMt}Iihi((Ho;O>mMTzjve)=`v^@%rk!;~MGWI`OG}ur$ z(6DE4$;5#ryZf)&tyb;3wP82YHZ<%WT(W2V+Bj_V(?>+w$b|l@iV9ckx3!_D5CVoL;Z|jFyK4m3@EOoyU#9BY znS%{QLBquU-GwXm-%S3K8zv4k6m3Ki4+l#o4mL~-8VdVᴓ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 z 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