From a7f3dd7eff47a0b11d99aba2fbc8d9f0a522c9a5 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 8 Aug 2020 05:16:47 -0300 Subject: [PATCH 01/81] Refactor patch loading --- src/console.c | 5 +- src/d_main.c | 37 +---- src/dehacked.c | 2 +- src/f_finale.c | 25 +--- src/hardware/hw_cache.c | 244 ++++++++++++++----------------- src/hardware/hw_data.h | 15 +- src/hardware/hw_draw.c | 93 ++++++------ src/hardware/hw_drv.h | 2 + src/hardware/hw_glob.h | 27 ++-- src/hardware/hw_main.c | 58 ++++---- src/hardware/hw_main.h | 6 +- src/hardware/hw_md2.c | 205 +++++++++++++++----------- src/hardware/r_opengl/r_opengl.c | 15 +- src/hu_stuff.c | 3 - src/lua_infolib.c | 4 +- src/m_menu.c | 43 +----- src/r_data.c | 6 +- src/r_defs.h | 22 ++- src/r_main.c | 8 - src/r_main.h | 1 - src/r_patch.c | 220 ++++++++++++++++------------ src/r_patch.h | 20 ++- src/r_segs.c | 2 +- src/r_things.c | 18 +-- src/screen.c | 3 - src/sdl/hwsym_sdl.c | 1 + src/sdl/i_video.c | 5 +- src/st_stuff.c | 3 - src/v_video.c | 10 +- src/w_wad.c | 71 +++------ src/w_wad.h | 7 - src/win32/win_dll.c | 2 + src/y_inter.c | 73 +-------- src/z_zone.c | 27 ---- src/z_zone.h | 6 - 35 files changed, 557 insertions(+), 732 deletions(-) diff --git a/src/console.c b/src/console.c index aac94d473..280dc4f22 100644 --- a/src/console.c +++ b/src/console.c @@ -1555,7 +1555,7 @@ static void CON_DrawBackpic(void) // then fill the sides with a solid color. if (x > 0) { - column_t *column = (column_t *)((UINT8 *)(con_backpic) + LONG(con_backpic->columnofs[0])); + column_t *column = (column_t *)((UINT8 *)(con_backpic->columns) + (con_backpic->columnofs[0])); if (!column->topdelta) { UINT8 *source = (UINT8 *)(column) + 3; @@ -1648,9 +1648,6 @@ void CON_Drawer(void) if (!con_started || !graphics_started) return; - if (needpatchrecache) - HU_LoadGraphics(); - if (con_recalc) { CON_RecalcSize(); diff --git a/src/d_main.c b/src/d_main.c index 6bc42da14..ee3ce699c 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -110,8 +110,6 @@ boolean devparm = false; // started game with -devparm boolean singletics = false; // timedemo boolean lastdraw = false; -static void D_CheckRendererState(void); - postimg_t postimgtype = postimg_none; INT32 postimgparam; postimg_t postimgtype2 = postimg_none; @@ -245,9 +243,7 @@ static void D_Display(void) // create plane polygons, if necessary. // 3. Functions related to switching video // modes (resolution) are called. - // 4. Patch data is freed from memory, - // and recached if necessary. - // 5. The frame is ready to be drawn! + // 4. The frame is ready to be drawn! // stop movie if needs to change renderer if (setrenderneeded && (moviemode == MM_APNG)) @@ -284,9 +280,6 @@ static void D_Display(void) forcerefresh = true; // force background redraw } - // Lactozilla: Renderer switching - D_CheckRendererState(); - // draw buffered stuff to screen // Used only by linux GGI version I_UpdateNoBlit(); @@ -679,26 +672,6 @@ static void D_Display(void) I_FinishUpdate(); // page flip or blit buffer rs_swaptime = I_GetTimeMicros() - rs_swaptime; } - - needpatchflush = false; - needpatchrecache = false; -} - -// Check the renderer's state -// after a possible renderer switch. -void D_CheckRendererState(void) -{ - // flush all patches from memory - if (needpatchflush) - { - Z_FlushCachedPatches(); - needpatchflush = false; - } - - // some patches have been freed, - // so cache them again - if (needpatchrecache) - R_ReloadHUDGraphics(); } // ========================================================================= @@ -1433,18 +1406,10 @@ void D_SRB2Main(void) if ((setrenderneeded != 0) && (setrenderneeded != rendermode)) { CONS_Printf(M_GetText("Switching the renderer...\n")); - Z_PreparePatchFlush(); - - // set needpatchflush / needpatchrecache true for D_CheckRendererState - needpatchflush = true; - needpatchrecache = true; // Set cv_renderer to the new render mode VID_CheckRenderer(); SCR_ChangeRendererCVars(rendermode); - - // check the renderer's state - D_CheckRendererState(); } wipegamestate = gamestate; diff --git a/src/dehacked.c b/src/dehacked.c index 9d6729dc2..c801dcde9 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1046,7 +1046,7 @@ static void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) #ifdef ROTSPRITE if ((sprites != NULL) && (!sprite2)) - R_FreeSingleRotSprite(&sprites[num]); + R_FreeRotSprite(&sprites[num]); #endif do diff --git a/src/f_finale.c b/src/f_finale.c index 8d39a7533..7cc5467c2 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1901,13 +1901,6 @@ void F_EndingDrawer(void) INT32 x, y, i, j, parallaxticker; patch_t *rockpat; - if (needpatchrecache) - { - F_CacheEnding(); - if (goodending && finalecount >= INFLECTIONPOINT) // time to swap some assets - F_CacheGoodEnding(); - } - if (!goodending || finalecount < INFLECTIONPOINT) rockpat = W_CachePatchName("ROID0000", PU_PATCH); else @@ -2706,17 +2699,12 @@ static void F_FigureActiveTtScale(void) SINT8 newttscale = max(1, min(6, vid.dupx)); SINT8 oldttscale = activettscale; - if (needpatchrecache) - ttloaded[0] = ttloaded[1] = ttloaded[2] = ttloaded[3] = ttloaded[4] = ttloaded[5] = 0; - else - { - if (newttscale == testttscale) - return; + if (newttscale == testttscale) + return; - // We have a new ttscale, so load gfx - if(oldttscale > 0) - F_UnloadAlacroixGraphics(oldttscale); - } + // We have a new ttscale, so load gfx + if(oldttscale > 0) + F_UnloadAlacroixGraphics(oldttscale); testttscale = newttscale; @@ -2750,9 +2738,6 @@ void F_TitleScreenDrawer(void) if (modeattacking) return; // We likely came here from retrying. Don't do a damn thing. - if (needpatchrecache && (curttmode != TTMODE_ALACROIX)) - F_CacheTitleScreen(); - // Draw that sky! if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index ed3b6afee..a26721169 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -309,7 +309,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, // Draw each column to the block cache for (; ncols--; block += bpp, xfrac += xfracstep) { - patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[xfrac>>FRACBITS])); + patchcol = (const column_t *)((const UINT8 *)realpatch->columns + (realpatch->columnofs[xfrac>>FRACBITS])); HWR_DrawColumnInCache(patchcol, block, mipmap, pblockheight, blockmodulo, @@ -323,7 +323,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 pblockheight, texture_t *texture, texpatch_t *patch, - const patch_t *realpatch) + const softwarepatch_t *realpatch) { INT32 x, x1, x2; INT32 col, ncols; @@ -394,7 +394,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, bpp = format2bpp(mipmap->format); if (bpp < 1 || bpp > 4) - I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); + I_Error("HWR_DrawTexturePatchInCache: no drawer defined for this bpp (%d)\n",bpp); // NOTE: should this actually be pblockwidth*bpp? blockmodulo = pblockwidth*bpp; @@ -449,7 +449,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) UINT8 *block; texture_t *texture; texpatch_t *patch; - patch_t *realpatch; + softwarepatch_t *realpatch; UINT8 *pdata; INT32 blockwidth, blockheight, blocksize; @@ -505,7 +505,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) boolean dealloc = true; size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); - realpatch = (patch_t *)pdata; + realpatch = (softwarepatch_t *)pdata; #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) @@ -547,36 +547,20 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) // patch may be NULL if grMipmap has been initialised already and makebitmap is false void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap) { -#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((const UINT8 *)patch, len)) - patch = R_PNGToPatch((const UINT8 *)patch, len, NULL); -#endif - - // don't do it twice (like a cache) if (grMipmap->width == 0) { - // save the original patch header so that the GLPatch can be casted - // into a standard patch_t struct and the existing code can get the - // orginal patch dimensions and offsets. - grPatch->width = SHORT(patch->width); - grPatch->height = SHORT(patch->height); - grPatch->leftoffset = SHORT(patch->leftoffset); - grPatch->topoffset = SHORT(patch->topoffset); - grMipmap->width = grMipmap->height = 1; - while (grMipmap->width < grPatch->width) grMipmap->width <<= 1; - while (grMipmap->height < grPatch->height) grMipmap->height <<= 1; + while (grMipmap->width < patch->width) grMipmap->width <<= 1; + while (grMipmap->height < patch->height) grMipmap->height <<= 1; // no wrap around, no chroma key grMipmap->flags = 0; + // setup the texture info grMipmap->format = patchformat; - //grPatch->max_s = grPatch->max_t = 1.0f; - grPatch->max_s = (float)grPatch->width / (float)grMipmap->width; - grPatch->max_t = (float)grPatch->height / (float)grMipmap->height; + grPatch->max_s = (float)patch->width / (float)grMipmap->width; + grPatch->max_t = (float)patch->height / (float)grMipmap->height; } Z_Free(grMipmap->data); @@ -588,7 +572,7 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm HWR_DrawPatchInCache(grMipmap, grMipmap->width, grMipmap->height, - grPatch->width, grPatch->height, + patch->width, patch->height, patch); } } @@ -608,13 +592,33 @@ void HWR_InitTextureCache(void) gl_flats = NULL; } -// Callback function for HWR_FreeTextureCache. -static void FreeMipmapColormap(INT32 patchnum, void *patch) +void HWR_FreeTexture(patch_t *patch) { - GLPatch_t* const pat = patch; - (void)patchnum; //unused + if (patch->hardware) + { + GLPatch_t *grPatch = patch->hardware; + + HWR_FreeTextureColormaps(patch); + + if (grPatch->mipmap && (rendermode == render_opengl)) + HWD.pfnDeleteTexture(grPatch->mipmap); + + Z_Free(patch->hardware); + } + + patch->hardware = NULL; +} + +// Called by HWR_FreeTextureCache. +void HWR_FreeTextureColormaps(patch_t *patch) +{ + GLPatch_t *pat; // The patch must be valid, obviously + if (!patch) + return; + + pat = patch->hardware; if (!pat) return; @@ -642,6 +646,7 @@ static void FreeMipmapColormap(INT32 patchnum, void *patch) if (next->data) Z_Free(next->data); next->data = NULL; + HWD.pfnDeleteTexture(next); // Free the old colormap mipmap from memory. free(next); @@ -663,7 +668,11 @@ void HWR_FreeMipmapCache(void) // Alam: free the Z_Blocks before freeing it's users // free all patch colormaps after each level: must be done after ClearMipMapCache! for (i = 0; i < numwadfiles; i++) - M_AATreeIterate(wadfiles[i]->hwrcache, FreeMipmapColormap); + { + INT32 j = 0; + for (; j < wadfiles[i]->numlumps; j++) + HWR_FreeTextureColormaps(wadfiles[i]->patchcache[j]); + } } void HWR_FreeTextureCache(void) @@ -733,7 +742,6 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex) // If hardware does not have the texture, then call pfnSetTexture to upload it if (!grtex->mipmap.downloaded) HWD.pfnSetTexture(&grtex->mipmap); - HWR_SetCurrentTexture(&grtex->mipmap); // The system-memory data can be purged now. @@ -809,14 +817,13 @@ void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum) if (flatlumpnum == LUMPERROR) return; - grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; + grmip = ((GLPatch_t *)HWR_GetCachedGLPatch(flatlumpnum)->hardware)->mipmap; if (!grmip->downloaded && !grmip->data) HWR_CacheFlat(grmip, flatlumpnum); // If hardware does not have the texture, then call pfnSetTexture to upload it if (!grmip->downloaded) HWD.pfnSetTexture(grmip); - HWR_SetCurrentTexture(grmip); // The system-memory data can be purged now. @@ -854,7 +861,6 @@ void HWR_GetLevelFlat(levelflat_t *levelflat) // If hardware does not have the texture, then call pfnSetTexture to upload it if (!grtex->mipmap.downloaded) HWD.pfnSetTexture(&grtex->mipmap); - HWR_SetCurrentTexture(&grtex->mipmap); // The system-memory data can be purged now. @@ -864,89 +870,61 @@ void HWR_GetLevelFlat(levelflat_t *levelflat) HWR_SetCurrentTexture(NULL); } -// -// HWR_LoadMappedPatch(): replace the skin color of the sprite in cache -// : load it first in doom cache if not already -// -static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) +// --------------------+ +// HWR_LoadPatchMipmap : Generates a patch into a mipmap, usually the mipmap inside the patch itself +// --------------------+ +static void HWR_LoadPatchMipmap(patch_t *patch, GLMipmap_t *grMipmap) { - if (!grmip->downloaded && !grmip->data) - { - patch_t *patch = gpatch->rawpatch; - if (!patch) - patch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); - HWR_MakePatch(patch, gpatch, grmip, true); - - // You can't free rawpatch for some reason? - // (Obviously I can't, sprite rotation needs that...) - if (!gpatch->rawpatch) - Z_Free(patch); - } + GLPatch_t *grPatch = patch->hardware; + if (!grMipmap->downloaded && !grMipmap->data) + HWR_MakePatch(patch, grPatch, grMipmap, true); // If hardware does not have the texture, then call pfnSetTexture to upload it - if (!grmip->downloaded) - HWD.pfnSetTexture(grmip); - - HWR_SetCurrentTexture(grmip); + if (!grMipmap->downloaded) + HWD.pfnSetTexture(grMipmap); + HWR_SetCurrentTexture(grMipmap); // The system-memory data can be purged now. - Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED); } // -----------------+ // HWR_GetPatch : Download a patch to the hardware cache and make it ready for use // -----------------+ -void HWR_GetPatch(GLPatch_t *gpatch) +void HWR_GetPatch(patch_t *patch) { - // is it in hardware cache - if (!gpatch->mipmap->downloaded && !gpatch->mipmap->data) - { - // load the software patch, PU_STATIC or the Z_Malloc for hardware patch will - // flush the software patch before the conversion! oh yeah I suffered - patch_t *ptr = gpatch->rawpatch; - if (!ptr) - ptr = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); - HWR_MakePatch(ptr, gpatch, gpatch->mipmap, true); - - // this is inefficient.. but the hardware patch in heap is purgeable so it should - // not fragment memory, and besides the REAL cache here is the hardware memory - if (!gpatch->rawpatch) - Z_Free(ptr); - } - - // If hardware does not have the texture, then call pfnSetTexture to upload it - if (!gpatch->mipmap->downloaded) - HWD.pfnSetTexture(gpatch->mipmap); - - HWR_SetCurrentTexture(gpatch->mipmap); - - // The system-memory patch data can be purged now. - Z_ChangeTag(gpatch->mipmap->data, PU_HWRCACHE_UNLOCKED); + if (!patch->hardware) + Patch_CreateGL(patch); + HWR_LoadPatchMipmap(patch, ((GLPatch_t *)patch->hardware)->mipmap); } - // -------------------+ // HWR_GetMappedPatch : Same as HWR_GetPatch for sprite color // -------------------+ -void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap) +void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap) { - GLMipmap_t *grmip, *newmip; + GLPatch_t *grPatch; + GLMipmap_t *grMipmap, *newMipmap; + + if (!patch->hardware) + Patch_CreateGL(patch); + grPatch = patch->hardware; if (colormap == colormaps || colormap == NULL) { - // Load the default (green) color in doom cache (temporary?) AND hardware cache - HWR_GetPatch(gpatch); + // Load the default (green) color in hardware cache + HWR_GetPatch(patch); return; } // search for the mimmap // skip the first (no colormap translated) - for (grmip = gpatch->mipmap; grmip->nextcolormap; ) + for (grMipmap = grPatch->mipmap; grMipmap->nextcolormap; ) { - grmip = grmip->nextcolormap; - if (grmip->colormap == colormap) + grMipmap = grMipmap->nextcolormap; + if (grMipmap->colormap == colormap) { - HWR_LoadMappedPatch(grmip, gpatch); + HWR_LoadPatchMipmap(patch, grMipmap); return; } } @@ -957,13 +935,13 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap) // (it have a liste of mipmap) // this malloc is cleared in HWR_FreeTextureCache // (...) unfortunately z_malloc fragment alot the memory :(so malloc is better - newmip = calloc(1, sizeof (*newmip)); - if (newmip == NULL) + newMipmap = calloc(1, sizeof (*newMipmap)); + if (newMipmap == NULL) I_Error("%s: Out of memory", "HWR_GetMappedPatch"); - grmip->nextcolormap = newmip; + grMipmap->nextcolormap = newMipmap; - newmip->colormap = colormap; - HWR_LoadMappedPatch(newmip, gpatch); + newMipmap->colormap = colormap; + HWR_LoadPatchMipmap(patch, newMipmap); } void HWR_UnlockCachedPatch(GLPatch_t *gpatch) @@ -1053,79 +1031,73 @@ static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheig // HWR_GetPic : Download a Doom pic (raw row encoded with no 'holes') // Returns : // -----------------+ -GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) +patch_t *HWR_GetPic(lumpnum_t lumpnum) { - GLPatch_t *grpatch = HWR_GetCachedGLPatch(lumpnum); - if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) + patch_t *patch = HWR_GetCachedGLPatch(lumpnum); + GLPatch_t *grPatch = (GLPatch_t *)(patch->hardware); + + if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data) { pic_t *pic; UINT8 *block; size_t len; pic = W_CacheLumpNum(lumpnum, PU_CACHE); - grpatch->width = SHORT(pic->width); - grpatch->height = SHORT(pic->height); + patch->width = SHORT(pic->width); + patch->height = SHORT(pic->height); len = W_LumpLength(lumpnum) - sizeof (pic_t); - grpatch->leftoffset = 0; - grpatch->topoffset = 0; - - grpatch->mipmap->width = (UINT16)grpatch->width; - grpatch->mipmap->height = (UINT16)grpatch->height; + grPatch->mipmap->width = (UINT16)patch->width; + grPatch->mipmap->height = (UINT16)patch->height; if (pic->mode == PALETTE) - grpatch->mipmap->format = textureformat; // can be set by driver + grPatch->mipmap->format = textureformat; // can be set by driver else - grpatch->mipmap->format = picmode2GR[pic->mode]; + grPatch->mipmap->format = picmode2GR[pic->mode]; - Z_Free(grpatch->mipmap->data); + Z_Free(grPatch->mipmap->data); // allocate block - block = MakeBlock(grpatch->mipmap); + block = MakeBlock(grPatch->mipmap); - if (grpatch->width == SHORT(pic->width) && - grpatch->height == SHORT(pic->height) && - format2bpp(grpatch->mipmap->format) == format2bpp(picmode2GR[pic->mode])) + if (patch->width == SHORT(pic->width) && + patch->height == SHORT(pic->height) && + format2bpp(grPatch->mipmap->format) == format2bpp(picmode2GR[pic->mode])) { // no conversion needed - M_Memcpy(grpatch->mipmap->data, pic->data,len); + M_Memcpy(grPatch->mipmap->data, pic->data,len); } else HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height), - SHORT(pic->width)*format2bpp(grpatch->mipmap->format), + SHORT(pic->width)*format2bpp(grPatch->mipmap->format), pic, - format2bpp(grpatch->mipmap->format)); + format2bpp(grPatch->mipmap->format)); Z_Unlock(pic); Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED); - grpatch->mipmap->flags = 0; - grpatch->max_s = grpatch->max_t = 1.0f; + grPatch->mipmap->flags = 0; + grPatch->max_s = grPatch->max_t = 1.0f; } - HWD.pfnSetTexture(grpatch->mipmap); - //CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.data, grpatch->mipmap.downloaded); + HWD.pfnSetTexture(grPatch->mipmap); + //CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grPatch->mipmap->data, grPatch->mipmap->downloaded); - return grpatch; + return patch; } -GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum) +patch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum) { - aatree_t *hwrcache = wadfiles[wadnum]->hwrcache; - GLPatch_t *grpatch; - - if (!(grpatch = M_AATreeGet(hwrcache, lumpnum))) + lumpcache_t *lumpcache = wadfiles[wadnum]->patchcache; + if (!lumpcache[lumpnum]) { - grpatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL); - grpatch->wadnum = wadnum; - grpatch->lumpnum = lumpnum; - grpatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL); - M_AATreeSet(hwrcache, lumpnum, grpatch); + void *ptr = Z_Calloc(sizeof(patch_t), PU_PATCH, &lumpcache[lumpnum]); + Patch_Create(NULL, 0, ptr); + Patch_AllocateHardwarePatch(ptr); } - - return grpatch; + return (patch_t *)(lumpcache[lumpnum]); } -GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum) +patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum) { return HWR_GetCachedGLPatchPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum)); } @@ -1218,7 +1190,7 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum) void HWR_GetFadeMask(lumpnum_t fademasklumpnum) { - GLMipmap_t *grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; + GLMipmap_t *grmip = ((GLPatch_t *)HWR_GetCachedGLPatch(fademasklumpnum)->hardware)->mipmap; if (!grmip->downloaded && !grmip->data) HWR_CacheFadeMask(grmip, fademasklumpnum); diff --git a/src/hardware/hw_data.h b/src/hardware/hw_data.h index e5477d729..6a872d258 100644 --- a/src/hardware/hw_data.h +++ b/src/hardware/hw_data.h @@ -73,23 +73,10 @@ struct GLMapTexture_s typedef struct GLMapTexture_s GLMapTexture_t; -// a cached patch as converted to hardware format, holding the original patch_t -// header so that the existing code can retrieve ->width, ->height as usual -// This is returned by W_CachePatchNum()/W_CachePatchName(), when rendermode -// is 'render_opengl'. Else it returns the normal patch_t data. - +// a cached patch as converted to hardware format struct GLPatch_s { - // the 4 first fields come right away from the original patch_t - INT16 width; - INT16 height; - INT16 leftoffset; // pixels to the left of origin - INT16 topoffset; // pixels below the origin - // float max_s,max_t; - UINT16 wadnum; // the software patch lump num for when the hardware patch - UINT16 lumpnum; // was flushed, and we need to re-create it - void *rawpatch; // :^) GLMipmap_t *mipmap; } ATTRPACK; typedef struct GLPatch_s GLPatch_t; diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index f5a984d5d..a4e1df496 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -68,10 +68,11 @@ static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111 // Notes : x,y : positions relative to the original Doom resolution // : textes(console+score) + menus + status bar // -----------------+ -void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) +void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option) { FOutVector v[4]; FBITFIELD flags; + GLPatch_t *hwrPatch; // 3--2 // | /| @@ -84,6 +85,7 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) // make patch ready in hardware cache HWR_GetPatch(gpatch); + hwrPatch = ((GLPatch_t *)gpatch->hardware); switch (option & V_SCALEPATCHMASK) { @@ -103,17 +105,17 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) if (option & V_NOSCALESTART) sdupx = sdupy = 2.0f; - v[0].x = v[3].x = (x*sdupx-SHORT(gpatch->leftoffset)*pdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx+(SHORT(gpatch->width)-SHORT(gpatch->leftoffset))*pdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdupy-SHORT(gpatch->topoffset)*pdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy+(SHORT(gpatch->height)-SHORT(gpatch->topoffset))*pdupy)/vid.height; + v[0].x = v[3].x = (x*sdupx-(gpatch->leftoffset)*pdupx)/vid.width - 1; + v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; + v[0].y = v[1].y = 1-(y*sdupy-(gpatch->topoffset)*pdupy)/vid.height; + v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].s = v[3].s = 0.0f; - v[2].s = v[1].s = gpatch->max_s; + v[2].s = v[1].s = hwrPatch->max_s; v[0].t = v[1].t = 0.0f; - v[2].t = v[3].t = gpatch->max_t; + v[2].t = v[3].t = hwrPatch->max_t; flags = PF_Translucent|PF_NoDepthTest; @@ -126,13 +128,14 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) HWD.pfnDrawPolygon(NULL, v, 4, flags); } -void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap) +void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap) { FOutVector v[4]; FBITFIELD flags; float cx = FIXED_TO_FLOAT(x); float cy = FIXED_TO_FLOAT(y); UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); + GLPatch_t *hwrPatch; // 3--2 // | /| @@ -151,6 +154,8 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t else HWR_GetMappedPatch(gpatch, colormap); + hwrPatch = ((GLPatch_t *)gpatch->hardware); + dupx = (float)vid.dupx; dupy = (float)vid.dupy; @@ -181,13 +186,13 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t // left offset if (option & V_FLIP) - offsetx = (float)(SHORT(gpatch->width) - SHORT(gpatch->leftoffset)) * fscalew; + offsetx = (float)(gpatch->width - gpatch->leftoffset) * fscalew; else - offsetx = (float)SHORT(gpatch->leftoffset) * fscalew; + offsetx = (float)(gpatch->leftoffset) * fscalew; // top offset // TODO: make some kind of vertical version of V_FLIP, maybe by deprecating V_OFFSET in future?!? - offsety = (float)SHORT(gpatch->topoffset) * fscaleh; + offsety = (float)(gpatch->topoffset) * fscaleh; if ((option & (V_NOSCALESTART|V_OFFSET)) == (V_NOSCALESTART|V_OFFSET)) // Multiply by dupx/dupy for crosshairs { @@ -277,17 +282,14 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) // cx and cy are possibly *slightly* off from float maths // This is done before here compared to software because we directly alter cx and cy to centre - if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) + if (cx >= -0.1f && cx <= 0.1f && (gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) { - // Need to temporarily cache the real patch to get the colour of the top left pixel - patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); - const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0])); + const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0])); if (!column->topdelta) { const UINT8 *source = (const UINT8 *)(column) + 3; HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); } - Z_Free(realpatch); } // centre screen if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) @@ -317,13 +319,13 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t if (pscale != FRACUNIT || (splitscreen && option & V_PERPLAYER)) { - fwidth = (float)SHORT(gpatch->width) * fscalew * dupx; - fheight = (float)SHORT(gpatch->height) * fscaleh * dupy; + fwidth = (float)(gpatch->width) * fscalew * dupx; + fheight = (float)(gpatch->height) * fscaleh * dupy; } else { - fwidth = (float)SHORT(gpatch->width) * dupx; - fheight = (float)SHORT(gpatch->height) * dupy; + fwidth = (float)(gpatch->width) * dupx; + fheight = (float)(gpatch->height) * dupy; } // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 @@ -345,17 +347,17 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t if (option & V_FLIP) { - v[0].s = v[3].s = gpatch->max_s; + v[0].s = v[3].s = hwrPatch->max_s; v[2].s = v[1].s = 0.0f; } else { v[0].s = v[3].s = 0.0f; - v[2].s = v[1].s = gpatch->max_s; + v[2].s = v[1].s = hwrPatch->max_s; } v[0].t = v[1].t = 0.0f; - v[2].t = v[3].t = gpatch->max_t; + v[2].t = v[3].t = hwrPatch->max_t; flags = PF_Translucent|PF_NoDepthTest; @@ -380,13 +382,14 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t HWD.pfnDrawPolygon(NULL, v, 4, flags); } -void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) +void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) { FOutVector v[4]; FBITFIELD flags; float cx = FIXED_TO_FLOAT(x); float cy = FIXED_TO_FLOAT(y); UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); + GLPatch_t *hwrPatch; // 3--2 // | /| @@ -399,6 +402,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal // make patch ready in hardware cache HWR_GetPatch(gpatch); + hwrPatch = ((GLPatch_t *)gpatch->hardware); dupx = (float)vid.dupx; dupy = (float)vid.dupy; @@ -438,15 +442,12 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal // This is done before here compared to software because we directly alter cx and cy to centre if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) { - // Need to temporarily cache the real patch to get the colour of the top left pixel - patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); - const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0])); + const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0])); if (!column->topdelta) { const UINT8 *source = (const UINT8 *)(column) + 3; HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); } - Z_Free(realpatch); } // centre screen if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) @@ -469,11 +470,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal fwidth = w; fheight = h; - if (fwidth > SHORT(gpatch->width)) - fwidth = SHORT(gpatch->width); + if (fwidth > gpatch->width) + fwidth = gpatch->width; - if (fheight > SHORT(gpatch->height)) - fheight = SHORT(gpatch->height); + if (fheight > gpatch->height) + fheight = gpatch->height; if (pscale != FRACUNIT) { @@ -503,17 +504,17 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].s = v[3].s = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s; - if (sx + w > SHORT(gpatch->width)) - v[2].s = v[1].s = gpatch->max_s; + v[0].s = v[3].s = ((sx)/(float)(gpatch->width))*hwrPatch->max_s; + if (sx + w > gpatch->width) + v[2].s = v[1].s = hwrPatch->max_s; else - v[2].s = v[1].s = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s; + v[2].s = v[1].s = ((sx+w)/(float)(gpatch->width))*hwrPatch->max_s; - v[0].t = v[1].t = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t; - if (sy + h > SHORT(gpatch->height)) - v[2].t = v[3].t = gpatch->max_t; + v[0].t = v[1].t = ((sy)/(float)(gpatch->height))*hwrPatch->max_t; + if (sy + h > gpatch->height) + v[2].t = v[3].t = hwrPatch->max_t; else - v[2].t = v[3].t = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t; + v[2].t = v[3].t = ((sy+h)/(float)(gpatch->height))*hwrPatch->max_t; flags = PF_Translucent|PF_NoDepthTest; @@ -541,7 +542,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) { FOutVector v[4]; - const GLPatch_t *patch; + const patch_t *patch; // make pic ready in hardware cache patch = HWR_GetPic(lumpnum); @@ -558,10 +559,10 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].s = v[3].s = 0; - v[2].s = v[1].s = patch->max_s; - v[0].t = v[1].t = 0; - v[2].t = v[3].t = patch->max_t; + v[0].s = v[3].s = 0; + v[2].s = v[1].s = ((GLPatch_t *)patch->hardware)->max_s; + v[0].t = v[1].t = 0; + v[2].t = v[3].t = ((GLPatch_t *)patch->hardware)->max_t; //Hurdler: Boris, the same comment as above... but maybe for pics @@ -934,7 +935,7 @@ void HWR_DrawViewBorder(INT32 clearlines) INT32 top, side; INT32 baseviewwidth, baseviewheight; INT32 basewindowx, basewindowy; - GLPatch_t *patch; + patch_t *patch; // if (gl_viewwidth == vid.width) // return; diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 6f039cc3a..cc1354909 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -42,6 +42,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo); +EXPORT void HWRAPI(DeleteTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(ClearMipMapCache) (void); @@ -96,6 +97,7 @@ struct hwdriver_s ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; UpdateTexture pfnUpdateTexture; + DeleteTexture pfnDeleteTexture; ReadRect pfnReadRect; GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 6ede8448b..94c553535 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -64,8 +64,7 @@ typedef struct gl_vissprite_s float x1, x2; float tz, ty; float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting - //lumpnum_t patchlumpnum; - GLPatch_t *gpatch; + patch_t *gpatch; boolean flip; UINT8 translucency; //alpha level 0-255 mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out. @@ -86,25 +85,33 @@ extern size_t addsubsector; void HWR_InitPolyPool(void); void HWR_FreePolyPool(void); +void HWR_FreeExtraSubsectors(void); + // -------- // hw_cache.c // -------- void HWR_InitTextureCache(void); void HWR_FreeTextureCache(void); void HWR_FreeMipmapCache(void); -void HWR_FreeExtraSubsectors(void); +patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump); +patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum); + +void HWR_GetPatch(patch_t *patch); +void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap); +void HWR_GetFadeMask(lumpnum_t fademasklumpnum); +patch_t *HWR_GetPic(lumpnum_t lumpnum); + +GLMapTexture_t *HWR_GetTexture(INT32 tex); void HWR_GetLevelFlat(levelflat_t *levelflat); void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum); -GLMapTexture_t *HWR_GetTexture(INT32 tex); -void HWR_GetPatch(GLPatch_t *gpatch); -void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap); + +void HWR_FreeTexture(patch_t *patch); +void HWR_FreeTextureColormaps(patch_t *patch); void HWR_UnlockCachedPatch(GLPatch_t *gpatch); -GLPatch_t *HWR_GetPic(lumpnum_t lumpnum); + void HWR_SetPalette(RGBA_t *palette); -GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump); -GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum); -void HWR_GetFadeMask(lumpnum_t fademasklumpnum); + // -------- // hw_draw.c diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index ddc935f0d..7ba7f911c 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -706,7 +706,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) { FOutVector wallVerts[4]; wallsplat_t *splat; - GLPatch_t *gpatch; + patch_t *gpatch; fixed_t i; // seg bbox fixed_t segbbox[4]; @@ -3549,7 +3549,7 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) { - GLPatch_t *gpatch; + patch_t *gpatch; FOutVector shadowVerts[4]; FSurfaceInfo sSurf; float fscale; float fx; float fy; float offset; @@ -3575,12 +3575,12 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) if (alpha >= 255) return; alpha = 255 - alpha; - gpatch = (GLPatch_t *)W_CachePatchName("DSHADOW", PU_CACHE); - if (!(gpatch && gpatch->mipmap->format)) return; + gpatch = (patch_t *)W_CachePatchName("DSHADOW", PU_CACHE); + if (!(gpatch && ((GLPatch_t *)gpatch->hardware)->mipmap->format)) return; HWR_GetPatch(gpatch); scalemul = FixedMul(FRACUNIT - floordiff/640, scale); - scalemul = FixedMul(scalemul, (thing->radius*2) / SHORT(gpatch->height)); + scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height); fscale = FIXED_TO_FLOAT(scalemul); fx = FIXED_TO_FLOAT(thing->x); @@ -3592,9 +3592,9 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) // 0--1 if (thing && fabsf(fscale - 1.0f) > 1.0E-36f) - offset = (SHORT(gpatch->height)/2) * fscale; + offset = ((gpatch->height)/2) * fscale; else - offset = (float)(SHORT(gpatch->height)/2); + offset = (float)((gpatch->height)/2); shadowVerts[2].x = shadowVerts[3].x = fx + offset; shadowVerts[1].x = shadowVerts[0].x = fx - offset; @@ -3624,10 +3624,10 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) } shadowVerts[0].s = shadowVerts[3].s = 0; - shadowVerts[2].s = shadowVerts[1].s = gpatch->max_s; + shadowVerts[2].s = shadowVerts[1].s = ((GLPatch_t *)gpatch->hardware)->max_s; shadowVerts[3].t = shadowVerts[2].t = 0; - shadowVerts[0].t = shadowVerts[1].t = gpatch->max_t; + shadowVerts[0].t = shadowVerts[1].t = ((GLPatch_t *)gpatch->hardware)->max_t; if (thing->subsector->sector->numlights) { @@ -3687,7 +3687,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) float this_scale = 1.0f; FOutVector wallVerts[4]; FOutVector baseWallVerts[4]; // This is what the verts should end up as - GLPatch_t *gpatch; + patch_t *gpatch; FSurfaceInfo Surf; const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); extracolormap_t *colormap; @@ -3715,7 +3715,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) if (hires) this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)spr->mobj->skin)->highresscale); - gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE); + gpatch = spr->gpatch; // cache the patch in the graphics card memory //12/12/99: Hurdler: same comment as above (for md2) @@ -3740,25 +3740,25 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) if (spr->flip) { - baseWallVerts[0].s = baseWallVerts[3].s = gpatch->max_s; + baseWallVerts[0].s = baseWallVerts[3].s = ((GLPatch_t *)gpatch->hardware)->max_s; baseWallVerts[2].s = baseWallVerts[1].s = 0; } else { baseWallVerts[0].s = baseWallVerts[3].s = 0; - baseWallVerts[2].s = baseWallVerts[1].s = gpatch->max_s; + baseWallVerts[2].s = baseWallVerts[1].s = ((GLPatch_t *)gpatch->hardware)->max_s; } // flip the texture coords (look familiar?) if (spr->vflip) { - baseWallVerts[3].t = baseWallVerts[2].t = gpatch->max_t; + baseWallVerts[3].t = baseWallVerts[2].t = ((GLPatch_t *)gpatch->hardware)->max_t; baseWallVerts[0].t = baseWallVerts[1].t = 0; } else { baseWallVerts[3].t = baseWallVerts[2].t = 0; - baseWallVerts[0].t = baseWallVerts[1].t = gpatch->max_t; + baseWallVerts[0].t = baseWallVerts[1].t = ((GLPatch_t *)gpatch->hardware)->max_t; } // if it has a dispoffset, push it a little towards the camera @@ -3963,7 +3963,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) { float this_scale = 1.0f; FOutVector wallVerts[4]; - GLPatch_t *gpatch; // sprite patch converted to hardware + patch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); //const boolean papersprite = (spr->mobj && (spr->mobj->frame & FF_PAPERSPRITE)); @@ -3990,7 +3990,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) // sure to do it the right way. So actually, we keep normal sprite // in memory and we add the md2 model if it exists for that sprite - gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE); + gpatch = spr->gpatch; #ifdef ALAM_LIGHTING if (!(spr->mobj->flags2 & MF2_DEBRIS) && (spr->mobj->sprite != SPR_PLAY || @@ -4021,21 +4021,21 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) if (spr->flip) { - wallVerts[0].s = wallVerts[3].s = gpatch->max_s; + wallVerts[0].s = wallVerts[3].s = ((GLPatch_t *)gpatch->hardware)->max_s; wallVerts[2].s = wallVerts[1].s = 0; }else{ wallVerts[0].s = wallVerts[3].s = 0; - wallVerts[2].s = wallVerts[1].s = gpatch->max_s; + wallVerts[2].s = wallVerts[1].s = ((GLPatch_t *)gpatch->hardware)->max_s; } // flip the texture coords (look familiar?) if (spr->vflip) { - wallVerts[3].t = wallVerts[2].t = gpatch->max_t; + wallVerts[3].t = wallVerts[2].t = ((GLPatch_t *)gpatch->hardware)->max_t; wallVerts[0].t = wallVerts[1].t = 0; }else{ wallVerts[3].t = wallVerts[2].t = 0; - wallVerts[0].t = wallVerts[1].t = gpatch->max_t; + wallVerts[0].t = wallVerts[1].t = ((GLPatch_t *)gpatch->hardware)->max_t; } // cache the patch in the graphics card memory @@ -4121,7 +4121,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) { FBITFIELD blend = 0; FOutVector wallVerts[4]; - GLPatch_t *gpatch; // sprite patch converted to hardware + patch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; if (!spr->mobj) @@ -4131,7 +4131,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) return; // cache sprite graphics - gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE); + gpatch = spr->gpatch; // create the sprite billboard // @@ -4153,10 +4153,10 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) HWR_RotateSpritePolyToAim(spr, wallVerts, true); wallVerts[0].s = wallVerts[3].s = 0; - wallVerts[2].s = wallVerts[1].s = gpatch->max_s; + wallVerts[2].s = wallVerts[1].s = ((GLPatch_t *)gpatch->hardware)->max_s; wallVerts[3].t = wallVerts[2].t = 0; - wallVerts[0].t = wallVerts[1].t = gpatch->max_t; + wallVerts[0].t = wallVerts[1].t = ((GLPatch_t *)gpatch->hardware)->max_t; // cache the patch in the graphics card memory //12/12/99: Hurdler: same comment as above (for md2) @@ -5014,13 +5014,12 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->tz = tz; // Keep tz for the simple sprite sorting that happens vis->tracertz = tracertz; vis->dispoffset = dispoffset; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST - //vis->patchlumpnum = sprframe->lumppat[rot]; #ifdef ROTSPRITE if (rotsprite) - vis->gpatch = (GLPatch_t *)rotsprite; + vis->gpatch = (patch_t *)rotsprite; else #endif - vis->gpatch = (GLPatch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); + vis->gpatch = (patch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); vis->flip = flip; vis->mobj = thing; vis->z1 = z1; @@ -5155,8 +5154,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->z2 = z2; vis->tz = tz; vis->dispoffset = 0; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST - //vis->patchlumpnum = sprframe->lumppat[rot]; - vis->gpatch = (GLPatch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); + vis->gpatch = (patch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); vis->flip = flip; vis->mobj = (mobj_t *)thing; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index ddb3696b6..3bcef05de 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -35,9 +35,9 @@ void HWR_DrawViewBorder(INT32 clearlines); void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); void HWR_InitTextureMapping(void); void HWR_SetViewSize(void); -void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); -void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); -void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); +void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option); +void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); +void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index fa5156758..caef0a02d 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -348,48 +348,53 @@ static GLTextureFormat_t PCX_Load(const char *filename, int *w, int *h, // -----------------+ static void md2_loadTexture(md2_t *model) { - GLPatch_t *grpatch; + patch_t *patch; + GLPatch_t *grPatch = NULL; const char *filename = model->filename; if (model->grpatch) { - grpatch = model->grpatch; - Z_Free(grpatch->mipmap->data); + patch = model->grpatch; + grPatch = (GLPatch_t *)(patch->hardware); + if (grPatch) + Z_Free(grPatch->mipmap->data); } else - { - grpatch = Z_Calloc(sizeof *grpatch, PU_HWRPATCHINFO, - &(model->grpatch)); - grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL); - } + model->grpatch = patch = Patch_Create(NULL, 0, NULL); - if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) + if (!patch->hardware) + Patch_AllocateHardwarePatch(patch); + + if (grPatch == NULL) + grPatch = (GLPatch_t *)(patch->hardware); + + if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data) { int w = 0, h = 0; UINT32 size; RGBA_t *image; #ifdef HAVE_PNG - grpatch->mipmap->format = PNG_Load(filename, &w, &h, grpatch); - if (grpatch->mipmap->format == 0) + grPatch->mipmap->format = PNG_Load(filename, &w, &h, grPatch); + if (grPatch->mipmap->format == 0) #endif - grpatch->mipmap->format = PCX_Load(filename, &w, &h, grpatch); - if (grpatch->mipmap->format == 0) + grPatch->mipmap->format = PCX_Load(filename, &w, &h, grPatch); + if (grPatch->mipmap->format == 0) { model->notexturefile = true; // mark it so its not searched for again repeatedly return; } - grpatch->mipmap->downloaded = 0; - grpatch->mipmap->flags = 0; + grPatch->mipmap->downloaded = 0; + grPatch->mipmap->flags = 0; - grpatch->width = (INT16)w; - grpatch->height = (INT16)h; - grpatch->mipmap->width = (UINT16)w; - grpatch->mipmap->height = (UINT16)h; + patch->width = (INT16)w; + patch->height = (INT16)h; + grPatch->mipmap->width = (UINT16)w; + grPatch->mipmap->height = (UINT16)h; // Lactozilla: Apply colour cube - image = grpatch->mipmap->data; + image = grPatch->mipmap->data; size = w*h; while (size--) { @@ -397,7 +402,7 @@ static void md2_loadTexture(md2_t *model) image++; } } - HWD.pfnSetTexture(grpatch->mipmap); + HWD.pfnSetTexture(grPatch->mipmap); } // -----------------+ @@ -405,48 +410,53 @@ static void md2_loadTexture(md2_t *model) // -----------------+ static void md2_loadBlendTexture(md2_t *model) { - GLPatch_t *grpatch; + patch_t *patch; + GLPatch_t *grPatch = NULL; char *filename = Z_Malloc(strlen(model->filename)+7, PU_STATIC, NULL); - strcpy(filename, model->filename); + strcpy(filename, model->filename); FIL_ForceExtension(filename, "_blend.png"); if (model->blendgrpatch) { - grpatch = model->blendgrpatch; - Z_Free(grpatch->mipmap->data); + patch = model->blendgrpatch; + grPatch = (GLPatch_t *)(patch->hardware); + if (grPatch) + Z_Free(grPatch->mipmap->data); } else - { - grpatch = Z_Calloc(sizeof *grpatch, PU_HWRPATCHINFO, - &(model->blendgrpatch)); - grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL); - } + model->blendgrpatch = patch = Patch_Create(NULL, 0, NULL); - if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) + if (!patch->hardware) + Patch_AllocateHardwarePatch(patch); + + if (grPatch == NULL) + grPatch = (GLPatch_t *)(patch->hardware); + + if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data) { int w = 0, h = 0; #ifdef HAVE_PNG - grpatch->mipmap->format = PNG_Load(filename, &w, &h, grpatch); - if (grpatch->mipmap->format == 0) + grPatch->mipmap->format = PNG_Load(filename, &w, &h, grPatch); + if (grPatch->mipmap->format == 0) #endif - grpatch->mipmap->format = PCX_Load(filename, &w, &h, grpatch); - if (grpatch->mipmap->format == 0) + grPatch->mipmap->format = PCX_Load(filename, &w, &h, grPatch); + if (grPatch->mipmap->format == 0) { model->noblendfile = true; // mark it so its not searched for again repeatedly Z_Free(filename); return; } - grpatch->mipmap->downloaded = 0; - grpatch->mipmap->flags = 0; + grPatch->mipmap->downloaded = 0; + grPatch->mipmap->flags = 0; - grpatch->width = (INT16)w; - grpatch->height = (INT16)h; - grpatch->mipmap->width = (UINT16)w; - grpatch->mipmap->height = (UINT16)h; + patch->width = (INT16)w; + patch->height = (INT16)h; + grPatch->mipmap->width = (UINT16)w; + grPatch->mipmap->height = (UINT16)h; } - HWD.pfnSetTexture(grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary + HWD.pfnSetTexture(grPatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary Z_Free(filename); } @@ -664,8 +674,10 @@ spritemodelfound: #define SETBRIGHTNESS(brightness,r,g,b) \ brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000)) -static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolornum_t color) +static void HWR_CreateBlendedTexture(patch_t *gpatch, patch_t *blendgpatch, GLMipmap_t *grMipmap, INT32 skinnum, skincolornum_t color) { + GLPatch_t *hwrPatch = gpatch->hardware; + GLPatch_t *hwrBlendPatch = blendgpatch->hardware; UINT16 w = gpatch->width, h = gpatch->height; UINT32 size = w*h; RGBA_t *image, *blendimage, *cur, blendcolor; @@ -678,28 +690,29 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, memset(translation, 0, sizeof(translation)); memset(cutoff, 0, sizeof(cutoff)); - if (grmip->width == 0) + if (grMipmap->width == 0) { - grmip->width = gpatch->width; - grmip->height = gpatch->height; + grMipmap->width = gpatch->width; + grMipmap->height = gpatch->height; // no wrap around, no chroma key - grmip->flags = 0; + grMipmap->flags = 0; + // setup the texture info - grmip->format = GL_TEXFMT_RGBA; + grMipmap->format = GL_TEXFMT_RGBA; } - if (grmip->data) + if (grMipmap->data) { - Z_Free(grmip->data); - grmip->data = NULL; + Z_Free(grMipmap->data); + grMipmap->data = NULL; } - cur = Z_Malloc(size*4, PU_HWRMODELTEXTURE, &grmip->data); + cur = Z_Malloc(size*4, PU_HWRMODELTEXTURE, &grMipmap->data); memset(cur, 0x00, size*4); - image = gpatch->mipmap->data; - blendimage = blendgpatch->mipmap->data; + image = hwrPatch->mipmap->data; + blendimage = hwrBlendPatch->mipmap->data; // TC_METALSONIC includes an actual skincolor translation, on top of its flashing. if (skinnum == TC_METALSONIC) @@ -1038,37 +1051,39 @@ skippixel: #undef SETBRIGHTNESS -static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolornum_t color) +static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 skinnum, const UINT8 *colormap, skincolornum_t color) { // mostly copied from HWR_GetMappedPatch, hence the similarities and comment - GLMipmap_t *grmip, *newmip; + GLPatch_t *grPatch = patch->hardware; + GLPatch_t *grBlendPatch = NULL; + GLMipmap_t *grMipmap, *newMipmap; - if (colormap == colormaps || colormap == NULL) + if (blendpatch == NULL || colormap == colormaps || colormap == NULL) { // Don't do any blending - HWD.pfnSetTexture(gpatch->mipmap); + HWD.pfnSetTexture(grPatch->mipmap); return; } - if ((blendgpatch && blendgpatch->mipmap->format) - && (gpatch->width != blendgpatch->width || gpatch->height != blendgpatch->height)) + if ((blendpatch && (grBlendPatch = blendpatch->hardware) && grBlendPatch->mipmap->format) + && (patch->width != blendpatch->width || patch->height != blendpatch->height)) { // Blend image exists, but it's bad. - HWD.pfnSetTexture(gpatch->mipmap); + HWD.pfnSetTexture(grPatch->mipmap); return; } // search for the mipmap // skip the first (no colormap translated) - for (grmip = gpatch->mipmap; grmip->nextcolormap; ) + for (grMipmap = grPatch->mipmap; grMipmap->nextcolormap; ) { - grmip = grmip->nextcolormap; - if (grmip->colormap == colormap) + grMipmap = grMipmap->nextcolormap; + if (grMipmap->colormap == colormap) { - if (grmip->downloaded && grmip->data) + if (grMipmap->downloaded && grMipmap->data) { - HWD.pfnSetTexture(grmip); // found the colormap, set it to the correct texture - Z_ChangeTag(grmip->data, PU_HWRMODELTEXTURE_UNLOCKED); + HWD.pfnSetTexture(grMipmap); // found the colormap, set it to the correct texture + Z_ChangeTag(grMipmap->data, PU_HWRMODELTEXTURE_UNLOCKED); return; } } @@ -1081,16 +1096,16 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT // (it have a liste of mipmap) // this malloc is cleared in HWR_FreeTextureCache // (...) unfortunately z_malloc fragment alot the memory :(so malloc is better - newmip = calloc(1, sizeof (*newmip)); - if (newmip == NULL) + newMipmap = calloc(1, sizeof (*newMipmap)); + if (newMipmap == NULL) I_Error("%s: Out of memory", "HWR_GetBlendedTexture"); - grmip->nextcolormap = newmip; - newmip->colormap = colormap; + grMipmap->nextcolormap = newMipmap; + newMipmap->colormap = colormap; - HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, skinnum, color); + HWR_CreateBlendedTexture(patch, blendpatch, newMipmap, skinnum, color); - HWD.pfnSetTexture(newmip); - Z_ChangeTag(newmip->data, PU_HWRMODELTEXTURE_UNLOCKED); + HWD.pfnSetTexture(newMipmap); + Z_ChangeTag(newMipmap->data, PU_HWRMODELTEXTURE_UNLOCKED); } #define NORMALFOG 0x00000000 @@ -1177,9 +1192,11 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t return spr2; } -static void adjustTextureCoords(model_t *model, GLPatch_t *gpatch) +static void adjustTextureCoords(model_t *model, patch_t *patch) { int i; + GLPatch_t *gpatch = ((GLPatch_t *)patch->hardware); + for (i = 0; i < model->numMeshes; i++) { int j; @@ -1264,7 +1281,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) // Look at HWR_ProjectSprite for more { - GLPatch_t *gpatch; + patch_t *gpatch, *blendgpatch; + GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL; INT32 durs = spr->mobj->state->tics; INT32 tics = spr->mobj->tics; //mdlframe_t *next = NULL; @@ -1309,14 +1327,26 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) // texture loading before model init, so it knows if sprite graphics are used, which // means that texture coordinates have to be adjusted gpatch = md2->grpatch; - if (!gpatch || ((!gpatch->mipmap->format || !gpatch->mipmap->downloaded) && !md2->notexturefile)) - md2_loadTexture(md2); - gpatch = md2->grpatch; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture... + if (gpatch) + hwrPatch = ((GLPatch_t *)gpatch->hardware); - if ((gpatch && gpatch->mipmap->format) // don't load the blend texture if the base texture isn't available - && (!md2->blendgrpatch - || ((!((GLPatch_t *)md2->blendgrpatch)->mipmap->format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded) - && !md2->noblendfile))) + if (!gpatch || !hwrPatch + || ((!hwrPatch->mipmap->format || !hwrPatch->mipmap->downloaded) && !md2->notexturefile)) + md2_loadTexture(md2); + + // Load it again, because it isn't being loaded into gpatch after md2_loadtexture... + gpatch = md2->grpatch; + if (gpatch) + hwrPatch = ((GLPatch_t *)gpatch->hardware); + + // Load blend texture + blendgpatch = md2->blendgrpatch; + if (blendgpatch) + hwrBlendPatch = ((GLPatch_t *)blendgpatch->hardware); + + if ((gpatch && hwrPatch && hwrPatch->mipmap->format) // don't load the blend texture if the base texture isn't available + && (!blendgpatch || !hwrBlendPatch + || ((!hwrBlendPatch->mipmap->format || !hwrBlendPatch->mipmap->downloaded) && !md2->noblendfile))) md2_loadBlendTexture(md2); if (md2->error) @@ -1332,7 +1362,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) md2_printModelInfo(md2->model); // if model uses sprite patch as texture, then // adjust texture coordinates to take power of two textures into account - if (!gpatch || !gpatch->mipmap->format) + if (!gpatch || !hwrPatch->mipmap->format) adjustTextureCoords(md2->model, spr->gpatch); HWD.pfnCreateModelVBOs(md2->model); } @@ -1352,7 +1382,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) finalscale = md2->scale; //Hurdler: arf, I don't like that implementation at all... too much crappy - if (gpatch && gpatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture + if (gpatch && hwrPatch && hwrPatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture { INT32 skinnum = TC_DEFAULT; @@ -1385,13 +1415,12 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) } // Translation or skin number found - HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color); + HWR_GetBlendedTexture(gpatch, blendgpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color); } else { // Sprite - gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE); - HWR_GetMappedPatch(gpatch, spr->colormap); + HWR_GetMappedPatch(spr->gpatch, spr->colormap); } if (spr->mobj->frame & FF_ANIMATE) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 461966224..fbe65bc17 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1317,6 +1317,17 @@ void SetStates(void) } +// -----------------+ +// DeleteTexture : Deletes a texture from the GPU and frees its data +// -----------------+ +EXPORT void HWRAPI(DeleteTexture) (FTextureInfo *pTexInfo) +{ + if (pTexInfo->downloaded) + pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded); + pTexInfo->downloaded = 0; +} + + // -----------------+ // Flush : flush OpenGL textures // : Clear list of downloaded mipmaps @@ -1327,9 +1338,7 @@ void Flush(void) while (gl_cachehead) { - if (gl_cachehead->downloaded) - pglDeleteTextures(1, (GLuint *)&gl_cachehead->downloaded); - gl_cachehead->downloaded = 0; + DeleteTexture(gl_cachehead); gl_cachehead = gl_cachehead->nextmipmap; } gl_cachetail = gl_cachehead = NULL; //Hurdler: well, gl_cachehead is already NULL diff --git a/src/hu_stuff.c b/src/hu_stuff.c index b61192533..ff9f274fc 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2038,9 +2038,6 @@ static void HU_DrawDemoInfo(void) // void HU_Drawer(void) { - if (needpatchrecache) - R_ReloadHUDGraphics(); - #ifndef NONET // draw chat string plus cursor if (chat_on) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 830d97625..712983cac 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -379,7 +379,7 @@ static int lib_setSpriteInfo(lua_State *L) return luaL_error(L, "spriteinfo[] index %d out of range (1 - %d)", i, NUMSPRITES-1); #ifdef ROTSPRITE if (sprites != NULL) - R_FreeSingleRotSprite(&sprites[i]); + R_FreeRotSprite(&sprites[i]); #endif info = &spriteinfo[i]; // get the spriteinfo to assign to. } @@ -464,7 +464,7 @@ static int spriteinfo_set(lua_State *L) #ifdef ROTSPRITE if (sprites != NULL) - R_FreeSingleRotSprite(&sprites[sprinfo-spriteinfo]); + R_FreeRotSprite(&sprites[sprinfo-spriteinfo]); #endif if (fastcmp(field, "pivot")) diff --git a/src/m_menu.c b/src/m_menu.c index 59d297e1a..3d6b1c0fa 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1490,7 +1490,7 @@ static menuitem_t OP_SoundOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "MIDI Music", &cv_gamemidimusic, 36}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "MIDI Music Volume", &cv_midimusicvolume, 41}, - + {IT_STRING | IT_CVAR, NULL, "Music Preference", &cv_musicpref, 51}, {IT_HEADER, NULL, "Miscellaneous", NULL, 61}, @@ -5593,9 +5593,6 @@ static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, bo if (map <= 0) return; - if (needpatchrecache) - M_CacheLevelPlatter(); - // A 564x100 image of the level as entry MAPxxW if (!(levelselect.rows[row].mapavailable[col])) { @@ -5627,9 +5624,6 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea if (map <= 0) return; - if (needpatchrecache) - M_CacheLevelPlatter(); - // A 160x100 image of the level as entry MAPxxP if (!(levelselect.rows[row].mapavailable[col])) { @@ -6452,10 +6446,6 @@ static void M_DrawAddons(void) return; } - // Lactozilla: Load addons menu patches. - if (needpatchrecache) - M_LoadAddonsPatches(); - if (Playing()) V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems."); else @@ -7610,9 +7600,6 @@ static void M_DrawSoundTest(void) fixed_t hscale = FRACUNIT/2, vscale = FRACUNIT/2, bounce = 0; UINT8 frame[4] = {0, 0, -1, SKINCOLOR_RUBY}; - if (needpatchrecache) - M_CacheSoundTest(); - // let's handle the ticker first. ideally we'd tick this somewhere else, BUT... if (curplaying) { @@ -8260,9 +8247,6 @@ static void M_DrawLoadGameData(void) if (vid.width != BASEVIDWIDTH*vid.dupx) hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx); - if (needpatchrecache) - M_CacheLoadGameData(); - for (i = -2; i <= 2; i++) { savetodraw = (saveSlotSelected + i + numsaves)%numsaves; @@ -8966,7 +8950,6 @@ void M_ForceSaveSlotSelected(INT32 sslot) // CHARACTER SELECT // ================ -// lactozilla: sometimes the renderer changes and these patches don't exist anymore static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) { if (!(description[i].picname[0])) @@ -8987,22 +8970,6 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH); } -static void M_CacheCharacterSelect(void) -{ - INT32 i, skinnum; - - for (i = 0; i < MAXSKINS; i++) - { - if (!description[i].used) - continue; - - // Already set in M_SetupChoosePlayer - skinnum = description[i].skinnum[0]; - if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) - M_CacheCharacterSelectEntry(i, skinnum); - } -} - static UINT8 M_SetupChoosePlayerDirect(INT32 choice) { INT32 skinnum; @@ -9209,10 +9176,6 @@ static void M_DrawSetupChoosePlayerMenu(void) INT32 x, y; INT32 w = (vid.width/vid.dupx); - // lactozilla: the renderer changed so recache patches - if (needpatchrecache) - M_CacheCharacterSelect(); - if (abs(char_scroll) > FRACUNIT) char_scroll -= (char_scroll>>2); else // close enough. @@ -10584,10 +10547,6 @@ void M_DrawMarathon(void) angle_t fa; INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy), xspan = (vid.width/dupz), yspan = (vid.height/dupz), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy; - // lactozilla: the renderer changed so recache patches - if (needpatchrecache) - M_CacheCharacterSelect(); - curbgxspeed = 0; curbgyspeed = 18; diff --git a/src/r_data.c b/src/r_data.c index befb73c20..4b2ff7484 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -482,7 +482,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) UINT8 *blocktex; texture_t *texture; texpatch_t *patch; - patch_t *realpatch; + softwarepatch_t *realpatch; UINT8 *pdata; int x, x1, x2, i, width, height; size_t blocksize; @@ -512,7 +512,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) lumpnum = patch->lump; lumplength = W_LumpLengthPwad(wadnum, lumpnum); pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); - realpatch = (patch_t *)pdata; + realpatch = (softwarepatch_t *)pdata; #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) @@ -608,7 +608,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) lumpnum = patch->lump; pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); lumplength = W_LumpLengthPwad(wadnum, lumpnum); - realpatch = (patch_t *)pdata; + realpatch = (softwarepatch_t *)pdata; dealloc = true; #ifndef NO_PNG_LUMPS diff --git a/src/r_defs.h b/src/r_defs.h index 132106bc8..10fc99ccd 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -652,16 +652,26 @@ typedef enum RGBA32 = 4, // 32 bit rgba } pic_mode_t; -#if defined(_MSC_VER) -#pragma pack(1) -#endif - // Patches. // A patch holds one or more columns. // Patches are used for sprites and all masked pictures, and we compose // textures from the TEXTURES list of patches. // -// WARNING: this structure is cloned in GLPatch_t +typedef struct +{ + INT16 width, height; + INT16 leftoffset, topoffset; + + INT32 *columnofs; // Column offsets. This is relative to patch->columns + UINT8 *columns; // Software column data + + void *hardware; // OpenGL patch, allocated whenever necessary +} patch_t; + +#if defined(_MSC_VER) +#pragma pack(1) +#endif + typedef struct { INT16 width; // bounding box size @@ -670,7 +680,7 @@ typedef struct INT16 topoffset; // pixels below the origin INT32 columnofs[8]; // only [width] used // the [0] is &columnofs[width] -} ATTRPACK patch_t; +} ATTRPACK softwarepatch_t; #ifdef _MSC_VER #pragma warning(disable : 4200) diff --git a/src/r_main.c b/src/r_main.c index 4f79dd8db..b70e6f25f 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1572,14 +1572,6 @@ void R_InitHardwareMode(void) } #endif -void R_ReloadHUDGraphics(void) -{ - CONS_Debug(DBG_RENDER, "R_ReloadHUDGraphics()...\n"); - ST_LoadGraphics(); - HU_LoadGraphics(); - ST_ReloadSkinFaceGraphics(); -} - // ========================================================================= // ENGINE COMMANDS & VARS // ========================================================================= diff --git a/src/r_main.h b/src/r_main.h index 729ec6973..cc098462d 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -115,7 +115,6 @@ void R_Init(void); #ifdef HWRENDER void R_InitHardwareMode(void); #endif -void R_ReloadHUDGraphics(void); void R_CheckViewMorph(void); void R_ApplyViewMorph(void); diff --git a/src/r_patch.c b/src/r_patch.c index 8980eda58..783c1fbec 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -50,6 +50,98 @@ static unsigned char imgbuf[1<<26]; +// +// Creates a patch. +// Assumes a PU_PATCH zone memory tag and no user, but can always be set later +// + +patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest) +{ + patch_t *patch = (dest == NULL) ? Z_Calloc(sizeof(patch_t), PU_PATCH, NULL) : (patch_t *)(dest); + + if (source) + { + INT32 col, colsize; + size_t size = sizeof(INT32) * source->width; + size_t offs = (sizeof(INT16) * 4) + size; + + patch->width = source->width; + patch->height = source->height; + patch->leftoffset = source->leftoffset; + patch->topoffset = source->topoffset; + patch->columnofs = Z_Calloc(size, PU_PATCH, NULL); + + for (col = 0; col < source->width; col++) + { + // This makes the column offsets relative to the column data itself, + // instead of the entire patch data + patch->columnofs[col] = LONG(source->columnofs[col]) - offs; + } + + if (!srcsize) + I_Error("R_CreatePatch: no source size!"); + + colsize = (INT32)(srcsize) - (INT32)offs; + if (colsize <= 0) + I_Error("R_CreatePatch: no column data!"); + + patch->columns = Z_Calloc(colsize, PU_PATCH, NULL); + M_Memcpy(patch->columns, ((UINT8 *)source + LONG(source->columnofs[0])), colsize); + } + + if (patch->hardware) + I_Error("wtf?\n"); + + return patch; +} + +// +// Frees a patch from memory. +// + +void Patch_Free(patch_t *patch) +{ +#ifdef HWRENDER + if (patch->hardware) + HWR_FreeTexture(patch); +#endif + + if (patch->columnofs) + Z_Free(patch->columnofs); + if (patch->columns) + Z_Free(patch->columns); + + Z_Free(patch); +} + +#ifdef HWRENDER +// +// Allocates a hardware patch. +// + +void *Patch_AllocateHardwarePatch(patch_t *patch) +{ + if (!patch->hardware) + { + GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, &patch->hardware); + grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, &grPatch->mipmap); + } + return (void *)(patch->hardware); +} + +// +// Creates a hardware patch. +// + +void *Patch_CreateGL(patch_t *patch) +{ + GLPatch_t *grPatch = (GLPatch_t *)Patch_AllocateHardwarePatch(patch); + if (!grPatch->mipmap->data) // Run HWR_MakePatch in all cases, to recalculate some things + HWR_MakePatch(patch, grPatch, grPatch->mipmap, false); + return grPatch; +} +#endif // HWRENDER + // // R_CheckIfPatch // @@ -177,7 +269,7 @@ void R_PatchToFlat(patch_t *patch, UINT8 *flat) for (col = 0; col < SHORT(patch->width); col++, desttop++) { INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[col])); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[col])); while (column->topdelta != 0xff) { @@ -220,7 +312,7 @@ void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip) for (col = 0; col < SHORT(patch->width); col++, desttop++) { INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-col) : col])); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[flip ? (patch->width-1-col) : col])); while (column->topdelta != 0xff) { topdelta = column->topdelta; @@ -244,7 +336,7 @@ void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip) // // Convert a flat to a patch. // -patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency) +softwarepatch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency) { UINT32 x, y; UINT8 *img; @@ -350,7 +442,7 @@ patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffse if (destsize != NULL) *destsize = size; - return (patch_t *)img; + return (softwarepatch_t *)img; } // @@ -359,7 +451,7 @@ patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffse // Convert a masked flat to a patch. // Explanation of "masked" flats in R_PatchToMaskedFlat. // -patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize) +softwarepatch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize) { UINT32 x, y; UINT8 *img; @@ -464,7 +556,7 @@ patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 le if (destsize != NULL) *destsize = size; - return (patch_t *)img; + return (softwarepatch_t *)img; } // @@ -736,7 +828,7 @@ UINT8 *R_PNGToFlat(UINT16 *width, UINT16 *height, UINT8 *png, size_t size) // // Convert a PNG to a patch. // -patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize) +softwarepatch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize) { UINT16 width, height; INT16 topoffset = 0, leftoffset = 0; @@ -981,7 +1073,7 @@ static void R_ParseSpriteInfo(boolean spr2) #ifdef ROTSPRITE if ((sprites != NULL) && (!spr2)) - R_FreeSingleRotSprite(&sprites[sprnum]); + R_FreeRotSprite(&sprites[sprnum]); #endif // Left Curly Brace @@ -1143,10 +1235,10 @@ static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) column_t *column; UINT8 *source; - if (x >= 0 && x < SHORT(patch->width)) + if (x >= 0 && x < patch->width) { INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-x) : x])); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[flip ? (patch->width-1-x) : x])); while (column->topdelta != 0xff) { topdelta = column->topdelta; @@ -1194,8 +1286,8 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp { UINT32 i; INT32 angle; - patch_t *patch; - patch_t *newpatch; + patch_t *patch, *newpatch; + softwarepatch_t *swpatch; UINT16 *rawdst; size_t size; INT32 bflip = (flip != 0x00); @@ -1212,28 +1304,14 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp INT32 width, height, leftoffset; fixed_t ca, sa; lumpnum_t lump = sprframe->lumppat[rot]; -#ifndef NO_PNG_LUMPS - size_t lumplength; -#endif if (lump == LUMPERROR) return; - patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC); -#ifndef NO_PNG_LUMPS - lumplength = W_LumpLength(lump); - - if (R_IsLumpPNG((UINT8 *)patch, lumplength)) - patch = R_PNGToPatch((UINT8 *)patch, lumplength, NULL); - else -#endif - // Because there's something wrong with SPR_DFLM, I guess - if (!R_CheckIfPatch(lump)) - return; - - width = SHORT(patch->width); - height = SHORT(patch->height); - leftoffset = SHORT(patch->leftoffset); + patch = (patch_t *)W_CachePatchNum(lump, PU_STATIC); + width = patch->width; + height = patch->height; + leftoffset = patch->leftoffset; // rotation pivot px = SPRITE_XCENTER; @@ -1345,37 +1423,33 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp } // make patch - newpatch = R_MaskedFlatToPatch(rawdst, newwidth, newheight, 0, 0, &size); + swpatch = R_MaskedFlatToPatch(rawdst, newwidth, newheight, 0, 0, &size); { - newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px); - newpatch->topoffset = (newpatch->height / 2) + (SHORT(patch->topoffset) - py); + swpatch->leftoffset = (swpatch->width / 2) + (leftoffset - px); + swpatch->topoffset = (swpatch->height / 2) + (patch->topoffset - py); } //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer if (rendermode != render_none) // not for psprite - newpatch->topoffset += FEETADJUST>>FRACBITS; + swpatch->topoffset += FEETADJUST>>FRACBITS; // P_PrecacheLevel if (devparm) spritememory += size; // convert everything to little-endian, for big-endian support - newpatch->width = SHORT(newpatch->width); - newpatch->height = SHORT(newpatch->height); - newpatch->leftoffset = SHORT(newpatch->leftoffset); - newpatch->topoffset = SHORT(newpatch->topoffset); + swpatch->width = SHORT(swpatch->width); + swpatch->height = SHORT(swpatch->height); + swpatch->leftoffset = SHORT(swpatch->leftoffset); + swpatch->topoffset = SHORT(swpatch->topoffset); + + newpatch = Patch_Create(swpatch, size, NULL); #ifdef HWRENDER if (rendermode == render_opengl) - { - GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL); - grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL); - grPatch->rawpatch = newpatch; - sprframe->rotsprite.patch[rot][angle] = (patch_t *)grPatch; - HWR_MakePatch(newpatch, grPatch, grPatch->mipmap, false); - } - else -#endif // HWRENDER - sprframe->rotsprite.patch[rot][angle] = newpatch; + Patch_CreateGL(newpatch); +#endif + + sprframe->rotsprite.patch[rot][angle] = newpatch; // free rotated image data Z_Free(rawdst); @@ -1386,6 +1460,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp // free image data Z_Free(patch); + Z_Free(swpatch); } #undef SPRITE_XCENTER #undef SPRITE_YCENTER @@ -1394,11 +1469,11 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp } // -// R_FreeSingleRotSprite +// R_FreeRotSprite // // Free sprite rotation data from memory, for a single spritedef. // -void R_FreeSingleRotSprite(spritedef_t *spritedef) +void R_FreeRotSprite(spritedef_t *spritedef) { UINT8 frame; INT32 rot, ang; @@ -1414,30 +1489,8 @@ void R_FreeSingleRotSprite(spritedef_t *spritedef) { patch_t *rotsprite = sprframe->rotsprite.patch[rot][ang]; if (rotsprite) - { -#ifdef HWRENDER - if (rendermode == render_opengl) - { - GLPatch_t *grPatch = (GLPatch_t *)rotsprite; - if (grPatch->rawpatch) - { - Z_Free(grPatch->rawpatch); - grPatch->rawpatch = NULL; - } - if (grPatch->mipmap) - { - if (grPatch->mipmap->data) - { - Z_Free(grPatch->mipmap->data); - grPatch->mipmap->data = NULL; - } - Z_Free(grPatch->mipmap); - grPatch->mipmap = NULL; - } - } -#endif - Z_Free(rotsprite); - } + Patch_Free(rotsprite); + rotsprite = NULL; } sprframe->rotsprite.cached &= ~(1<sprites; for (i = 0; i < NUMPLAYERSPRITES*2; i++) { - R_FreeSingleRotSprite(skinsprites); + R_FreeRotSprite(skinsprites); skinsprites++; } } - -// -// R_FreeAllRotSprite -// -// Free ALL sprite rotation data from memory. -// -void R_FreeAllRotSprite(void) -{ - INT32 i; - size_t s; - for (s = 0; s < numsprites; s++) - R_FreeSingleRotSprite(&sprites[s]); - for (i = 0; i < numskins; ++i) - R_FreeSkinRotSprite(i); -} #endif diff --git a/src/r_patch.h b/src/r_patch.h index a2db6320c..de4981fba 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -37,21 +37,30 @@ typedef struct boolean available; } spriteinfo_t; +// Patch functions +patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest); +void Patch_Free(patch_t *patch); + +#ifdef HWRENDER +void *Patch_AllocateHardwarePatch(patch_t *patch); +void *Patch_CreateGL(patch_t *patch); +#endif + // Conversions between patches / flats / textures... boolean R_CheckIfPatch(lumpnum_t lump); void R_TextureToFlat(size_t tex, UINT8 *flat); void R_PatchToFlat(patch_t *patch, UINT8 *flat); void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip); -patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency); -patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize); +softwarepatch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency); +softwarepatch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize); -// Portable Network Graphics +// PNGs boolean R_IsLumpPNG(const UINT8 *d, size_t s); #define W_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename); // Fears Of LJ Sonic #ifndef NO_PNG_LUMPS UINT8 *R_PNGToFlat(UINT16 *width, UINT16 *height, UINT8 *png, size_t size); -patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize); +softwarepatch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize); boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size); #endif @@ -64,11 +73,10 @@ void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); #ifdef ROTSPRITE INT32 R_GetRollAngle(angle_t rollangle); void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip); -void R_FreeSingleRotSprite(spritedef_t *spritedef); +void R_FreeRotSprite(spritedef_t *spritedef); void R_FreeSkinRotSprite(size_t skinnum); extern fixed_t rollcosang[ROTANGLES]; extern fixed_t rollsinang[ROTANGLES]; -void R_FreeAllRotSprite(void); #endif #endif // __R_PATCH__ diff --git a/src/r_segs.c b/src/r_segs.c index d9fc75838..177827892 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -217,7 +217,7 @@ static void R_DrawWallSplats(void) continue; // draw the texture - col = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); + col = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); R_DrawSplatColumn(col); } } // next splat diff --git a/src/r_things.c b/src/r_things.c index c0795acd5..0636a880d 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -228,7 +228,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 UINT8 frame; UINT8 rotation; lumpinfo_t *lumpinfo; - patch_t patch; + softwarepatch_t patch; UINT8 numadded = 0; memset(sprtemp,0xFF, sizeof (sprtemp)); @@ -241,7 +241,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 if (spritedef->numframes) // (then spriteframes is not null) { #ifdef ROTSPRITE - R_FreeSingleRotSprite(spritedef); + R_FreeRotSprite(spritedef); #endif // copy the already defined sprite frames M_Memcpy(sprtemp, spritedef->spriteframes, @@ -277,7 +277,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 W_ReadLumpHeaderPwad(wadnum, l, &patch, sizeof (patch_t), 0); #ifndef NO_PNG_LUMPS { - patch_t *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC); + softwarepatch_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)) @@ -398,7 +398,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 spritedef->numframes < maxframe) // more frames are defined ? { #ifdef ROTSPRITE - R_FreeSingleRotSprite(spritedef); + R_FreeRotSprite(spritedef); #endif Z_Free(spritedef->spriteframes); spritedef->spriteframes = NULL; @@ -910,7 +910,7 @@ static void R_DrawVisSprite(vissprite_t *vis) sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); dc_iscale = (0xffffffffu / (unsigned)spryscale); - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); localcolfunc (column); } @@ -928,9 +928,9 @@ static void R_DrawVisSprite(vissprite_t *vis) texturecolumn = frac>>FRACBITS; if (texturecolumn < 0 || texturecolumn >= pwidth) I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); #else - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS])); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); #endif localcolfunc (column); } @@ -995,9 +995,9 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) I_Error("R_DrawPrecipitationSpriteRange: bad texturecolumn"); - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); #else - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS])); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); #endif R_DrawMaskedColumn(column); } diff --git a/src/screen.c b/src/screen.c index e7ff9e735..f5d19cada 100644 --- a/src/screen.c +++ b/src/screen.c @@ -202,9 +202,6 @@ void SCR_SetMode(void) // Lactozilla: Renderer switching if (setrenderneeded) { - Z_PreparePatchFlush(); - needpatchflush = true; - needpatchrecache = true; VID_CheckRenderer(); if (!setmodeneeded) VID_SetMode(vid.modenum); diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 416c8d2f5..e1845fac8 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -86,6 +86,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(ClearBuffer); GETFUNC(SetTexture); GETFUNC(UpdateTexture); + GETFUNC(DeleteTexture); GETFUNC(ReadRect); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 01194a02f..1bb48e468 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1660,7 +1660,7 @@ static void Impl_SetWindowName(const char *title) static void Impl_SetWindowIcon(void) { if (window && icoSurface) - SDL_SetWindowIcon(window, icoSurface); + SDL_SetWindowIcon(window, icoSurface); } static void Impl_VideoSetupSDLBuffer(void) @@ -1770,7 +1770,7 @@ void I_StartupGraphics(void) // Window icon #ifdef HAVE_IMAGE icoSurface = IMG_ReadXPMFromArray(SDL_icon_xpm); -#endif +#endif // Fury: we do window initialization after GL setup to allow // SDL_GL_LoadLibrary to work well on Windows @@ -1836,6 +1836,7 @@ void VID_StartupOpenGL(void) HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL); + HWD.pfnDeleteTexture = hwSym("DeleteTexture",NULL); HWD.pfnReadRect = hwSym("ReadRect",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); diff --git a/src/st_stuff.c b/src/st_stuff.c index d5aa5fbac..f6ba94fcc 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2755,9 +2755,6 @@ static void ST_overlayDrawer(void) void ST_Drawer(void) { - if (needpatchrecache) - R_ReloadHUDGraphics(); - #ifdef SEENAMES if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo) { diff --git a/src/v_video.c b/src/v_video.c index b88c4838b..7f07852fa 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -531,7 +531,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca //if (rendermode != render_soft && !con_startup) // Why? if (rendermode == render_opengl) { - HWR_DrawStretchyFixedPatch((GLPatch_t *)patch, x, y, pscale, vscale, scrn, colormap); + HWR_DrawStretchyFixedPatch(patch, x, y, pscale, vscale, scrn, colormap); return; } #endif @@ -716,7 +716,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); + column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[0])); if (!column->topdelta) { source = (const UINT8 *)(column) + 3; @@ -784,7 +784,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca if (x+offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) break; } - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); + column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); while (column->topdelta != 0xff) { @@ -831,7 +831,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ //if (rendermode != render_soft && !con_startup) // Not this again if (rendermode == render_opengl) { - HWR_DrawCroppedPatch((GLPatch_t*)patch,x,y,pscale,scrn,sx,sy,w,h); + HWR_DrawCroppedPatch(patch,x,y,pscale,scrn,sx,sy,w,h); return; } #endif @@ -1007,7 +1007,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ continue; if (x >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) break; - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[col>>FRACBITS])); + column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); while (column->topdelta != 0xff) { diff --git a/src/w_wad.c b/src/w_wad.c index e4a19f30e..f40f4eb4a 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -836,11 +836,6 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) 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 - wadfile->hwrcache = M_AATreeAlloc(AATREE_ZUSER); -#endif - // // add the wadfile // @@ -1676,13 +1671,7 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) if (!lumpcache[lump]) { size_t len = W_LumpLengthPwad(wad, lump); - void *ptr, *lumpdata; -#ifndef NO_PNG_LUMPS - void *srcdata = NULL; -#endif - - ptr = Z_Malloc(len, tag, &lumpcache[lump]); - lumpdata = Z_Malloc(len, tag, NULL); + void *ptr, *dest, *lumpdata = Z_Malloc(len, PU_STATIC, NULL); // read the lump in full W_ReadLumpHeaderPwad(wad, lump, lumpdata, 0, 0); @@ -1692,14 +1681,25 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) if (R_IsLumpPNG((UINT8 *)lumpdata, len)) { size_t newlen; - srcdata = R_PNGToPatch((UINT8 *)lumpdata, len, &newlen); - ptr = Z_Realloc(ptr, newlen, tag, &lumpcache[lump]); - M_Memcpy(ptr, srcdata, newlen); - Z_Free(srcdata); + void *converted = R_PNGToPatch((UINT8 *)lumpdata, len, &newlen); + ptr = Z_Malloc(newlen, PU_STATIC, NULL); + M_Memcpy(ptr, converted, newlen); + Z_Free(converted); + len = newlen; } else // just copy it into the patch cache #endif + { + ptr = Z_Malloc(len, PU_STATIC, NULL); M_Memcpy(ptr, lumpdata, len); + } + + Z_Free(lumpdata); + + dest = Z_Calloc(sizeof(patch_t), tag, &lumpcache[lump]); + Patch_Create(ptr, len, dest); + + Z_Free(ptr); } else Z_ChangeTag(lumpcache[lump], tag); @@ -1714,45 +1714,22 @@ void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag) void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { -#ifdef HWRENDER - GLPatch_t *grPatch; -#endif + patch_t *patch; if (!TestValidLump(wad, lump)) return NULL; + patch = W_CacheSoftwarePatchNumPwad(wad, lump, tag); + #ifdef HWRENDER // Software-only compile cache the data without conversion if (rendermode == render_soft || rendermode == render_none) #endif - { - return W_CacheSoftwarePatchNumPwad(wad, lump, tag); - } + return (void *)patch; + #ifdef HWRENDER - - grPatch = HWR_GetCachedGLPatchPwad(wad, lump); - - if (grPatch->mipmap->data) - { - if (tag == PU_CACHE) - tag = PU_HWRCACHE; - Z_ChangeTag(grPatch->mipmap->data, tag); - } - else - { - patch_t *ptr = NULL; - - // Only load the patch if we haven't initialised the grPatch yet - if (grPatch->mipmap->width == 0) - ptr = W_CacheLumpNumPwad(grPatch->wadnum, grPatch->lumpnum, PU_STATIC); - - // Run HWR_MakePatch in all cases, to recalculate some things - HWR_MakePatch(ptr, grPatch, grPatch->mipmap, false); - Z_Free(ptr); - } - - // return GLPatch_t, which can be casted to (patch_t) with valid patch header info - return (void *)grPatch; + Patch_CreateGL(patch); + return (void *)patch; #endif } @@ -1767,7 +1744,7 @@ void W_UnlockCachedPatch(void *patch) // have different lifetimes from software's. #ifdef HWRENDER if (rendermode == render_opengl) - HWR_UnlockCachedPatch((GLPatch_t*)patch); + HWR_UnlockCachedPatch((GLPatch_t *)((patch_t *)patch)->hardware); else #endif Z_Unlock(patch); diff --git a/src/w_wad.h b/src/w_wad.h index fddc65529..ee3df9cf4 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -102,10 +102,6 @@ virtlump_t* vres_Find(const virtres_t*, const char*); #define lumpcache_t void * -#ifdef HWRENDER -#include "m_aatree.h" -#endif - // Resource type of the WAD. Yeah, I know this sounds dumb, but I'll leave it like this until I clean up the code further. typedef enum restype { @@ -123,9 +119,6 @@ typedef struct wadfile_s lumpinfo_t *lumpinfo; lumpcache_t *lumpcache; lumpcache_t *patchcache; -#ifdef HWRENDER - aatree_t *hwrcache; // patches are cached in renderer's native format -#endif UINT16 numlumps; // this wad's number of resources FILE *handle; UINT32 filesize; // for network diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index 3f6c5e290..54526975e 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -107,6 +107,7 @@ static loadfunc_t hwdFuncTable[] = { {"ClearBuffer@12", &hwdriver.pfnClearBuffer}, {"SetTexture@4", &hwdriver.pfnSetTexture}, {"UpdateTexture@4", &hwdriver.pfnUpdateTexture}, + {"DeleteTexture@4", &hwdriver.pfnDeleteTexture}, {"ReadRect@24", &hwdriver.pfnReadRect}, {"GClipRect@20", &hwdriver.pfnGClipRect}, {"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache}, @@ -139,6 +140,7 @@ static loadfunc_t hwdFuncTable[] = { {"ClearBuffer", &hwdriver.pfnClearBuffer}, {"SetTexture", &hwdriver.pfnSetTexture}, {"UpdateTexture", &hwdriver.pfnUpdateTexture}, + {"DeleteTexture", &hwdriver.pfnDeleteTexture}, {"ReadRect", &hwdriver.pfnReadRect}, {"GClipRect", &hwdriver.pfnGClipRect}, {"ClearMipMapCache", &hwdriver.pfnClearMipMapCache}, diff --git a/src/y_inter.c b/src/y_inter.c index d857d60dc..4810ce7fa 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -158,7 +158,6 @@ typedef struct boolean usebuffer = false; static boolean useinterpic; -static boolean safetorender = true; static y_buffer_t *y_buffer; static INT32 intertic; @@ -175,7 +174,6 @@ static void Y_CalculateCompetitionWinners(void); static void Y_CalculateTimeRaceWinners(void); static void Y_CalculateMatchWinners(void); static void Y_UnloadData(void); -static void Y_CleanupData(void); // Stuff copy+pasted from st_stuff.c #define ST_DrawNumFromHud(h,n) V_DrawTallNum(hudinfo[h].x, hudinfo[h].y, hudinfo[h].f, n) @@ -322,19 +320,6 @@ void Y_IntermissionDrawer(void) if (intertype == int_none || rendermode == render_none) return; - // Lactozilla: Renderer switching - if (needpatchrecache) - { - Y_CleanupData(); - safetorender = false; - } - - if (!safetorender) - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - - if (!safetorender) - goto dontdrawbg; - if (useinterpic) V_DrawScaledPatch(0, 0, 0, interpic); else if (!usetile) @@ -372,7 +357,6 @@ void Y_IntermissionDrawer(void) if (!LUA_HudEnabled(hud_intermissiontally)) goto skiptallydrawer; -dontdrawbg: if (intertype == int_coop) { INT32 bonusy; @@ -422,17 +406,14 @@ dontdrawbg: bonusy = 150; // Total - if (safetorender) - { - V_DrawScaledPatch(152, bonusy, 0, data.coop.ptotal); - V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.total); - } + V_DrawScaledPatch(152, bonusy, 0, data.coop.ptotal); + V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.total); bonusy -= (3*SHORT(tallnum[0]->height)/2) + 1; // Draw bonuses for (i = 3; i >= 0; --i) { - if (data.coop.bonuses[i].display && safetorender) + if (data.coop.bonuses[i].display) { V_DrawScaledPatch(152, bonusy, 0, data.coop.bonuspatches[i]); V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.bonuses[i].points); @@ -661,8 +642,7 @@ dontdrawbg: char strtime[10]; // draw the header - if (safetorender) - V_DrawScaledPatch(112, 2, 0, data.match.result); + V_DrawScaledPatch(112, 2, 0, data.match.result); // draw the level name V_DrawCenteredString(BASEVIDWIDTH/2, 20, 0, data.match.levelstring); @@ -1218,8 +1198,6 @@ void Y_StartIntermission(void) I_Error("endtic is dirty"); #endif - safetorender = true; - if (!multiplayer) { timer = 0; @@ -2067,7 +2045,6 @@ void Y_EndIntermission(void) } #define UNLOAD(x) if (x) {Z_ChangeTag(x, PU_CACHE);} x = NULL; -#define CLEANUP(x) x = NULL; // // Y_UnloadData @@ -2118,45 +2095,3 @@ static void Y_UnloadData(void) break; } } - -static void Y_CleanupData(void) -{ - // unload the background patches - CLEANUP(bgpatch); - CLEANUP(bgtile); - CLEANUP(interpic); - - switch (intertype) - { - case int_coop: - // unload the coop and single player patches - CLEANUP(data.coop.bonuspatches[3]); - CLEANUP(data.coop.bonuspatches[2]); - CLEANUP(data.coop.bonuspatches[1]); - CLEANUP(data.coop.bonuspatches[0]); - CLEANUP(data.coop.ptotal); - break; - case int_spec: - // unload the special stage patches - //CLEANUP(data.spec.cemerald); - //CLEANUP(data.spec.nowsuper); - CLEANUP(data.spec.bonuspatches[1]); - CLEANUP(data.spec.bonuspatches[0]); - CLEANUP(data.spec.pscore); - CLEANUP(data.spec.pcontinues); - break; - case int_match: - case int_race: - CLEANUP(data.match.result); - break; - case int_ctf: - CLEANUP(data.match.blueflag); - CLEANUP(data.match.redflag); - break; - default: - //without this default, - //int_none, int_tag, int_chaos, and int_classicrace - //are not handled - break; - } -} diff --git a/src/z_zone.c b/src/z_zone.c index 2387a1143..7a6dfe040 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -499,33 +499,6 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag) // Utility functions // ----------------- -// for renderer switching -boolean needpatchflush = false; -boolean needpatchrecache = false; - -// flush all patches from memory -void Z_FlushCachedPatches(void) -{ - CONS_Debug(DBG_RENDER, "Z_FlushCachedPatches()...\n"); - Z_FreeTag(PU_PATCH); - Z_FreeTag(PU_HUDGFX); - Z_FreeTag(PU_HWRPATCHINFO); - Z_FreeTag(PU_HWRMODELTEXTURE); - Z_FreeTag(PU_HWRCACHE); - Z_FreeTag(PU_HWRCACHE_UNLOCKED); - Z_FreeTag(PU_HWRPATCHINFO_UNLOCKED); - Z_FreeTag(PU_HWRMODELTEXTURE_UNLOCKED); -} - -// happens before a renderer switch -void Z_PreparePatchFlush(void) -{ - CONS_Debug(DBG_RENDER, "Z_PreparePatchFlush()...\n"); -#ifdef ROTSPRITE - R_FreeAllRotSprite(); -#endif -} - // starting value of nextcleanup #define CLEANUPCOUNT 2000 diff --git a/src/z_zone.h b/src/z_zone.h index 5cbcc6655..c9dafc1ae 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -144,10 +144,4 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag); char *Z_StrDup(const char *in); #define Z_Unlock(p) (void)p // TODO: remove this now that NDS code has been removed -// For renderer switching -extern boolean needpatchflush; -extern boolean needpatchrecache; -void Z_FlushCachedPatches(void); -void Z_PreparePatchFlush(void); - #endif From f6a5acc6f323e12b6ac9f7325fd2999107c5a8b0 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 8 Aug 2020 14:56:04 -0300 Subject: [PATCH 02/81] Remove LUA_PATCH_SAFETY --- src/doomdef.h | 3 -- src/lua_hudlib.c | 80 ------------------------------------------------ src/r_defs.h | 18 ----------- 3 files changed, 101 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index fab83d38c..d45bd3fad 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -629,9 +629,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// \note Required for proper collision with moving sloped surfaces that have sector specials on them. #define SECTORSPECIALSAFTERTHINK -/// Cache patches in Lua in a way that renderer switching will work flawlessly. -//#define LUA_PATCH_SAFETY - /// Sprite rotation #define ROTSPRITE #define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 4aa70574b..d8375e1e8 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -35,11 +35,6 @@ static UINT8 hud_enabled[(hud_MAX/8)+1]; static UINT8 hudAvailable; // hud hooks field -#ifdef LUA_PATCH_SAFETY -static patchinfo_t *patchinfo, *patchinfohead; -static int numluapatches; -#endif - // must match enum hud in lua_hud.h static const char *const hud_disable_options[] = { "stagetitle", @@ -292,11 +287,7 @@ static int colormap_get(lua_State *L) static int patch_get(lua_State *L) { -#ifdef LUA_PATCH_SAFETY patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); -#else - patchinfo_t *patch = *((patchinfo_t **)luaL_checkudata(L, 1, META_PATCH)); -#endif enum patch field = luaL_checkoption(L, 2, NULL, patch_opt); // patches are invalidated when switching renderers @@ -403,59 +394,8 @@ static int libd_patchExists(lua_State *L) static int libd_cachePatch(lua_State *L) { -#ifdef LUA_PATCH_SAFETY - int i; - lumpnum_t lumpnum; - patchinfo_t *luapat; - patch_t *realpatch; - - HUDONLY - - luapat = patchinfohead; - lumpnum = W_CheckNumForLongName(luaL_checkstring(L, 1)); - if (lumpnum == LUMPERROR) - lumpnum = W_GetNumForLongName("MISSING"); - - for (i = 0; i < numluapatches; i++) - { - // check if already cached - if (luapat->wadnum == WADFILENUM(lumpnum) && luapat->lumpnum == LUMPNUM(lumpnum)) - { - LUA_PushUserdata(L, luapat, META_PATCH); - return 1; - } - luapat = luapat->next; - if (!luapat) - break; - } - - if (numluapatches > 0) - { - patchinfo->next = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL); - patchinfo = patchinfo->next; - } - else - { - patchinfo = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL); - patchinfohead = patchinfo; - } - - realpatch = W_CachePatchNum(lumpnum, PU_PATCH); - - patchinfo->width = realpatch->width; - patchinfo->height = realpatch->height; - patchinfo->leftoffset = realpatch->leftoffset; - patchinfo->topoffset = realpatch->topoffset; - - patchinfo->wadnum = WADFILENUM(lumpnum); - patchinfo->lumpnum = LUMPNUM(lumpnum); - - LUA_PushUserdata(L, patchinfo, META_PATCH); - numluapatches++; -#else HUDONLY LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); -#endif return 1; } @@ -651,22 +591,14 @@ static int libd_draw(lua_State *L) { INT32 x, y, flags; patch_t *patch; -#ifdef LUA_PATCH_SAFETY - patchinfo_t *luapat; -#endif const UINT8 *colormap = NULL; HUDONLY x = luaL_checkinteger(L, 1); y = luaL_checkinteger(L, 2); -#ifdef LUA_PATCH_SAFETY - luapat = *((patchinfo_t **)luaL_checkudata(L, 3, META_PATCH)); - patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH); -#else patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH)); if (!patch) return LUA_ErrInvalid(L, "patch_t"); -#endif flags = luaL_optinteger(L, 4, 0); if (!lua_isnoneornil(L, 5)) colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP)); @@ -682,9 +614,6 @@ static int libd_drawScaled(lua_State *L) fixed_t x, y, scale; INT32 flags; patch_t *patch; -#ifdef LUA_PATCH_SAFETY - patchinfo_t *luapat; -#endif const UINT8 *colormap = NULL; HUDONLY @@ -693,14 +622,9 @@ static int libd_drawScaled(lua_State *L) scale = luaL_checkinteger(L, 3); if (scale < 0) return luaL_error(L, "negative scale"); -#ifdef LUA_PATCH_SAFETY - luapat = *((patchinfo_t **)luaL_checkudata(L, 4, META_PATCH)); - patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH); -#else patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH)); if (!patch) return LUA_ErrInvalid(L, "patch_t"); -#endif flags = luaL_optinteger(L, 5, 0); if (!lua_isnoneornil(L, 6)) colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP)); @@ -1247,10 +1171,6 @@ int LUA_HudLib(lua_State *L) { memset(hud_enabled, 0xff, (hud_MAX/8)+1); -#ifdef LUA_PATCH_SAFETY - numluapatches = 0; -#endif - lua_newtable(L); // HUD registry table lua_newtable(L); luaL_register(L, NULL, lib_draw); diff --git a/src/r_defs.h b/src/r_defs.h index 10fc99ccd..becf2aed8 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -727,24 +727,6 @@ typedef enum SRF_NONE = 0xff // Initial value } spriterotateflags_t; // SRF's up! -// Same as a patch_t, except just the header -// and the wadnum/lumpnum combination that points -// to wherever the patch is in memory. -struct patchinfo_s -{ - INT16 width; // bounding box size - INT16 height; - INT16 leftoffset; // pixels to the left of origin - INT16 topoffset; // pixels below the origin - - UINT16 wadnum; // the software patch lump num for when the patch - UINT16 lumpnum; // was flushed, and we need to re-create it - - // next patchinfo_t in memory - struct patchinfo_s *next; -}; -typedef struct patchinfo_s patchinfo_t; - // // Sprites are patches with a special naming convention so they can be // recognized by R_InitSprites. From c5cda018eadcb639fb95080cef8853165276b0e7 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 14 Aug 2020 20:48:15 -0300 Subject: [PATCH 03/81] Cache the console patch only once in CON_DrawBackpic --- src/console.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/console.c b/src/console.c index 280dc4f22..e9c0138d7 100644 --- a/src/console.c +++ b/src/console.c @@ -1543,8 +1543,8 @@ static void CON_DrawBackpic(void) if (piclump == LUMPERROR) piclump = W_GetNumForName("MISSING"); - // Cache the Software patch. - con_backpic = W_CacheSoftwarePatchNum(piclump, PU_PATCH); + // Cache the patch. + con_backpic = W_CachePatchNum(piclump, PU_PATCH); // Center the backpic, and draw a vertically cropped patch. w = (con_backpic->width * vid.dupx); @@ -1567,8 +1567,7 @@ static void CON_DrawBackpic(void) } } - // Cache the patch normally. - con_backpic = W_CachePatchNum(piclump, PU_PATCH); + // Draw the patch. V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, V_NOSCALESTART, con_backpic, 0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h); From cb3660331a1ac4596ec946ed6d5ef510280c308c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 14 Aug 2020 22:27:16 -0300 Subject: [PATCH 04/81] Refactor renderer switching --- src/android/i_video.c | 12 ++- src/console.c | 28 ++++--- src/console.h | 4 + src/d_main.c | 45 +++++------- src/dummy/i_video.c | 12 ++- src/hardware/hw_cache.c | 94 +++++++++++++++++------- src/hardware/hw_glob.h | 10 ++- src/hardware/hw_main.c | 15 +++- src/hardware/hw_main.h | 1 - src/hardware/hw_md2.c | 2 +- src/i_video.h | 8 +- src/m_menu.c | 15 +++- src/p_setup.c | 14 ++-- src/p_setup.h | 2 +- src/r_data.c | 4 +- src/r_main.c | 12 --- src/r_main.h | 3 - src/screen.c | 158 ++++++++++++---------------------------- src/screen.h | 26 +++++-- src/sdl/i_video.c | 103 ++++++++++++++++---------- src/v_video.c | 33 +++++++++ src/v_video.h | 3 + src/w_wad.c | 2 +- src/win32/win_vid.c | 8 +- 24 files changed, 343 insertions(+), 271 deletions(-) diff --git a/src/android/i_video.c b/src/android/i_video.c index 1909cd71a..a38078a5d 100644 --- a/src/android/i_video.c +++ b/src/android/i_video.c @@ -9,6 +9,7 @@ #include "utils/Log.h" rendermode_t rendermode = render_soft; +rendermode_t chosenrendermode = render_none; boolean highcolor = false; @@ -52,8 +53,15 @@ INT32 VID_SetMode(INT32 modenum) return 0; } -void VID_CheckRenderer(void) {} -void VID_CheckGLLoaded(rendermode_t oldrender) {} +boolean VID_CheckRenderer(void) +{ + return false; +} + +void VID_CheckGLLoaded(rendermode_t oldrender) +{ + (void)oldrender; +} const char *VID_GetModeName(INT32 modenum) { diff --git a/src/console.c b/src/console.c index e9c0138d7..630feb2aa 100644 --- a/src/console.c +++ b/src/console.c @@ -45,7 +45,8 @@ #define MAXHUDLINES 20 static boolean con_started = false; // console has been initialised - boolean con_startup = false; // true at game startup, screen need refreshing + boolean con_startup = false; // true at game startup + boolean con_refresh = false; // screen needs refreshing static boolean con_forcepic = true; // at startup toggle console translucency when first off boolean con_recalc; // set true when screen size has changed @@ -406,7 +407,8 @@ void CON_Init(void) if (!dedicated) { con_started = true; - con_startup = true; // need explicit screen refresh until we are in Doom loop + con_startup = true; + con_refresh = true; // needs explicit screen refresh until we are in the main game loop consoletoggle = false; CV_RegisterVar(&cons_msgtimeout); CV_RegisterVar(&cons_hudlines); @@ -419,7 +421,8 @@ void CON_Init(void) else { con_started = true; - con_startup = false; // need explicit screen refresh until we are in Doom loop + con_startup = false; + con_refresh = false; // disable explicit screen refresh consoletoggle = true; } } @@ -1293,16 +1296,19 @@ void CONS_Printf(const char *fmt, ...) con_scrollup = 0; // if not in display loop, force screen update - if (con_startup && (!setrenderneeded)) + if (con_refresh) { -#ifdef _WINDOWS - patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH); +#if defined(_WINDOWS) + if (con_startup) + { + patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH); - // Jimita: CON_DrawBackpic just called V_DrawScaledPatch - V_DrawScaledPatch(0, 0, 0, con_backpic); + // Jimita: CON_DrawBackpic just called V_DrawScaledPatch + V_DrawScaledPatch(0, 0, 0, con_backpic); - W_UnlockCachedPatch(con_backpic); - I_LoadingScreen(txt); // Win32/OS2 only + W_UnlockCachedPatch(con_backpic); + I_LoadingScreen(txt); // Win32/OS2 only + } #else // here we display the console text CON_Drawer(); @@ -1369,7 +1375,7 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) // void CONS_Error(const char *msg) { -#ifdef RPC_NO_WINDOWS_H +#if defined(RPC_NO_WINDOWS_H) && defined(_WINDOWS) if (!graphics_started) { MessageBoxA(vid.WndParent, msg, "SRB2 Warning", MB_OK); diff --git a/src/console.h b/src/console.h index 2be92d62b..6f38ca8d0 100644 --- a/src/console.h +++ b/src/console.h @@ -20,8 +20,12 @@ boolean CON_Responder(event_t *ev); // set true when screen size has changed, to adapt console extern boolean con_recalc; +// console being displayed at game startup extern boolean con_startup; +// needs explicit screen refresh until we are in the main game loop +extern boolean con_refresh; + // top clip value for view render: do not draw part of view hidden by console extern INT32 con_clipviewtop; diff --git a/src/d_main.c b/src/d_main.c index ee3ce699c..6144abd85 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -220,7 +220,6 @@ INT16 wipetypepost = -1; static void D_Display(void) { - INT32 setrenderstillneeded = 0; boolean forcerefresh = false; static boolean wipe = false; INT32 wipedefindex = 0; @@ -245,36 +244,21 @@ static void D_Display(void) // modes (resolution) are called. // 4. The frame is ready to be drawn! - // stop movie if needs to change renderer - if (setrenderneeded && (moviemode == MM_APNG)) - M_StopMovie(); - - // check for change of renderer or screen size (video mode) + // Check for change of renderer or screen size (video mode) if ((setrenderneeded || setmodeneeded) && !wipe) - { - if (setrenderneeded) - { - CONS_Debug(DBG_RENDER, "setrenderneeded set (%d)\n", setrenderneeded); - setrenderstillneeded = setrenderneeded; - } SCR_SetMode(); // change video mode - } - if (vid.recalc || setrenderstillneeded) - { + // Recalc the screen + if (vid.recalc) SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc() -#ifdef HWRENDER - // Shoot! The screen texture was flushed! - if ((rendermode == render_opengl) && (gamestate == GS_INTERMISSION)) - usebuffer = false; -#endif - } + // View morph if (rendermode == render_soft && !splitscreen) R_CheckViewMorph(); - // change the view size if needed - if (setsizeneeded || setrenderstillneeded) + // Change the view size if needed + // Set by changing video mode or renderer + if (setsizeneeded) { R_ExecuteSetViewSize(); forcerefresh = true; // force background redraw @@ -697,6 +681,7 @@ void D_SRB2Loop(void) oldentertics = I_GetTime(); // end of loading screen: CONS_Printf() will no more call FinishUpdate() + con_refresh = false; con_startup = false; // make sure to do a d_display to init mode _before_ load a level @@ -1402,14 +1387,20 @@ void D_SRB2Main(void) // set user default mode or mode set at cmdline SCR_CheckDefaultMode(); - // Lactozilla: Does the render mode need to change? - if ((setrenderneeded != 0) && (setrenderneeded != rendermode)) + // Lactozilla: Check if the render mode needs to change. + if (setrenderneeded) { CONS_Printf(M_GetText("Switching the renderer...\n")); + // Switch the renderer in the interface + if (VID_CheckRenderer()) + con_refresh = true; // Allow explicit screen refresh again + // Set cv_renderer to the new render mode - VID_CheckRenderer(); - SCR_ChangeRendererCVars(rendermode); + CV_StealthSetValue(&cv_renderer, rendermode); +#ifdef HWRENDER + CV_StealthSetValue(&cv_newrenderer, rendermode); +#endif } wipegamestate = gamestate; diff --git a/src/dummy/i_video.c b/src/dummy/i_video.c index 56ead3672..38a67ef37 100644 --- a/src/dummy/i_video.c +++ b/src/dummy/i_video.c @@ -3,6 +3,7 @@ #include "../i_video.h" rendermode_t rendermode = render_none; +rendermode_t chosenrendermode = render_none; boolean highcolor = false; @@ -40,8 +41,15 @@ INT32 VID_SetMode(INT32 modenum) return 0; } -void VID_CheckRenderer(void) {} -void VID_CheckGLLoaded(rendermode_t oldrender) {} +boolean VID_CheckRenderer(void) +{ + return false; +} + +void VID_CheckGLLoaded(rendermode_t oldrender) +{ + (void)oldrender; +} const char *VID_GetModeName(INT32 modenum) { diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index a26721169..901c0184a 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -585,23 +585,27 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm static size_t gl_numtextures = 0; // Texture count static GLMapTexture_t *gl_textures; // For all textures static GLMapTexture_t *gl_flats; // For all (texture) flats, as normal flats don't need to be cached - -void HWR_InitTextureCache(void) -{ - gl_textures = NULL; - gl_flats = NULL; -} +boolean gl_maptexturesloaded = false; void HWR_FreeTexture(patch_t *patch) { + if (!patch) + return; + if (patch->hardware) { GLPatch_t *grPatch = patch->hardware; HWR_FreeTextureColormaps(patch); - if (grPatch->mipmap && (rendermode == render_opengl)) - HWD.pfnDeleteTexture(grPatch->mipmap); + if (grPatch->mipmap) + { + if (vid.glstate == VID_GL_LIBRARY_LOADED) + HWD.pfnDeleteTexture(grPatch->mipmap); + if (grPatch->mipmap->data) + Z_Free(grPatch->mipmap->data); + Z_Free(grPatch->mipmap); + } Z_Free(patch->hardware); } @@ -609,7 +613,7 @@ void HWR_FreeTexture(patch_t *patch) patch->hardware = NULL; } -// Called by HWR_FreeTextureCache. +// Called by HWR_FreePatchCache. void HWR_FreeTextureColormaps(patch_t *patch) { GLPatch_t *pat; @@ -653,10 +657,22 @@ void HWR_FreeTextureColormaps(patch_t *patch) } } -void HWR_FreeMipmapCache(void) +static void HWR_FreePatchCache(boolean freeall) { INT32 i; + for (i = 0; i < numwadfiles; i++) + { + INT32 j = 0; + for (; j < wadfiles[i]->numlumps; j++) + (freeall ? HWR_FreeTexture : HWR_FreeTextureColormaps)(wadfiles[i]->patchcache[j]); + } +} + +void HWR_ClearAllTextures(void) +{ + HWR_FreeMapTextures(); + // free references to the textures HWD.pfnClearMipMapCache(); @@ -666,19 +682,38 @@ void HWR_FreeMipmapCache(void) Z_FreeTag(PU_HWRCACHE_UNLOCKED); // Alam: free the Z_Blocks before freeing it's users - // free all patch colormaps after each level: must be done after ClearMipMapCache! - for (i = 0; i < numwadfiles; i++) - { - INT32 j = 0; - for (; j < wadfiles[i]->numlumps; j++) - HWR_FreeTextureColormaps(wadfiles[i]->patchcache[j]); - } + HWR_FreePatchCache(true); } -void HWR_FreeTextureCache(void) +// free all patch colormaps after each level: must be done after ClearMipMapCache! +void HWR_FreeColormapCache(void) { - // free references to the textures - HWR_FreeMipmapCache(); + HWR_FreePatchCache(false); +} + +void HWR_InitMapTextures(void) +{ + gl_textures = NULL; + gl_flats = NULL; + gl_maptexturesloaded = false; +} + +static void FreeMapTexture(GLMapTexture_t *tex) +{ + HWD.pfnDeleteTexture(&tex->mipmap); + if (tex->mipmap.data) + Z_Free(tex->mipmap.data); +} + +void HWR_FreeMapTextures(void) +{ + size_t i; + + for (i = 0; i < gl_numtextures; i++) + { + FreeMapTexture(&gl_textures[i]); + FreeMapTexture(&gl_flats[i]); + } // now the heap don't have any 'user' pointing to our // texturecache info, we can free it @@ -689,12 +724,13 @@ void HWR_FreeTextureCache(void) gl_textures = NULL; gl_flats = NULL; gl_numtextures = 0; + gl_maptexturesloaded = false; } -void HWR_LoadTextures(size_t pnumtextures) +void HWR_LoadMapTextures(size_t pnumtextures) { // we must free it since numtextures changed - HWR_FreeTextureCache(); + HWR_FreeMapTextures(); // Why not Z_Malloc? gl_numtextures = pnumtextures; @@ -704,7 +740,9 @@ void HWR_LoadTextures(size_t pnumtextures) // Doesn't tell you which it _is_, but hopefully // should never ever happen (right?!) if ((gl_textures == NULL) || (gl_flats == NULL)) - I_Error("HWR_LoadTextures: ran out of memory for OpenGL textures. Sad!"); + I_Error("HWR_LoadMapTextures: ran out of memory for OpenGL textures. Sad!"); + + gl_maptexturesloaded = true; } void HWR_SetPalette(RGBA_t *palette) @@ -814,10 +852,13 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum) void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum) { GLMipmap_t *grmip; + patch_t *patch; + if (flatlumpnum == LUMPERROR) return; - grmip = ((GLPatch_t *)HWR_GetCachedGLPatch(flatlumpnum)->hardware)->mipmap; + patch = HWR_GetCachedGLPatch(flatlumpnum); + grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap; if (!grmip->downloaded && !grmip->data) HWR_CacheFlat(grmip, flatlumpnum); @@ -933,7 +974,7 @@ void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap) //BP: WARNING: don't free it manually without clearing the cache of harware renderer // (it have a liste of mipmap) - // this malloc is cleared in HWR_FreeTextureCache + // this malloc is cleared in HWR_FreeColormapCache // (...) unfortunately z_malloc fragment alot the memory :(so malloc is better newMipmap = calloc(1, sizeof (*newMipmap)); if (newMipmap == NULL) @@ -1190,7 +1231,8 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum) void HWR_GetFadeMask(lumpnum_t fademasklumpnum) { - GLMipmap_t *grmip = ((GLPatch_t *)HWR_GetCachedGLPatch(fademasklumpnum)->hardware)->mipmap; + patch_t *patch = HWR_GetCachedGLPatch(fademasklumpnum); + GLMipmap_t *grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap; if (!grmip->downloaded && !grmip->data) HWR_CacheFadeMask(grmip, fademasklumpnum); diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 94c553535..b16a0f231 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -90,9 +90,11 @@ void HWR_FreeExtraSubsectors(void); // -------- // hw_cache.c // -------- -void HWR_InitTextureCache(void); -void HWR_FreeTextureCache(void); -void HWR_FreeMipmapCache(void); +void HWR_InitMapTextures(void); +void HWR_LoadMapTextures(size_t pnumtextures); +void HWR_FreeMapTextures(void); + +extern boolean gl_maptexturesloaded; patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump); patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum); @@ -108,6 +110,8 @@ void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum); void HWR_FreeTexture(patch_t *patch); void HWR_FreeTextureColormaps(patch_t *patch); +void HWR_ClearAllTextures(void); +void HWR_FreeColormapCache(void); void HWR_UnlockCachedPatch(GLPatch_t *gpatch); void HWR_SetPalette(RGBA_t *palette); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 7ba7f911c..e9d52c791 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5930,7 +5930,7 @@ void HWR_Startup(void) HWR_InitPolyPool(); HWR_AddSessionCommands(); - HWR_InitTextureCache(); + HWR_InitMapTextures(); HWR_InitModels(); #ifdef ALAM_LIGHTING HWR_InitLight(); @@ -5954,9 +5954,20 @@ void HWR_Startup(void) // -------------------------------------------------------------------------- void HWR_Switch(void) { + // Add session commands + HWR_AddSessionCommands(); + // Set special states from CVARs HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value); HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value); + + // Load textures + if (!gl_maptexturesloaded) + HWR_LoadMapTextures(numtextures); + + // Create plane polygons + if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)) + HWR_LoadLevel(); } // -------------------------------------------------------------------------- @@ -5967,7 +5978,7 @@ void HWR_Shutdown(void) CONS_Printf("HWR_Shutdown()\n"); HWR_FreeExtraSubsectors(); HWR_FreePolyPool(); - HWR_FreeTextureCache(); + HWR_FreeMapTextures(); HWD.pfnFlushScreenTextures(); } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 3bcef05de..780572a85 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -41,7 +41,6 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum); -void HWR_LoadTextures(size_t pnumtextures); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength); void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 actualcolor); // Lat: separate flags from color since color needs to be an uint to work right. diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index caef0a02d..057ef62c1 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1094,7 +1094,7 @@ static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 ski //BP: WARNING: don't free it manually without clearing the cache of harware renderer // (it have a liste of mipmap) - // this malloc is cleared in HWR_FreeTextureCache + // this malloc is cleared in HWR_FreeColormapCache // (...) unfortunately z_malloc fragment alot the memory :(so malloc is better newMipmap = calloc(1, sizeof (*newMipmap)); if (newMipmap == NULL) diff --git a/src/i_video.h b/src/i_video.h index 98ed7f38a..ab48881d4 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -36,10 +36,9 @@ typedef enum */ extern rendermode_t rendermode; -/** \brief OpenGL state - 0 = never loaded, 1 = loaded successfully, -1 = failed loading +/** \brief render mode set by command line arguments */ -extern INT32 vid_opengl_state; +extern rendermode_t chosenrendermode; /** \brief use highcolor modes if true */ @@ -90,8 +89,9 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h); INT32 VID_SetMode(INT32 modenum); /** \brief Checks the render state + \return true if the renderer changed */ -void VID_CheckRenderer(void); +boolean VID_CheckRenderer(void); /** \brief Load OpenGL mode */ diff --git a/src/m_menu.c b/src/m_menu.c index 3d6b1c0fa..0e60dce0c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2149,15 +2149,22 @@ menu_t OP_PlaystyleDef = { static void M_VideoOptions(INT32 choice) { (void)choice; + + OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR); + OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer"; + OP_VideoOptionsMenu[op_video_renderer].text = "Software"; + #ifdef HWRENDER - if (vid_opengl_state == -1) + if (vid.glstate != VID_GL_LIBRARY_ERROR) { - OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR); - OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer"; - OP_VideoOptionsMenu[op_video_renderer].text = "Software"; + OP_VideoOptionsMenu[op_video_renderer].status = (IT_STRING | IT_CVAR); + OP_VideoOptionsMenu[op_video_renderer].patch = NULL; + OP_VideoOptionsMenu[op_video_renderer].text = "Renderer"; } + CV_StealthSetValue(&cv_newrenderer, cv_renderer.value); #endif + M_SetupNextMenu(&OP_VideoOptionsDef); } diff --git a/src/p_setup.c b/src/p_setup.c index ceb96df40..0105a06da 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4146,13 +4146,11 @@ boolean P_LoadLevel(boolean fromnetsave) #ifdef HWRENDER // not win32 only 19990829 by Kin // Lactozilla: Free extrasubsectors regardless of renderer. - // Maybe we're not in OpenGL anymore. - if (extrasubsectors) - free(extrasubsectors); - extrasubsectors = NULL; - // stuff like HWR_CreatePlanePolygons is called there + HWR_FreeExtraSubsectors(); + + // Create plane polygons. if (rendermode == render_opengl) - HWR_SetupLevel(); + HWR_LoadLevel(); #endif // oh god I hope this helps @@ -4238,7 +4236,7 @@ boolean P_LoadLevel(boolean fromnetsave) } #ifdef HWRENDER -void HWR_SetupLevel(void) +void HWR_LoadLevel(void) { // Lactozilla (December 8, 2019) // Level setup used to free EVERY mipmap from memory. @@ -4249,7 +4247,7 @@ void HWR_SetupLevel(void) // when the texture list is loaded. // Sal: Unfortunately, NOT freeing them causes the dreaded Color Bug. - HWR_FreeMipmapCache(); + HWR_FreeColormapCache(); #ifdef ALAM_LIGHTING // BP: reset light between levels (we draw preview frame lights on current frame) diff --git a/src/p_setup.h b/src/p_setup.h index e7150c0ae..497870628 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -99,7 +99,7 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); void P_RespawnThings(void); boolean P_LoadLevel(boolean fromnetsave); #ifdef HWRENDER -void HWR_SetupLevel(void); +void HWR_LoadLevel(void); #endif boolean P_AddWadFile(const char *wadfilename); boolean P_RunSOC(const char *socfilename); diff --git a/src/r_data.c b/src/r_data.c index 4b2ff7484..dc2c41150 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -33,7 +33,7 @@ #endif #ifdef HWRENDER -#include "hardware/hw_main.h" // HWR_LoadTextures +#include "hardware/hw_main.h" // HWR_LoadMapTextures #endif #if defined(_MSC_VER) @@ -1084,7 +1084,7 @@ void R_LoadTextures(void) #ifdef HWRENDER if (rendermode == render_opengl) - HWR_LoadTextures(numtextures); + HWR_LoadMapTextures(numtextures); #endif } diff --git a/src/r_main.c b/src/r_main.c index b70e6f25f..883ac0abf 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1560,18 +1560,6 @@ void R_RenderPlayerView(player_t *player) free(masks); } -// Lactozilla: Renderer switching -#ifdef HWRENDER -void R_InitHardwareMode(void) -{ - HWR_AddSessionCommands(); - HWR_Switch(); - HWR_LoadTextures(numtextures); - if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)) - HWR_SetupLevel(); -} -#endif - // ========================================================================= // ENGINE COMMANDS & VARS // ========================================================================= diff --git a/src/r_main.h b/src/r_main.h index cc098462d..6c0aec3f5 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -112,9 +112,6 @@ extern consvar_t cv_tailspickup; // Called by startup code. void R_Init(void); -#ifdef HWRENDER -void R_InitHardwareMode(void); -#endif void R_CheckViewMorph(void); void R_ApplyViewMorph(void); diff --git a/src/screen.c b/src/screen.c index f5d19cada..d460e1f6d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -28,6 +28,7 @@ #include "d_main.h" #include "d_clisrv.h" #include "f_finale.h" +#include "y_inter.h" // usebuffer #include "i_sound.h" // closed captions #include "s_sound.h" // ditto #include "g_game.h" // ditto @@ -63,7 +64,6 @@ consvar_t cv_scr_height = {"scr_height", "800", CV_SAVE, CV_Unsigned, NULL, 0, N consvar_t cv_scr_depth = {"scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static void SCR_ActuallyChangeRenderer(void); CV_PossibleValue_t cv_renderer_t[] = { {1, "Software"}, #ifdef HWRENDER @@ -71,7 +71,7 @@ CV_PossibleValue_t cv_renderer_t[] = { #endif {0, NULL} }; -consvar_t cv_renderer = {"renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_ChangeRenderer, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_renderer = {"renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_SetTargetRenderer, 0, NULL, NULL, 0, 0, NULL}; static void SCR_ChangeFullscreen(void); @@ -202,11 +202,15 @@ void SCR_SetMode(void) // Lactozilla: Renderer switching if (setrenderneeded) { + // stop recording movies (APNG only) + if (setrenderneeded && (moviemode == MM_APNG)) + M_StopMovie(); + VID_CheckRenderer(); - if (!setmodeneeded) - VID_SetMode(vid.modenum); + vid.recalc = 1; } + // Set the video mode in the video interface. if (setmodeneeded) VID_SetMode(--setmodeneeded); @@ -276,34 +280,9 @@ void SCR_Startup(void) vid.modenum = 0; - vid.dupx = vid.width / BASEVIDWIDTH; - vid.dupy = vid.height / BASEVIDHEIGHT; - vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); - vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); - -#ifdef HWRENDER - if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl -#endif - vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); - - vid.meddupx = (UINT8)(vid.dupx >> 1) + 1; - vid.meddupy = (UINT8)(vid.dupy >> 1) + 1; -#ifdef HWRENDER - vid.fmeddupx = vid.meddupx*FRACUNIT; - vid.fmeddupy = vid.meddupy*FRACUNIT; -#endif - - vid.smalldupx = (UINT8)(vid.dupx / 3) + 1; - vid.smalldupy = (UINT8)(vid.dupy / 3) + 1; -#ifdef HWRENDER - vid.fsmalldupx = vid.smalldupx*FRACUNIT; - vid.fsmalldupy = vid.smalldupy*FRACUNIT; -#endif - - vid.baseratio = FRACUNIT; - V_Init(); + V_Recalc(); + CV_RegisterVar(&cv_ticrate); CV_RegisterVar(&cv_constextsize); @@ -320,38 +299,7 @@ void SCR_Recalc(void) // bytes per pixel quick access scr_bpp = vid.bpp; - // scale 1,2,3 times in x and y the patches for the menus and overlays... - // calculated once and for all, used by routines in v_video.c - vid.dupx = vid.width / BASEVIDWIDTH; - vid.dupy = vid.height / BASEVIDHEIGHT; - vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); - vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); - -#ifdef HWRENDER - //if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl - // 13/11/18: - // The above is no longer necessary, since we want OpenGL to be just like software now - // -- Monster Iestyn -#endif - vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); - - //vid.baseratio = FixedDiv(vid.height << FRACBITS, BASEVIDHEIGHT << FRACBITS); - vid.baseratio = FRACUNIT; - - vid.meddupx = (UINT8)(vid.dupx >> 1) + 1; - vid.meddupy = (UINT8)(vid.dupy >> 1) + 1; -#ifdef HWRENDER - vid.fmeddupx = vid.meddupx*FRACUNIT; - vid.fmeddupy = vid.meddupy*FRACUNIT; -#endif - - vid.smalldupx = (UINT8)(vid.dupx / 3) + 1; - vid.smalldupy = (UINT8)(vid.dupy / 3) + 1; -#ifdef HWRENDER - vid.fsmalldupx = vid.smalldupx*FRACUNIT; - vid.fsmalldupy = vid.smalldupy*FRACUNIT; -#endif + V_Recalc(); // toggle off (then back on) the automap because some screensize-dependent values will // be calculated next time the automap is activated. @@ -371,6 +319,12 @@ void SCR_Recalc(void) // vid.recalc lasts only for the next refresh... con_recalc = true; am_recalc = true; + +#ifdef HWRENDER + // Shoot! The screen texture was flushed! + if ((rendermode == render_opengl) && (gamestate == GS_INTERMISSION)) + usebuffer = false; +#endif } // Check for screen cmd-line parms: to force a resolution. @@ -408,7 +362,19 @@ void SCR_CheckDefaultMode(void) setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; } - SCR_ActuallyChangeRenderer(); + if (cv_renderer.value != (signed)rendermode) + { + if (chosenrendermode == render_none) // nothing set at command line + SCR_ChangeRenderer(); + else + { + // Set cv_renderer to the current render mode + CV_StealthSetValue(&cv_renderer, rendermode); +#ifdef HWRENDER + CV_StealthSetValue(&cv_newrenderer, rendermode); +#endif + } + } } // sets the modenum as the new default video mode to be saved in the config file @@ -438,67 +404,33 @@ void SCR_ChangeFullscreen(void) #endif } -static int target_renderer = 0; - -void SCR_ActuallyChangeRenderer(void) +void SCR_SetTargetRenderer(void) { - setrenderneeded = target_renderer; + if (!con_refresh) + SCR_ChangeRenderer(); +} + +void SCR_ChangeRenderer(void) +{ + if ((signed)rendermode == cv_renderer.value) + return; #ifdef HWRENDER - // Well, it didn't even load anyway. - if ((vid_opengl_state == -1) && (setrenderneeded == render_opengl)) + // Check if OpenGL loaded successfully (or wasn't disabled) before switching to it. + if ((vid.glstate == VID_GL_LIBRARY_ERROR) + && (cv_renderer.value == render_opengl)) { if (M_CheckParm("-nogl")) CONS_Alert(CONS_ERROR, "OpenGL rendering was disabled!\n"); else CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); - setrenderneeded = 0; return; } #endif - // setting the same renderer twice WILL crash your game, so let's not, please - if (rendermode == setrenderneeded) - setrenderneeded = 0; -} - -// Lactozilla: Renderer switching -void SCR_ChangeRenderer(void) -{ - setrenderneeded = 0; - - if (con_startup) - { - target_renderer = cv_renderer.value; -#ifdef HWRENDER - if (M_CheckParm("-opengl") && (vid_opengl_state == 1)) - target_renderer = rendermode = render_opengl; - else -#endif - if (M_CheckParm("-software")) - target_renderer = rendermode = render_soft; - // set cv_renderer back - SCR_ChangeRendererCVars(rendermode); - return; - } - - if (cv_renderer.value == 1) - target_renderer = render_soft; - else if (cv_renderer.value == 2) - target_renderer = render_opengl; - SCR_ActuallyChangeRenderer(); -} - -void SCR_ChangeRendererCVars(INT32 mode) -{ - // set cv_renderer back - if (mode == render_soft) - CV_StealthSetValue(&cv_renderer, 1); - else if (mode == render_opengl) - CV_StealthSetValue(&cv_renderer, 2); -#ifdef HWRENDER - CV_StealthSetValue(&cv_newrenderer, cv_renderer.value); -#endif + // Set the new render mode + setrenderneeded = cv_renderer.value; + con_refresh = false; } boolean SCR_IsAspectCorrect(INT32 width, INT32 height) diff --git a/src/screen.h b/src/screen.h index 91ec175f4..3f6c91d05 100644 --- a/src/screen.h +++ b/src/screen.h @@ -72,10 +72,16 @@ typedef struct viddef_s #ifdef HWRENDER INT32/*fixed_t*/ fsmalldupx, fsmalldupy; INT32/*fixed_t*/ fmeddupx, fmeddupy; + INT32 glstate; #endif } viddef_t; -#define VIDWIDTH vid.width -#define VIDHEIGHT vid.height + +enum +{ + VID_GL_LIBRARY_NOTLOADED = 0, + VID_GL_LIBRARY_LOADED = 1, + VID_GL_LIBRARY_ERROR = -1, +}; // internal additional info for vesa modes only typedef struct @@ -171,10 +177,10 @@ extern boolean R_SSE2; extern viddef_t vid; extern INT32 setmodeneeded; // mode number to set if needed, or 0 +extern UINT8 setrenderneeded; void SCR_ChangeRenderer(void); -void SCR_ChangeRendererCVars(INT32 mode); -extern UINT8 setrenderneeded; +void SCR_SetTargetRenderer(void); extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders @@ -188,17 +194,23 @@ extern consvar_t cv_newrenderer; // wait for page flipping to end or not extern consvar_t cv_vidwait; +// Initialize the screen +void SCR_Startup(void); + // Change video mode, only at the start of a refresh. void SCR_SetMode(void); + +// Set drawer functions for Software void SCR_SetDrawFuncs(void); + // Recalc screen size dependent stuff void SCR_Recalc(void); + // Check parms once at startup void SCR_CheckDefaultMode(void); -// Set the mode number which is saved in the config -void SCR_SetDefaultMode (void); -void SCR_Startup (void); +// Set the mode number which is saved in the config +void SCR_SetDefaultMode(void); FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 1bb48e468..3e31e4450 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -95,7 +95,7 @@ static INT32 numVidModes = -1; static char vidModeName[33][32]; // allow 33 different modes rendermode_t rendermode = render_soft; -static rendermode_t chosenrendermode = render_soft; // set by command line arguments +rendermode_t chosenrendermode = render_none; // set by command line arguments boolean highcolor = false; @@ -105,7 +105,6 @@ static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff static consvar_t cv_alwaysgrabmouse = {"alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; UINT8 graphics_started = 0; // Is used in console.c and screen.c -INT32 vid_opengl_state = 0; // To disable fullscreen at startup; is set in VID_PrepareModeList boolean allow_fullscreen = false; @@ -1443,7 +1442,8 @@ static SDL_bool Impl_CreateContext(void) { // Renderer-specific stuff #ifdef HWRENDER - if ((rendermode == render_opengl) && (vid_opengl_state != -1)) + if ((rendermode == render_opengl) + && (vid.glstate != VID_GL_LIBRARY_ERROR)) { if (!sdlglcontext) sdlglcontext = SDL_GL_CreateContext(window); @@ -1479,30 +1479,29 @@ static SDL_bool Impl_CreateContext(void) void VID_CheckGLLoaded(rendermode_t oldrender) { #ifdef HWRENDER - if (vid_opengl_state == -1) // Well, it didn't work the first time anyway. + if (vid.glstate == VID_GL_LIBRARY_ERROR) // Well, it didn't work the first time anyway. { CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); rendermode = oldrender; if (chosenrendermode == render_opengl) // fallback to software rendermode = render_soft; - if (setrenderneeded) - { - CV_StealthSetValue(&cv_renderer, oldrender); - CV_StealthSetValue(&cv_newrenderer, oldrender); - setrenderneeded = 0; - } + + CV_StealthSetValue(&cv_renderer, oldrender); + CV_StealthSetValue(&cv_newrenderer, oldrender); } #endif } -void VID_CheckRenderer(void) +boolean VID_CheckRenderer(void) { boolean rendererchanged = false; boolean contextcreated = false; +#ifdef HWRENDER rendermode_t oldrenderer = rendermode; +#endif if (dedicated) - return; + return false; if (setrenderneeded) { @@ -1516,11 +1515,12 @@ void VID_CheckRenderer(void) // Initialise OpenGL before calling SDLSetMode!!! // This is because SDLSetMode calls OglSdlSurface. - if (vid_opengl_state == 0) + if (vid.glstate == VID_GL_LIBRARY_NOTLOADED) { VID_StartupOpenGL(); + // Loaded successfully! - if (vid_opengl_state == 1) + if (vid.glstate == VID_GL_LIBRARY_LOADED) { // Destroy the current window, if it exists. if (window) @@ -1543,7 +1543,7 @@ void VID_CheckRenderer(void) contextcreated = true; } } - else if (vid_opengl_state == -1) + else if (vid.glstate == VID_GL_LIBRARY_ERROR) rendererchanged = false; } #endif @@ -1565,27 +1565,22 @@ void VID_CheckRenderer(void) bufSurface = NULL; } - if (rendererchanged) - { #ifdef HWRENDER - if (vid_opengl_state == 1) // Only if OpenGL ever loaded! - HWR_FreeTextureCache(); + if (rendererchanged && vid.glstate == VID_GL_LIBRARY_LOADED) // Only if OpenGL ever loaded! + HWR_ClearAllTextures(); #endif - SCR_SetDrawFuncs(); - } + + SCR_SetDrawFuncs(); } #ifdef HWRENDER - else if (rendermode == render_opengl) + else if (rendermode == render_opengl && rendererchanged) { - if (rendererchanged) - { - R_InitHardwareMode(); - V_SetPalette(0); - } + HWR_Switch(); + V_SetPalette(0); } -#else - (void)oldrenderer; #endif + + return rendererchanged; } INT32 VID_SetMode(INT32 modeNum) @@ -1626,7 +1621,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) flags |= SDL_WINDOW_BORDERLESS; #ifdef HWRENDER - if (vid_opengl_state == 1) + if (vid.glstate == VID_GL_LIBRARY_LOADED) flags |= SDL_WINDOW_OPENGL; #endif @@ -1747,12 +1742,44 @@ void I_StartupGraphics(void) framebuffer = SDL_TRUE; } -#ifdef HWRENDER - if (M_CheckParm("-opengl")) - chosenrendermode = rendermode = render_opengl; + // Renderer choices + // Takes priority over the config. + if (M_CheckParm("-renderer")) + { + INT32 i = 0; + CV_PossibleValue_t *renderer_list = cv_renderer_t; + const char *modeparm = M_GetNextParm(); + while (renderer_list[i].strvalue) + { + if (!stricmp(modeparm, renderer_list[i].strvalue)) + { + chosenrendermode = renderer_list[i].value; + break; + } + i++; + } + } + + // Choose Software renderer else if (M_CheckParm("-software")) + chosenrendermode = render_soft; + +#ifdef HWRENDER + // Choose OpenGL renderer + else if (M_CheckParm("-opengl")) + chosenrendermode = render_opengl; + + // Don't startup OpenGL + if (M_CheckParm("-nogl")) + { + vid.glstate = VID_GL_LIBRARY_ERROR; + if (chosenrendermode == render_opengl) + chosenrendermode = render_none; + } #endif - chosenrendermode = rendermode = render_soft; + + if (chosenrendermode != render_none) + rendermode = chosenrendermode; usesdl2soft = M_CheckParm("-softblit"); borderlesswindow = M_CheckParm("-borderless"); @@ -1761,9 +1788,7 @@ void I_StartupGraphics(void) VID_Command_ModeList_f(); #ifdef HWRENDER - if (M_CheckParm("-nogl")) - vid_opengl_state = -1; // Don't startup OpenGL - else if (chosenrendermode == render_opengl) + if (rendermode == render_opengl) VID_StartupOpenGL(); #endif @@ -1865,9 +1890,9 @@ void VID_StartupOpenGL(void) HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); HWD.pfnInitCustomShaders= hwSym("InitCustomShaders",NULL); - vid_opengl_state = HWD.pfnInit() ? 1 : -1; // let load the OpenGL library + vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library - if (vid_opengl_state == -1) + if (vid.glstate == VID_GL_LIBRARY_ERROR) { rendermode = render_soft; setrenderneeded = 0; diff --git a/src/v_video.c b/src/v_video.c index 7f07852fa..89ffea6cf 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -3719,3 +3719,36 @@ void V_Init(void) CONS_Debug(DBG_RENDER, " screens[%d] = %x\n", i, screens[i]); #endif } + +void V_Recalc(void) +{ + // scale 1,2,3 times in x and y the patches for the menus and overlays... + // calculated once and for all, used by routines in v_video.c and v_draw.c + vid.dupx = vid.width / BASEVIDWIDTH; + vid.dupy = vid.height / BASEVIDHEIGHT; + vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); + vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); + +#ifdef HWRENDER + //if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl + // 13/11/18: + // The above is no longer necessary, since we want OpenGL to be just like software now + // -- Monster Iestyn +#endif + vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); + + vid.meddupx = (UINT8)(vid.dupx >> 1) + 1; + vid.meddupy = (UINT8)(vid.dupy >> 1) + 1; +#ifdef HWRENDER + vid.fmeddupx = vid.meddupx*FRACUNIT; + vid.fmeddupy = vid.meddupy*FRACUNIT; +#endif + + vid.smalldupx = (UINT8)(vid.dupx / 3) + 1; + vid.smalldupy = (UINT8)(vid.dupy / 3) + 1; +#ifdef HWRENDER + vid.fsmalldupx = vid.smalldupx*FRACUNIT; + vid.fsmalldupy = vid.smalldupy*FRACUNIT; +#endif +} diff --git a/src/v_video.h b/src/v_video.h index 9f7a9a9e9..96bc7db89 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -37,6 +37,9 @@ cv_allcaps; // Allocates buffer screens, call before R_Init. void V_Init(void); +// Recalculates the viddef (dupx, dupy, etc.) according to the current screen resolution. +void V_Recalc(void); + // Color look-up table #define COLORBITS 6 #define SHIFTCOLORBITS (8-COLORBITS) diff --git a/src/w_wad.c b/src/w_wad.c index f40f4eb4a..0d329302a 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -845,7 +845,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) #ifdef HWRENDER // Read shaders from file - if (rendermode == render_opengl && (vid_opengl_state == 1)) + if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) { HWR_ReadShaders(numwadfiles - 1, (type == RET_PK3)); HWR_LoadShaders(); diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index 716f38089..6a74a08d2 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -48,6 +48,7 @@ // this is the CURRENT rendermode!! very important: used by w_wad, and much other code rendermode_t rendermode = render_soft; +rendermode_t chosenrendermode = render_none; // set by command line arguments static void OnTop_OnChange(void); // synchronize page flipping with screen refresh static CV_PossibleValue_t CV_NeverOnOff[] = {{-1, "Never"}, {0, "Off"}, {1, "On"}, {0, NULL}}; @@ -56,7 +57,6 @@ static consvar_t cv_stretch = {"stretch", "On", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, static consvar_t cv_ontop = {"ontop", "Never", 0, CV_NeverOnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; boolean highcolor; -int vid_opengl_state = 0; static BOOL bDIBMode; // means we are using DIB instead of DirectDraw surfaces static LPBITMAPINFO bmiMain = NULL; @@ -952,7 +952,11 @@ INT32 VID_SetMode(INT32 modenum) return 1; } -void VID_CheckRenderer(void) {} +boolean VID_CheckRenderer(void) +{ + return false; +} + void VID_CheckGLLoaded(rendermode_t oldrender) { (void)oldrender; From 901adcf3da3258899004668f8f7db11c8459cf54 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 15 Aug 2020 20:14:36 -0300 Subject: [PATCH 05/81] Rename R_CheckIfPatch --- src/p_setup.c | 2 +- src/r_patch.c | 18 ++++++------------ src/r_patch.h | 3 ++- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 0105a06da..8d7904bb0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -603,7 +603,7 @@ texturefound: { flatfound: /* This could be a flat, patch, or PNG. */ - if (R_CheckIfPatch(flatnum)) + if (Patch_CheckIfDoom((patch_t *)W_CacheLumpNum(flatnum, PU_STATIC), W_LumpLength(flatnum))) levelflat->type = LEVELFLAT_PATCH; else { diff --git a/src/r_patch.c b/src/r_patch.c index 783c1fbec..9a5364f9a 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -143,29 +143,23 @@ void *Patch_CreateGL(patch_t *patch) #endif // HWRENDER // -// R_CheckIfPatch +// Patch_CheckIfDoom // -// Returns true if the lump is a valid patch. +// Returns true if the lump is a valid Doom patch. // -boolean R_CheckIfPatch(lumpnum_t lump) +boolean Patch_CheckIfDoom(softwarepatch_t *patch, size_t length) { - 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) + if (length < 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)); + result = (height > 0 && height <= 16384 && width > 0 && width <= 16384 && width < (INT16)(length / 4)); if (result) { @@ -180,7 +174,7 @@ boolean R_CheckIfPatch(lumpnum_t lump) 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) + if (ofs < (UINT32)width * 4 + 8 || ofs >= (UINT32)length) { result = false; break; diff --git a/src/r_patch.h b/src/r_patch.h index de4981fba..9fe5fde72 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -46,8 +46,9 @@ void *Patch_AllocateHardwarePatch(patch_t *patch); void *Patch_CreateGL(patch_t *patch); #endif +boolean Patch_CheckIfDoom(softwarepatch_t *patch, size_t length); + // Conversions between patches / flats / textures... -boolean R_CheckIfPatch(lumpnum_t lump); void R_TextureToFlat(size_t tex, UINT8 *flat); void R_PatchToFlat(patch_t *patch, UINT8 *flat); void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip); From d18d12fdeaf5a2fdaa67125e6c6ce25667d8ec45 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 15 Aug 2020 21:52:01 -0300 Subject: [PATCH 06/81] Introduce Doom patch format into picture formats Fixes sprite rotation --- src/hardware/hw_cache.c | 4 +- src/p_setup.c | 4 +- src/r_patch.c | 3 - src/r_picformats.c | 155 +++++++++++++++++++++++++++------------- src/r_picformats.h | 10 ++- src/r_textures.c | 6 +- src/r_things.c | 2 +- src/w_wad.c | 2 +- 8 files changed, 122 insertions(+), 64 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 138301d01..631aa056b 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -516,13 +516,13 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) { // Dummy variables. INT32 pngwidth, pngheight; - realpatch = (softwarepatch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, &pngwidth, &pngheight, NULL, NULL, lumplength, NULL, 0); + realpatch = (softwarepatch_t *)Picture_PNGConvert(pdata, PICFMT_DOOMPATCH, &pngwidth, &pngheight, NULL, NULL, lumplength, NULL, 0); } else #endif #ifdef WALLFLATS if (texture->type == TEXTURETYPE_FLAT) - realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); + realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_DOOMPATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); else #endif { diff --git a/src/p_setup.c b/src/p_setup.c index 5e0b0304b..78f78f0c8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -549,7 +549,7 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize) lumpnum_t flatnum; int texturenum; - patch_t *flatpatch; + UINT8 *flatpatch; size_t lumplength; size_t i; @@ -609,7 +609,7 @@ flatfound: /* This could be a flat, patch, or PNG. */ flatpatch = W_CacheLumpNum(flatnum, PU_CACHE); lumplength = W_LumpLength(flatnum); - if (Picture_CheckIfPatch(flatpatch, lumplength)) + if (Picture_CheckIfDoomPatch((softwarepatch_t *)flatpatch, lumplength)) levelflat->type = LEVELFLAT_PATCH; else { diff --git a/src/r_patch.c b/src/r_patch.c index e70d0cb7c..281523fd2 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -57,9 +57,6 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest) M_Memcpy(patch->columns, ((UINT8 *)source + LONG(source->columnofs[0])), colsize); } - if (patch->hardware) - I_Error("wtf?\n"); - return patch; } diff --git a/src/r_picformats.c b/src/r_picformats.c index e351466c9..d42d36a00 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -118,7 +118,7 @@ void *Picture_PatchConvert( UINT8 *imgptr = imgbuf; UINT8 *colpointers, *startofspan; size_t size = 0; - softwarepatch_t *inpatch = NULL; + patch_t *inpatch = NULL; INT32 inbpp = Picture_FormatBPP(informat); (void)insize; // ignore @@ -140,10 +140,21 @@ void *Picture_PatchConvert( if (Picture_IsPatchFormat(informat)) { inpatch = (patch_t *)picture; - inwidth = SHORT(inpatch->width); - inheight = SHORT(inpatch->height); - inleftoffset = SHORT(inpatch->leftoffset); - intopoffset = SHORT(inpatch->topoffset); + if (Picture_IsDoomPatchFormat(informat)) + { + softwarepatch_t *doompatch = (softwarepatch_t *)picture; + inwidth = SHORT(doompatch->width); + inheight = SHORT(doompatch->height); + inleftoffset = SHORT(doompatch->leftoffset); + intopoffset = SHORT(doompatch->topoffset); + } + else + { + inwidth = inpatch->width; + inheight = inpatch->height; + inleftoffset = inpatch->leftoffset; + intopoffset = inpatch->topoffset; + } } // Write image size and offset @@ -273,6 +284,7 @@ void *Picture_PatchConvert( switch (outformat) { case PICFMT_PATCH32: + case PICFMT_DOOMPATCH32: { if (inbpp == PICDEPTH_32BPP) { @@ -292,6 +304,7 @@ void *Picture_PatchConvert( break; } case PICFMT_PATCH16: + case PICFMT_DOOMPATCH16: if (inbpp == PICDEPTH_32BPP) { RGBA_t in = *(RGBA_t *)input; @@ -338,7 +351,18 @@ void *Picture_PatchConvert( if (outsize != NULL) *outsize = size; - return img; + + if (Picture_IsInternalPatchFormat(outformat)) + { + patch_t *converted = Patch_Create((softwarepatch_t *)img, size, NULL); +#ifdef HWRENDER + Patch_CreateGL(converted); +#endif + Z_Free(img); + return converted; + } + else + return img; } /** Converts a picture to a flat. @@ -389,8 +413,17 @@ void *Picture_FlatConvert( if (Picture_IsPatchFormat(informat)) { inpatch = (patch_t *)picture; - inwidth = SHORT(inpatch->width); - inheight = SHORT(inpatch->height); + if (Picture_IsDoomPatchFormat(informat)) + { + softwarepatch_t *doompatch = ((softwarepatch_t *)picture); + inwidth = SHORT(doompatch->width); + inheight = SHORT(doompatch->height); + } + else + { + inwidth = inpatch->width; + inheight = inpatch->height; + } } size = (inwidth * inheight) * (outbpp / 8); @@ -501,22 +534,25 @@ void *Picture_GetPatchPixel( UINT8 *s8 = NULL; UINT16 *s16 = NULL; UINT32 *s32 = NULL; + softwarepatch_t *doompatch = (softwarepatch_t *)patch; + INT16 width; if (patch == NULL) I_Error("Picture_GetPatchPixel: patch == NULL"); - if (x >= 0 && x < SHORT(patch->width)) - { - INT32 topdelta, prevdelta = -1; - INT32 colofs = 0; + width = (Picture_IsDoomPatchFormat(informat) ? patch->width : SHORT(patch->width)); - if (flags & PICFLAGS_XFLIP) - colofs = LONG(patch->columnofs[(SHORT(patch->width)-1)-x]); - else - colofs = LONG(patch->columnofs[x]); + if (x >= 0 && x < width) + { + INT32 colx = (flags & PICFLAGS_XFLIP) ? (width-1)-x : x; + INT32 topdelta, prevdelta = -1; + INT32 colofs = (Picture_IsDoomPatchFormat(informat) ? LONG(patch->columnofs[colx]) : patch->columnofs[colx]); // Column offsets are pointers so no casting required - column = (column_t *)((UINT8 *)patch + colofs); + if (Picture_IsDoomPatchFormat(informat)) + column = (column_t *)((UINT8 *)doompatch + colofs); + else + column = (column_t *)((UINT8 *)patch->columns + colofs); while (column->topdelta != 0xff) { @@ -525,25 +561,25 @@ void *Picture_GetPatchPixel( topdelta += prevdelta; prevdelta = topdelta; s8 = (UINT8 *)(column) + 3; - if (informat == PICFMT_PATCH32) + if (Picture_FormatBPP(informat) == PICDEPTH_32BPP) s32 = (UINT32 *)s8; - else if (informat == PICFMT_PATCH16) + else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP) s16 = (UINT16 *)s8; for (ofs = 0; ofs < column->length; ofs++) { if ((topdelta + ofs) == y) { - if (informat == PICFMT_PATCH32) + if (Picture_FormatBPP(informat) == PICDEPTH_32BPP) return &s32[ofs]; - else if (informat == PICFMT_PATCH16) + else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP) return &s16[ofs]; - else // PICFMT_PATCH + else // PICDEPTH_8BPP return &s8[ofs]; } } - if (informat == PICFMT_PATCH32) + if (Picture_FormatBPP(informat) == PICDEPTH_32BPP) column = (column_t *)((UINT32 *)column + column->length); - else if (informat == PICFMT_PATCH16) + else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP) column = (column_t *)((UINT16 *)column + column->length); else column = (column_t *)((UINT8 *)column + column->length); @@ -566,15 +602,18 @@ INT32 Picture_FormatBPP(pictureformat_t format) { case PICFMT_PATCH32: case PICFMT_FLAT32: + case PICFMT_DOOMPATCH32: case PICFMT_PNG: bpp = PICDEPTH_32BPP; break; case PICFMT_PATCH16: case PICFMT_FLAT16: + case PICFMT_DOOMPATCH16: bpp = PICDEPTH_16BPP; break; case PICFMT_PATCH: case PICFMT_FLAT: + case PICFMT_DOOMPATCH: bpp = PICDEPTH_8BPP; break; default: @@ -590,7 +629,43 @@ INT32 Picture_FormatBPP(pictureformat_t format) */ boolean Picture_IsPatchFormat(pictureformat_t format) { - return (format == PICFMT_PATCH || format == PICFMT_PATCH16 || format == PICFMT_PATCH32); + return (Picture_IsInternalPatchFormat(format) || Picture_IsDoomPatchFormat(format)); +} + +/** Checks if the specified picture format is an internal patch. + * + * \param format Input picture format. + * \return True if the picture format is an internal patch, false if not. + */ +boolean Picture_IsInternalPatchFormat(pictureformat_t format) +{ + switch (format) + { + case PICFMT_PATCH: + case PICFMT_PATCH16: + case PICFMT_PATCH32: + return true; + default: + return false; + } +} + +/** Checks if the specified picture format is a Doom patch. + * + * \param format Input picture format. + * \return True if the picture format is a Doom patch, false if not. + */ +boolean Picture_IsDoomPatchFormat(pictureformat_t format) +{ + switch (format) + { + case PICFMT_DOOMPATCH: + case PICFMT_DOOMPATCH16: + case PICFMT_DOOMPATCH32: + return true; + default: + return false; + } } /** Checks if the specified picture format is a flat. @@ -604,13 +679,13 @@ boolean Picture_IsFlatFormat(pictureformat_t format) } /** Returns true if the lump is a valid Doom patch. - * PICFMT_PATCH only, I think?? + * PICFMT_DOOMPATCH only. * * \param patch Input patch. * \param picture Input patch size. * \return True if the input patch is valid. */ -boolean Picture_CheckIfPatch(softwarepatch_t *patch, size_t size) +boolean Picture_CheckIfDoomPatch(softwarepatch_t *patch, size_t size) { INT16 width, height; boolean result; @@ -1461,7 +1536,6 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp { INT32 angle; patch_t *patch, *newpatch; - softwarepatch_t *swpatch; UINT16 *rawdst; size_t size; pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0; @@ -1598,32 +1672,19 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp } // make patch - swpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0); + newpatch = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0); { - swpatch->leftoffset = (swpatch->width / 2) + (leftoffset - px); - swpatch->topoffset = (swpatch->height / 2) + (patch->topoffset - py); + newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px); + newpatch->topoffset = (newpatch->height / 2) + (patch->topoffset - py); } //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer if (rendermode != render_none) // not for psprite - swpatch->topoffset += FEETADJUST>>FRACBITS; + newpatch->topoffset += FEETADJUST>>FRACBITS; // P_PrecacheLevel if (devparm) spritememory += size; - // convert everything to little-endian, for big-endian support - swpatch->width = SHORT(swpatch->width); - swpatch->height = SHORT(swpatch->height); - swpatch->leftoffset = SHORT(swpatch->leftoffset); - swpatch->topoffset = SHORT(swpatch->topoffset); - - newpatch = Patch_Create(swpatch, size, NULL); - -#ifdef HWRENDER - if (rendermode == render_opengl) - Patch_CreateGL(newpatch); -#endif - sprframe->rotsprite.patch[rot][angle] = newpatch; // free rotated image data @@ -1632,10 +1693,6 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp // This rotation is cached now sprframe->rotsprite.cached |= (1<type == TEXTURETYPE_FLAT) - realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); + realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_DOOMPATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); else #endif { @@ -608,7 +608,7 @@ void *R_GetLevelFlat(levelflat_t *levelflat) levelflat->height = ds_flatheight = SHORT(patch->height); levelflat->picture = Z_Malloc(levelflat->width * levelflat->height, PU_LEVEL, NULL); - converted = Picture_FlatConvert(PICFMT_PATCH, patch, PICFMT_FLAT, 0, &size, levelflat->width, levelflat->height, patch->topoffset, patch->leftoffset, 0); + converted = Picture_FlatConvert(PICFMT_DOOMPATCH, patch, PICFMT_FLAT, 0, &size, levelflat->width, levelflat->height, patch->topoffset, patch->leftoffset, 0); M_Memcpy(levelflat->picture, converted, size); Z_Free(converted); } diff --git a/src/r_things.c b/src/r_things.c index 9b32a6d5f..8bbf21b54 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -286,7 +286,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 // Dummy variables. INT32 pngwidth, pngheight; INT16 topoffset, leftoffset; - patch_t *converted = (patch_t *)Picture_PNGConvert((UINT8 *)png, PICFMT_PATCH, &pngwidth, &pngheight, &topoffset, &leftoffset, len, NULL, 0); + patch_t *converted = (patch_t *)Picture_PNGConvert((UINT8 *)png, PICFMT_DOOMPATCH, &pngwidth, &pngheight, &topoffset, &leftoffset, len, NULL, 0); M_Memcpy(&patch, converted, sizeof(INT16)*4); // only copy the header because that's all we need Z_Free(converted); } diff --git a/src/w_wad.c b/src/w_wad.c index 21004e6e8..1a1e08da9 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1684,7 +1684,7 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { size_t newlen; INT32 pngwidth, pngheight; // Dummy variables. - void *converted = Picture_PNGConvert((UINT8 *)lumpdata, PICFMT_PATCH, &pngwidth, &pngheight, NULL, NULL, len, &newlen, 0); + void *converted = Picture_PNGConvert((UINT8 *)lumpdata, PICFMT_DOOMPATCH, &pngwidth, &pngheight, NULL, NULL, len, &newlen, 0); ptr = Z_Malloc(newlen, PU_STATIC, NULL); M_Memcpy(ptr, converted, newlen); Z_Free(converted); From 98c6b54994e12182d5bdaf734369a5c0b22c8de2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 7 Sep 2020 02:23:07 -0300 Subject: [PATCH 07/81] Improved memory management for patches --- src/dehacked.c | 8 -- src/f_finale.c | 294 ++++++++++++++++++++--------------------- src/hardware/hw_main.c | 12 +- src/lua_hudlib.c | 12 +- src/lua_infolib.c | 9 -- src/m_menu.c | 7 +- src/p_setup.c | 4 + src/r_data.c | 2 +- src/r_defs.h | 1 - src/r_patch.c | 22 ++- src/r_patch.h | 3 + src/r_picformats.c | 256 ++++++++++++++--------------------- src/r_picformats.h | 4 +- src/r_things.c | 17 +-- src/st_stuff.c | 8 +- src/y_inter.c | 7 +- src/z_zone.c | 32 +++++ src/z_zone.h | 14 +- 18 files changed, 344 insertions(+), 368 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 613c683f3..bb5e811ff 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1046,11 +1046,6 @@ static void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) spriteinfo_t *info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); info->available = true; -#ifdef ROTSPRITE - if ((sprites != NULL) && (!sprite2)) - R_FreeRotSprite(&sprites[num]); -#endif - do { lastline = f->curpos; @@ -1179,9 +1174,6 @@ static void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) size_t skinnum = skinnumbers[i]; skin_t *skin = &skins[skinnum]; spriteinfo_t *sprinfo = skin->sprinfo; -#ifdef ROTSPRITE - R_FreeSkinRotSprite(skinnum); -#endif M_Memcpy(&sprinfo[num], info, sizeof(spriteinfo_t)); } } diff --git a/src/f_finale.c b/src/f_finale.c index 7cc5467c2..2a5e0b3c6 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -528,78 +528,78 @@ static void F_IntroDrawScene(void) case 0: break; case 1: - background = W_CachePatchName("INTRO1", PU_PATCH); + background = W_CachePatchName("INTRO1", PU_PATCH_LOWPRIORITY); break; case 2: - background = W_CachePatchName("INTRO2", PU_PATCH); + background = W_CachePatchName("INTRO2", PU_PATCH_LOWPRIORITY); break; case 3: - background = W_CachePatchName("INTRO3", PU_PATCH); + background = W_CachePatchName("INTRO3", PU_PATCH_LOWPRIORITY); break; case 4: - background = W_CachePatchName("INTRO4", PU_PATCH); + background = W_CachePatchName("INTRO4", PU_PATCH_LOWPRIORITY); break; case 5: if (intro_curtime >= 5*TICRATE) - background = W_CachePatchName("RADAR", PU_PATCH); + background = W_CachePatchName("RADAR", PU_PATCH_LOWPRIORITY); else - background = W_CachePatchName("DRAT", PU_PATCH); + background = W_CachePatchName("DRAT", PU_PATCH_LOWPRIORITY); break; case 6: - background = W_CachePatchName("INTRO6", PU_PATCH); + background = W_CachePatchName("INTRO6", PU_PATCH_LOWPRIORITY); cx = 180; cy = 8; break; case 7: { if (intro_curtime >= 7*TICRATE + ((TICRATE/7)*2)) - background = W_CachePatchName("SGRASS5", PU_PATCH); + background = W_CachePatchName("SGRASS5", PU_PATCH_LOWPRIORITY); else if (intro_curtime >= 7*TICRATE + (TICRATE/7)) - background = W_CachePatchName("SGRASS4", PU_PATCH); + background = W_CachePatchName("SGRASS4", PU_PATCH_LOWPRIORITY); else if (intro_curtime >= 7*TICRATE) - background = W_CachePatchName("SGRASS3", PU_PATCH); + background = W_CachePatchName("SGRASS3", PU_PATCH_LOWPRIORITY); else if (intro_curtime >= 6*TICRATE) - background = W_CachePatchName("SGRASS2", PU_PATCH); + background = W_CachePatchName("SGRASS2", PU_PATCH_LOWPRIORITY); else - background = W_CachePatchName("SGRASS1", PU_PATCH); + background = W_CachePatchName("SGRASS1", PU_PATCH_LOWPRIORITY); break; } case 8: - background = W_CachePatchName("WATCHING", PU_PATCH); + background = W_CachePatchName("WATCHING", PU_PATCH_LOWPRIORITY); break; case 9: - background = W_CachePatchName("ZOOMING", PU_PATCH); + background = W_CachePatchName("ZOOMING", PU_PATCH_LOWPRIORITY); break; case 10: break; case 11: - background = W_CachePatchName("INTRO5", PU_PATCH); + background = W_CachePatchName("INTRO5", PU_PATCH_LOWPRIORITY); break; case 12: - background = W_CachePatchName("REVENGE", PU_PATCH); + background = W_CachePatchName("REVENGE", PU_PATCH_LOWPRIORITY); cx = 208; cy = 8; break; case 13: - background = W_CachePatchName("CONFRONT", PU_PATCH); + background = W_CachePatchName("CONFRONT", PU_PATCH_LOWPRIORITY); cy += 48; break; case 14: - background = W_CachePatchName("TAILSSAD", PU_PATCH); + background = W_CachePatchName("TAILSSAD", PU_PATCH_LOWPRIORITY); bgxoffs = 144; cx = 8; cy = 8; break; case 15: if (intro_curtime >= 7*TICRATE) - background = W_CachePatchName("SONICDO2", PU_PATCH); + background = W_CachePatchName("SONICDO2", PU_PATCH_LOWPRIORITY); else - background = W_CachePatchName("SONICDO1", PU_PATCH); + background = W_CachePatchName("SONICDO1", PU_PATCH_LOWPRIORITY); cx = 224; cy = 8; break; case 16: - background = W_CachePatchName("INTRO7", PU_PATCH); + background = W_CachePatchName("INTRO7", PU_PATCH_LOWPRIORITY); break; default: break; @@ -629,30 +629,30 @@ static void F_IntroDrawScene(void) S_ChangeMusicInternal("_stjr", false); x = (BASEVIDWIDTH< 6) { - V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH2", PU_PATCH)), aspect); + V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH2", PU_PATCH_LOWPRIORITY)), aspect); W_UnlockCachedPatch(patch); } if (finalecount > 10) { - V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH3", PU_PATCH)), aspect); + V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH3", PU_PATCH_LOWPRIORITY)), aspect); W_UnlockCachedPatch(patch); } if (finalecount > 14) { - V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH4", PU_PATCH)), aspect); + V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH4", PU_PATCH_LOWPRIORITY)), aspect); W_UnlockCachedPatch(patch); } } else if (finalecount-30 < 20) { // Big eggy - background = W_CachePatchName("FEEDIN", PU_PATCH); + background = W_CachePatchName("FEEDIN", PU_PATCH_LOWPRIORITY); x = (BASEVIDWIDTH< 4*TICRATE) { // Door is being raised! int ftime = (finalecount-TICRATE/2-4*TICRATE); y -= FixedDiv((ftime*ftime)< 5*TICRATE && timetonext < 6*TICRATE) { if (!(finalecount & 3)) - background = W_CachePatchName("BRITEGG1", PU_PATCH); + background = W_CachePatchName("BRITEGG1", PU_PATCH_LOWPRIORITY); else - background = W_CachePatchName("DARKEGG1", PU_PATCH); + background = W_CachePatchName("DARKEGG1", PU_PATCH_LOWPRIORITY); V_DrawSmallScaledPatch(0, 0, 0, background); } else if (timetonext > 3*TICRATE && timetonext < 4*TICRATE) { if (!(finalecount & 3)) - background = W_CachePatchName("BRITEGG2", PU_PATCH); + background = W_CachePatchName("BRITEGG2", PU_PATCH_LOWPRIORITY); else - background = W_CachePatchName("DARKEGG2", PU_PATCH); + background = W_CachePatchName("DARKEGG2", PU_PATCH_LOWPRIORITY); V_DrawSmallScaledPatch(0, 0, 0, background); } else if (timetonext > 1*TICRATE && timetonext < 2*TICRATE) { if (!(finalecount & 3)) - background = W_CachePatchName("BRITEGG3", PU_PATCH); + background = W_CachePatchName("BRITEGG3", PU_PATCH_LOWPRIORITY); else - background = W_CachePatchName("DARKEGG3", PU_PATCH); + background = W_CachePatchName("DARKEGG3", PU_PATCH_LOWPRIORITY); V_DrawSmallScaledPatch(0, 0, 0, background); } @@ -766,79 +766,79 @@ static void F_IntroDrawScene(void) knucklesx += sonicx; sonicx += P_ReturnThrustX(NULL, finalecount * ANG10, 3); - V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_PATCH))); + V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_PATCH_LOWPRIORITY))); V_DrawSmallScaledPatch(skyx - 320, 0, 0, patch); W_UnlockCachedPatch(patch); - V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_PATCH))); + V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_PATCH_LOWPRIORITY))); V_DrawSmallScaledPatch(grassx - 320, 0, 0, patch); W_UnlockCachedPatch(patch); if (finalecount & 1) { // Sonic - V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_PATCH))); + V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); // Appendages if (finalecount & 2) { // Sonic's feet - V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_PATCH))); + V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); // Tails' tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); } else { // Sonic's feet - V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_PATCH))); + V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); // Tails' tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); } // Tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_PATCH))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); // Knuckles - V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_PATCH))); + V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); } else { // Sonic - V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_PATCH))); + V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); // Appendages if (finalecount & 2) { // Sonic's feet - V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_PATCH))); + V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); // Tails' tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); } else { // Sonic's feet - V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_PATCH))); + V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); // Tails' tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); } // Tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_PATCH))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); // Knuckles - V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_PATCH))); + V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_PATCH_LOWPRIORITY))); W_UnlockCachedPatch(patch); } @@ -871,8 +871,8 @@ static void F_IntroDrawScene(void) y += (30*(FRACUNIT-scale)); } - rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_PATCH); - glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_PATCH); + rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_PATCH_LOWPRIORITY); + glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_PATCH_LOWPRIORITY); if (worktics >= 5) trans = (worktics-5)>>1; @@ -986,7 +986,7 @@ void F_IntroDrawer(void) { if (intro_scenenum == 5 && intro_curtime == 5*TICRATE) { - patch_t *radar = W_CachePatchName("RADAR", PU_PATCH); + patch_t *radar = W_CachePatchName("RADAR", PU_PATCH_LOWPRIORITY); F_WipeStartScreen(); F_WipeColorFill(31); @@ -999,7 +999,7 @@ void F_IntroDrawer(void) } else if (intro_scenenum == 7 && intro_curtime == 6*TICRATE) // Force a wipe here { - patch_t *grass = W_CachePatchName("SGRASS2", PU_PATCH); + patch_t *grass = W_CachePatchName("SGRASS2", PU_PATCH_LOWPRIORITY); F_WipeStartScreen(); F_WipeColorFill(31); @@ -1012,7 +1012,7 @@ void F_IntroDrawer(void) } /*else if (intro_scenenum == 12 && intro_curtime == 7*TICRATE) { - patch_t *confront = W_CachePatchName("CONFRONT", PU_PATCH); + patch_t *confront = W_CachePatchName("CONFRONT", PU_PATCH_LOWPRIORITY); F_WipeStartScreen(); F_WipeColorFill(31); @@ -1025,7 +1025,7 @@ void F_IntroDrawer(void) }*/ if (intro_scenenum == 15 && intro_curtime == 7*TICRATE) { - patch_t *sdo = W_CachePatchName("SONICDO2", PU_PATCH); + patch_t *sdo = W_CachePatchName("SONICDO2", PU_PATCH_LOWPRIORITY); F_WipeStartScreen(); F_WipeColorFill(31); @@ -1361,14 +1361,14 @@ void F_CreditDrawer(void) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Zig Zagz - V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH)); - V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH)); - V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH)); - V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH)); + V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY)); + V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY)); + V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY)); + V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY)); // Draw background pictures first for (i = 0; credits_pics[i].patch; i++) - V_DrawSciencePatch(credits_pics[i].x<>1); + V_DrawSciencePatch(credits_pics[i].x<>1); // Dim the background V_DrawFadeScreen(0xFF00, 16); @@ -1577,14 +1577,14 @@ void F_GameEvaluationDrawer(void) if (goodending) { - rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH); - glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH); + rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH_LOWPRIORITY); + glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH_LOWPRIORITY); x -= FRACUNIT; } else { - rockpat = W_CachePatchName("ROID0000", PU_LEVEL); - glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH); + rockpat = W_CachePatchName("ROID0000", PU_PATCH_LOWPRIORITY); + glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH_LOWPRIORITY); } if (finalecount >= 5) @@ -1616,20 +1616,20 @@ void F_GameEvaluationDrawer(void) // if j == 0 - alternate between 0 and 1 // 1 - 1 and 2 // 2 - 2 and not rendered - V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE)); + V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH_LOWPRIORITY), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE)); } j--; } } else { - patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH); + patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH_LOWPRIORITY); V_DrawFixedPatch(x, y, scale, 0, eggrock, colormap[0]); if (trans < 10) V_DrawFixedPatch(x, y, scale, trans<spriteframes[XTRA_ENDING]; - endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY); sprframe = &sprdef->spriteframes[XTRA_ENDING+1]; - endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY); sprframe = &sprdef->spriteframes[XTRA_ENDING+2]; - endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY); } else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this) { - endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH); - endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH); - endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH); + endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH_LOWPRIORITY); + endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH_LOWPRIORITY); + endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH_LOWPRIORITY); } - endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH); + endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH_LOWPRIORITY); } else { // eggman, skin nonspecific - endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH); - endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH); - endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH); + endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH_LOWPRIORITY); + endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH_LOWPRIORITY); + endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH_LOWPRIORITY); - endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_LEVEL); + endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_PATCH_LOWPRIORITY); } } static void F_CacheGoodEnding(void) { - endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH); - endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH); + endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH_LOWPRIORITY); + endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH_LOWPRIORITY); - endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH); - endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH); + endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH_LOWPRIORITY); + endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH_LOWPRIORITY); - endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH); + endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH_LOWPRIORITY); } void F_StartEnding(void) @@ -1902,9 +1902,9 @@ void F_EndingDrawer(void) patch_t *rockpat; if (!goodending || finalecount < INFLECTIONPOINT) - rockpat = W_CachePatchName("ROID0000", PU_PATCH); + rockpat = W_CachePatchName("ROID0000", PU_PATCH_LOWPRIORITY); else - rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_PATCH); + rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_PATCH_LOWPRIORITY); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); @@ -2241,7 +2241,7 @@ void F_EndingDrawer(void) eemeralds_cur[0] += (360< 20) @@ -2388,11 +2388,11 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname) if (!scrollxspeed && !scrollyspeed) { - V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH)); + V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY)); return; } - pat = W_CachePatchName(patchname, PU_PATCH); + pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY); patwidth = SHORT(pat->width); patheight = SHORT(pat->height); @@ -2431,7 +2431,7 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname) lumpnum = W_CheckNumForName(name); \ if (lumpnum != LUMPERROR) \ { \ - arr[0] = W_CachePatchName(name, PU_LEVEL); \ + arr[0] = W_CachePatchName(name, PU_PATCH_LOWPRIORITY); \ arr[min(1, maxf-1)] = 0; \ } \ else if (strlen(name) <= 6) \ @@ -2444,7 +2444,7 @@ else if (strlen(name) <= 6) \ lumpname[8] = 0; \ lumpnum = W_CheckNumForName(lumpname); \ if (lumpnum != LUMPERROR) \ - arr[i] = W_CachePatchName(lumpname, PU_LEVEL); \ + arr[i] = W_CachePatchName(lumpname, PU_PATCH_LOWPRIORITY); \ else \ break; \ } \ @@ -2459,21 +2459,21 @@ static void F_CacheTitleScreen(void) { case TTMODE_OLD: case TTMODE_NONE: - ttbanner = W_CachePatchName("TTBANNER", PU_LEVEL); - ttwing = W_CachePatchName("TTWING", PU_LEVEL); - ttsonic = W_CachePatchName("TTSONIC", PU_LEVEL); - ttswave1 = W_CachePatchName("TTSWAVE1", PU_LEVEL); - ttswave2 = W_CachePatchName("TTSWAVE2", PU_LEVEL); - ttswip1 = W_CachePatchName("TTSWIP1", PU_LEVEL); - ttsprep1 = W_CachePatchName("TTSPREP1", PU_LEVEL); - ttsprep2 = W_CachePatchName("TTSPREP2", PU_LEVEL); - ttspop1 = W_CachePatchName("TTSPOP1", PU_LEVEL); - ttspop2 = W_CachePatchName("TTSPOP2", PU_LEVEL); - ttspop3 = W_CachePatchName("TTSPOP3", PU_LEVEL); - ttspop4 = W_CachePatchName("TTSPOP4", PU_LEVEL); - ttspop5 = W_CachePatchName("TTSPOP5", PU_LEVEL); - ttspop6 = W_CachePatchName("TTSPOP6", PU_LEVEL); - ttspop7 = W_CachePatchName("TTSPOP7", PU_LEVEL); + ttbanner = W_CachePatchName("TTBANNER", PU_PATCH_LOWPRIORITY); + ttwing = W_CachePatchName("TTWING", PU_PATCH_LOWPRIORITY); + ttsonic = W_CachePatchName("TTSONIC", PU_PATCH_LOWPRIORITY); + ttswave1 = W_CachePatchName("TTSWAVE1", PU_PATCH_LOWPRIORITY); + ttswave2 = W_CachePatchName("TTSWAVE2", PU_PATCH_LOWPRIORITY); + ttswip1 = W_CachePatchName("TTSWIP1", PU_PATCH_LOWPRIORITY); + ttsprep1 = W_CachePatchName("TTSPREP1", PU_PATCH_LOWPRIORITY); + ttsprep2 = W_CachePatchName("TTSPREP2", PU_PATCH_LOWPRIORITY); + ttspop1 = W_CachePatchName("TTSPOP1", PU_PATCH_LOWPRIORITY); + ttspop2 = W_CachePatchName("TTSPOP2", PU_PATCH_LOWPRIORITY); + ttspop3 = W_CachePatchName("TTSPOP3", PU_PATCH_LOWPRIORITY); + ttspop4 = W_CachePatchName("TTSPOP4", PU_PATCH_LOWPRIORITY); + ttspop5 = W_CachePatchName("TTSPOP5", PU_PATCH_LOWPRIORITY); + ttspop6 = W_CachePatchName("TTSPOP6", PU_PATCH_LOWPRIORITY); + ttspop7 = W_CachePatchName("TTSPOP7", PU_PATCH_LOWPRIORITY); break; // don't load alacroix gfx yet; we do that upon first draw. @@ -2593,7 +2593,7 @@ void F_StartTitleScreen(void) static void F_UnloadAlacroixGraphics(SINT8 oldttscale) { - // This all gets freed by PU_LEVEL when exiting the menus. + // This all gets freed by PU_PATCH_LOWPRIORITY when exiting the menus. // When re-visiting the menus (e.g., from exiting in-game), the gfx are force-reloaded. // So leftover addresses here should not be a problem. @@ -3701,7 +3701,7 @@ void F_ContinueDrawer(void) V_DrawLevelTitle(x - (V_LevelNameWidth("Continue?")>>1), 16, 0, "Continue?"); // Two stars... - patch = W_CachePatchName("CONTSTAR", PU_PATCH); + patch = W_CachePatchName("CONTSTAR", PU_PATCH_LOWPRIORITY); V_DrawScaledPatch(x-32, 160, 0, patch); V_DrawScaledPatch(x+32, 160, 0, patch); @@ -3709,14 +3709,14 @@ void F_ContinueDrawer(void) if (timeleft > 9) { numbuf[7] = '1'; - V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); + V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY)); numbuf[7] = '0'; - V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); + V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY)); } else { numbuf[7] = '0'+timeleft; - V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); + V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY)); } // Draw the continue markers! Show continues. @@ -3745,7 +3745,7 @@ void F_ContinueDrawer(void) } // Spotlight - V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_PATCH)); + V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_PATCH_LOWPRIORITY)); // warping laser if (continuetime) @@ -3782,7 +3782,7 @@ void F_ContinueDrawer(void) #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_PATCH);\ + patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH_LOWPRIORITY);\ V_DrawFixedPatch((dx), (dy), contskins[n]->highresscale, (sprframe->flip & (1<scene[scenenum].pichires[picnum]) V_DrawSmallScaledPatch(picxpos, picypos, 0, - W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH)); + W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY)); else V_DrawScaledPatch(picxpos,picypos, 0, - W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH)); + W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY)); } if (dofadenow && rendermode != render_none) @@ -4536,10 +4536,10 @@ void F_TextPromptDrawer(void) { if (textprompts[cutnum]->page[scenenum].pichires[picnum]) V_DrawSmallScaledPatch(picxpos, picypos, 0, - W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH)); + W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY)); else V_DrawScaledPatch(picxpos,picypos, 0, - W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH)); + W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY)); } // Draw background @@ -4549,7 +4549,7 @@ void F_TextPromptDrawer(void) if (iconlump != LUMPERROR) { INT32 iconx, icony, scale, scaledsize; - patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_PATCH); + patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_PATCH_LOWPRIORITY); // scale and center if (patch->width > patch->height) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 486b03f33..a8644bb9a 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -733,7 +733,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) if (!M_PointInBox(segbbox,splat->v1.x,splat->v1.y) && !M_PointInBox(segbbox,splat->v2.x,splat->v2.y)) continue; - gpatch = W_CachePatchNum(splat->patch, PU_PATCH); + gpatch = W_CachePatchNum(splat->patch, PU_SPRITE); HWR_GetPatch(gpatch); wallVerts[0].x = wallVerts[3].x = FIXED_TO_FLOAT(splat->v1.x); @@ -3586,7 +3586,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) if (alpha >= 255) return; alpha = 255 - alpha; - gpatch = (patch_t *)W_CachePatchName("DSHADOW", PU_CACHE); + gpatch = (patch_t *)W_CachePatchName("DSHADOW", PU_SPRITE); if (!(gpatch && ((GLPatch_t *)gpatch->hardware)->mipmap->format)) return; HWR_GetPatch(gpatch); @@ -4901,8 +4901,8 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->rollangle) { rollangle = R_GetRollAngle(thing->rollangle); - if (!(sprframe->rotsprite.cached & (1<sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip); + if (sprframe->rotsprite.patch[rot][rollangle] == NULL) + R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, rollangle, flip); rotsprite = sprframe->rotsprite.patch[rot][rollangle]; if (rotsprite != NULL) { @@ -5030,7 +5030,7 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->gpatch = (patch_t *)rotsprite; else #endif - vis->gpatch = (patch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); + vis->gpatch = (patch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); vis->flip = flip; vis->mobj = thing; vis->z1 = z1; @@ -5165,7 +5165,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->z2 = z2; vis->tz = tz; vis->dispoffset = 0; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST - vis->gpatch = (patch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); + vis->gpatch = (patch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); vis->flip = flip; vis->mobj = (mobj_t *)thing; diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index d8375e1e8..69e807d50 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -458,8 +458,8 @@ static int libd_getSpritePatch(lua_State *L) INT32 rot = R_GetRollAngle(rollangle); if (rot) { - if (!(sprframe->rotsprite.cached & (1<flip & (1<rotsprite.patch[angle][rot] == NULL) + R_CacheRotSprite(i, frame, NULL, sprframe, angle, rot, sprframe->flip & (1<rotsprite.patch[angle][rot], META_PATCH); lua_pushboolean(L, false); lua_pushboolean(L, true); @@ -469,7 +469,7 @@ static int libd_getSpritePatch(lua_State *L) #endif // push both the patch and it's "flip" value - LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH); + LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH); lua_pushboolean(L, (sprframe->flip & (1<rotsprite.cached & (1<flip & (1<rotsprite.patch[angle][rot] == NULL) + R_CacheRotSprite(SPR_PLAY, frame, &skins[i].sprinfo[j], sprframe, angle, rot, sprframe->flip & (1<rotsprite.patch[angle][rot], META_PATCH); lua_pushboolean(L, false); lua_pushboolean(L, true); @@ -582,7 +582,7 @@ static int libd_getSprite2Patch(lua_State *L) #endif // push both the patch and it's "flip" value - LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH); + LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH); lua_pushboolean(L, (sprframe->flip & (1<= NUMSPRITES) return luaL_error(L, "spriteinfo[] index %d out of range (1 - %d)", i, NUMSPRITES-1); -#ifdef ROTSPRITE - if (sprites != NULL) - R_FreeRotSprite(&sprites[i]); -#endif info = &spriteinfo[i]; // get the spriteinfo to assign to. } luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. @@ -463,11 +459,6 @@ static int spriteinfo_set(lua_State *L) lua_remove(L, 1); // remove field lua_settop(L, 1); // leave only one value -#ifdef ROTSPRITE - if (sprites != NULL) - R_FreeRotSprite(&sprites[sprinfo-spriteinfo]); -#endif - if (fastcmp(field, "pivot")) { // pivot[] is a table diff --git a/src/m_menu.c b/src/m_menu.c index 0e60dce0c..3c6397ebb 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5840,8 +5840,6 @@ static void M_DrawNightsAttackSuperSonic(void) const UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_YELLOW, GTC_CACHE); INT32 timer = (ntsatkdrawtimer/4) % 2; angle_t fa = (FixedAngle(((ntsatkdrawtimer * 4) % 360)<>ANGLETOFINESHIFT) & FINEMASK; - ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH); - ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH); V_DrawFixedPatch(235<menuitems[itemOn].text,PU_CACHE); + pic_t *pictest = (pic_t *)W_CacheLumpName(currentMenu->menuitems[itemOn].text,PU_CACHE); if (!pictest->zero) V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].text)); else @@ -10153,6 +10151,9 @@ static void M_NightsAttack(INT32 choice) // This is really just to make sure Sonic is the played character, just in case M_PatchSkinNameTable(); + ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH); + ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH); + G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please M_SetupNextMenu(&SP_NightsAttackDef); diff --git a/src/p_setup.c b/src/p_setup.c index 78f78f0c8..ef1ae9eba 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4090,6 +4090,8 @@ boolean P_LoadLevel(boolean fromnetsave) // Clear pointers that would be left dangling by the purge R_FlushTranslationColormapCache(); + Patch_FreeTag(PU_PATCH_LOWPRIORITY); + Patch_FreeTag(PU_SPRITE_ROTATED); Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); #if defined (WALLSPLATS) || defined (FLOORSPLATS) @@ -4475,6 +4477,8 @@ boolean P_AddWadFile(const char *wadfilename) // // search for sprite replacements // + Patch_FreeTag(PU_SPRITE); + Patch_FreeTag(PU_SPRITE_ROTATED); R_AddSpriteDefs(wadnum); // Reload it all anyway, just in case they diff --git a/src/r_data.c b/src/r_data.c index 0e0e613f4..3c7d76d21 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1308,7 +1308,7 @@ void R_PrecacheLevel(void) lump = sf->lumppat[a];\ if (devparm)\ spritememory += W_LumpLength(lump);\ - W_CachePatchNum(lump, PU_PATCH);\ + W_CachePatchNum(lump, PU_SPRITE);\ } // see R_InitSprites for more about lumppat,lumpid switch (sf->rotate) diff --git a/src/r_defs.h b/src/r_defs.h index becf2aed8..679b0fa35 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -711,7 +711,6 @@ typedef struct typedef struct { patch_t *patch[16][ROTANGLES]; - UINT16 cached; } rotsprite_t; #endif/*ROTSPRITE*/ diff --git a/src/r_patch.c b/src/r_patch.c index 281523fd2..d3dff0e33 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -64,7 +64,7 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest) // Frees a patch from memory. // -void Patch_Free(patch_t *patch) +static void Patch_FreeData(patch_t *patch) { #ifdef HWRENDER if (patch->hardware) @@ -75,10 +75,30 @@ void Patch_Free(patch_t *patch) Z_Free(patch->columnofs); if (patch->columns) Z_Free(patch->columns); +} +void Patch_Free(patch_t *patch) +{ + Patch_FreeData(patch); Z_Free(patch); } +// +// Frees patches with a tag range. +// + +static boolean Patch_FreeTagsCallback(void *mem) +{ + patch_t *patch = (patch_t *)mem; + Patch_FreeData(patch); + return true; +} + +void Patch_FreeTags(INT32 lowtag, INT32 hightag) +{ + Z_IterateTags(lowtag, hightag, Patch_FreeTagsCallback); +} + #ifdef HWRENDER // // Allocates a hardware patch. diff --git a/src/r_patch.h b/src/r_patch.h index 2caa8d0e4..c460e7d09 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -19,6 +19,9 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest); void Patch_Free(patch_t *patch); +#define Patch_FreeTag(tagnum) Patch_FreeTags(tagnum, tagnum) +void Patch_FreeTags(INT32 lowtag, INT32 hightag); + #ifdef HWRENDER void *Patch_AllocateHardwarePatch(patch_t *patch); void *Patch_CreateGL(patch_t *patch); diff --git a/src/r_picformats.c b/src/r_picformats.c index d42d36a00..078901fab 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1350,11 +1350,6 @@ static void R_ParseSpriteInfo(boolean spr2) info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); info->available = true; -#ifdef ROTSPRITE - if ((sprites != NULL) && (!spr2)) - R_FreeRotSprite(&sprites[sprnum]); -#endif - // Left Curly Brace sprinfoToken = M_GetToken(NULL); if (sprinfoToken == NULL) @@ -1415,9 +1410,6 @@ static void R_ParseSpriteInfo(boolean spr2) size_t skinnum = skinnumbers[i]; skin_t *skin = &skins[skinnum]; spriteinfo_t *sprinfo = skin->sprinfo; -#ifdef ROTSPRITE - R_FreeSkinRotSprite(skinnum); -#endif M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t)); } } @@ -1532,24 +1524,28 @@ INT32 R_GetRollAngle(angle_t rollangle) // // Create a rotated sprite. // -void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip) +void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, INT32 angle, UINT8 flip) { - INT32 angle; patch_t *patch, *newpatch; UINT16 *rawdst; size_t size; pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0; + // Don't cache angle = 0 + if (angle < 1 || angle >= ROTANGLES) + return; + #define SPRITE_XCENTER (leftoffset) #define SPRITE_YCENTER (height / 2) #define ROTSPRITE_XCENTER (newwidth / 2) #define ROTSPRITE_YCENTER (newheight / 2) - if (!(sprframe->rotsprite.cached & (1<rotsprite.patch[rot][angle] == NULL) { INT32 dx, dy; INT32 px, py; INT32 width, height, leftoffset; + INT32 newwidth, newheight; fixed_t ca, sa; lumpnum_t lump = sprframe->lumppat[rot]; @@ -1579,172 +1575,116 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp leftoffset = width - leftoffset; } - // Don't cache angle = 0 - for (angle = 1; angle < ROTANGLES; angle++) + ca = rollcosang[angle]; + sa = rollsinang[angle]; + + // Find the dimensions of the rotated patch. { - INT32 newwidth, newheight; + INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa)); + INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa)); + INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca)); + INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca)); + w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2))); + w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2))); + h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2))); + h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2))); + newwidth = max(width, max(w1, w2)); + newheight = max(height, max(h1, h2)); + } - ca = rollcosang[angle]; - sa = rollsinang[angle]; + // check boundaries + { + fixed_t top[2][2]; + fixed_t bottom[2][2]; - // Find the dimensions of the rotated patch. - { - INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa)); - INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa)); - INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca)); - INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca)); - w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2))); - w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2))); - h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2))); - h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2))); - newwidth = max(width, max(w1, w2)); - newheight = max(height, max(h1, h2)); - } + top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); + top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); + top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); + top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - // check boundaries - { - fixed_t top[2][2]; - fixed_t bottom[2][2]; + bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); + bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); + bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); + bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); + top[0][0] >>= FRACBITS; + top[0][1] >>= FRACBITS; + top[1][0] >>= FRACBITS; + top[1][1] >>= FRACBITS; - bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - - top[0][0] >>= FRACBITS; - top[0][1] >>= FRACBITS; - top[1][0] >>= FRACBITS; - top[1][1] >>= FRACBITS; - - bottom[0][0] >>= FRACBITS; - bottom[0][1] >>= FRACBITS; - bottom[1][0] >>= FRACBITS; - bottom[1][1] >>= FRACBITS; + bottom[0][0] >>= FRACBITS; + bottom[0][1] >>= FRACBITS; + bottom[1][0] >>= FRACBITS; + bottom[1][1] >>= FRACBITS; #define BOUNDARYWCHECK(b) (b[0] < 0 || b[0] >= width) #define BOUNDARYHCHECK(b) (b[1] < 0 || b[1] >= height) #define BOUNDARYADJUST(x) x *= 2 - // top left/right - if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1])) - BOUNDARYADJUST(newwidth); - // bottom left/right - else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1])) - BOUNDARYADJUST(newwidth); - // top left/right - if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1])) - BOUNDARYADJUST(newheight); - // bottom left/right - else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1])) - BOUNDARYADJUST(newheight); + // top left/right + if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1])) + BOUNDARYADJUST(newwidth); + // bottom left/right + else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1])) + BOUNDARYADJUST(newwidth); + // top left/right + if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1])) + BOUNDARYADJUST(newheight); + // bottom left/right + else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1])) + BOUNDARYADJUST(newheight); #undef BOUNDARYWCHECK #undef BOUNDARYHCHECK #undef BOUNDARYADJUST - } - - // Draw the rotated sprite to a temporary buffer. - size = (newwidth * newheight); - if (!size) - size = (width * height); - rawdst = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL); - - for (dy = 0; dy < newheight; dy++) - { - for (dx = 0; dx < newwidth; dx++) - { - INT32 x = (dx-ROTSPRITE_XCENTER) << FRACBITS; - INT32 y = (dy-ROTSPRITE_YCENTER) << FRACBITS; - INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (px << FRACBITS); - INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (py << FRACBITS); - sx >>= FRACBITS; - sy >>= FRACBITS; - if (sx >= 0 && sy >= 0 && sx < width && sy < height) - { - void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip); - if (input != NULL) - rawdst[(dy*newwidth)+dx] = (0xFF00 | (*(UINT8 *)input)); - } - } - } - - // make patch - newpatch = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0); - { - newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px); - newpatch->topoffset = (newpatch->height / 2) + (patch->topoffset - py); - } - - //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer - if (rendermode != render_none) // not for psprite - newpatch->topoffset += FEETADJUST>>FRACBITS; - - // P_PrecacheLevel - if (devparm) spritememory += size; - - sprframe->rotsprite.patch[rot][angle] = newpatch; - - // free rotated image data - Z_Free(rawdst); } - // This rotation is cached now - sprframe->rotsprite.cached |= (1<>= FRACBITS; + sy >>= FRACBITS; + if (sx >= 0 && sy >= 0 && sx < width && sy < height) + { + void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip); + if (input != NULL) + rawdst[(dy*newwidth)+dx] = (0xFF00 | (*(UINT8 *)input)); + } + } + } + + // make patch + newpatch = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0); + Z_ChangeTag(newpatch, PU_SPRITE_ROTATED); + { + newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px); + newpatch->topoffset = (newpatch->height / 2) + (patch->topoffset - py); + } + + //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer + if (rendermode != render_none) // not for psprite + newpatch->topoffset += FEETADJUST>>FRACBITS; + + // P_PrecacheLevel + if (devparm) spritememory += size; + + Z_SetUser(newpatch, &sprframe->rotsprite.patch[rot][angle]); + + // free rotated image data + Z_Free(rawdst); } #undef SPRITE_XCENTER #undef SPRITE_YCENTER #undef ROTSPRITE_XCENTER #undef ROTSPRITE_YCENTER } - -// -// R_FreeRotSprite -// -// Free sprite rotation data from memory, for a single spritedef. -// -void R_FreeRotSprite(spritedef_t *spritedef) -{ - UINT8 frame; - INT32 rot, ang; - - for (frame = 0; frame < spritedef->numframes; frame++) - { - spriteframe_t *sprframe = &spritedef->spriteframes[frame]; - for (rot = 0; rot < 16; rot++) - { - if (sprframe->rotsprite.cached & (1<rotsprite.patch[rot][ang]; - if (rotsprite) - Patch_Free(rotsprite); - rotsprite = NULL; - } - sprframe->rotsprite.cached &= ~(1<sprites; - for (i = 0; i < NUMPLAYERSPRITES*2; i++) - { - R_FreeRotSprite(skinsprites); - skinsprites++; - } -} #endif diff --git a/src/r_picformats.h b/src/r_picformats.h index f303b9e3d..4f5c60ee1 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -126,9 +126,7 @@ void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); // Sprite rotation #ifdef ROTSPRITE INT32 R_GetRollAngle(angle_t rollangle); -void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip); -void R_FreeRotSprite(spritedef_t *spritedef); -void R_FreeSkinRotSprite(size_t skinnum); +void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, INT32 angle, UINT8 flip); extern fixed_t rollcosang[ROTANGLES]; extern fixed_t rollsinang[ROTANGLES]; #endif diff --git a/src/r_things.c b/src/r_things.c index 8bbf21b54..e4465dfa9 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -107,7 +107,6 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch // rotsprite #ifdef ROTSPRITE - sprtemp[frame].rotsprite.cached = 0; for (r = 0; r < 16; r++) { for (ang = 0; ang < ROTANGLES; ang++) @@ -241,9 +240,6 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 // if so, it might patch only certain frames, not all if (spritedef->numframes) // (then spriteframes is not null) { -#ifdef ROTSPRITE - R_FreeRotSprite(spritedef); -#endif // copy the already defined sprite frames M_Memcpy(sprtemp, spritedef->spriteframes, spritedef->numframes * sizeof (spriteframe_t)); @@ -402,9 +398,6 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 if (spritedef->numframes && // has been allocated spritedef->numframes < maxframe) // more frames are defined ? { -#ifdef ROTSPRITE - R_FreeRotSprite(spritedef); -#endif Z_Free(spritedef->spriteframes); spritedef->spriteframes = NULL; } @@ -1237,7 +1230,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, scalemul = FixedMul(FRACUNIT - floordiff/640, scale); - patch = W_CachePatchName("DSHADOW", PU_CACHE); + patch = W_CachePatchName("DSHADOW", PU_SPRITE); xscale = FixedDiv(projection, tz); yscale = FixedDiv(projectiony, tz); shadowxscale = FixedMul(thing->radius*2, scalemul); @@ -1533,8 +1526,8 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->rollangle) { rollangle = R_GetRollAngle(thing->rollangle); - if (!(sprframe->rotsprite.cached & (1<sprite, frame, sprinfo, sprframe, rot, flip); + if (sprframe->rotsprite.patch[rot][rollangle] == NULL) + R_CacheRotSprite(thing->sprite, frame, sprinfo, sprframe, rot, rollangle, flip); rotsprite = sprframe->rotsprite.patch[rot][rollangle]; if (rotsprite != NULL) { @@ -1823,7 +1816,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->patch = rotsprite; else #endif - vis->patch = W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); + vis->patch = W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); // // determine the colormap (lightlevel & special effects) @@ -2006,7 +1999,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) //Fab: lumppat is the lump number of the patch to use, this is different // than lumpid for sprites-in-pwad : the graphics are patched - vis->patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + vis->patch = W_CachePatchNum(sprframe->lumppat[0], PU_SPRITE); // specific translucency if (thing->frame & FF_TRANSMASK) diff --git a/src/st_stuff.c b/src/st_stuff.c index f6ba94fcc..5f3d75f44 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -232,7 +232,7 @@ void ST_doPaletteStuff(void) void ST_UnloadGraphics(void) { - Z_FreeTag(PU_HUDGFX); + Patch_FreeTag(PU_HUDGFX); } void ST_LoadGraphics(void) @@ -2080,21 +2080,21 @@ static void ST_drawNiGHTSHUD(void) if (stplyr->powers[pw_nights_superloop]) { pwr = stplyr->powers[pw_nights_superloop]; - V_DrawSmallScaledPatch(110, 44, 0, W_CachePatchName("NPRUA0",PU_CACHE)); + V_DrawSmallScaledPatch(110, 44, 0, W_CachePatchName("NPRUA0",PU_SPRITE)); V_DrawThinString(106, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); } if (stplyr->powers[pw_nights_helper]) { pwr = stplyr->powers[pw_nights_helper]; - V_DrawSmallScaledPatch(150, 44, 0, W_CachePatchName("NPRUC0",PU_CACHE)); + V_DrawSmallScaledPatch(150, 44, 0, W_CachePatchName("NPRUC0",PU_SPRITE)); V_DrawThinString(146, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); } if (stplyr->powers[pw_nights_linkfreeze]) { pwr = stplyr->powers[pw_nights_linkfreeze]; - V_DrawSmallScaledPatch(190, 44, 0, W_CachePatchName("NPRUE0",PU_CACHE)); + V_DrawSmallScaledPatch(190, 44, 0, W_CachePatchName("NPRUE0",PU_SPRITE)); V_DrawThinString(186, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); } } diff --git a/src/y_inter.c b/src/y_inter.c index 4810ce7fa..961311593 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -2044,18 +2044,13 @@ void Y_EndIntermission(void) usebuffer = false; } -#define UNLOAD(x) if (x) {Z_ChangeTag(x, PU_CACHE);} x = NULL; +#define UNLOAD(x) if (x) {Patch_Free(x);} x = NULL; // // Y_UnloadData // static void Y_UnloadData(void) { - // In hardware mode, don't Z_ChangeTag a pointer returned by W_CachePatchName(). - // It doesn't work and is unnecessary. - if (rendermode != render_soft) - return; - // unload the background patches UNLOAD(bgpatch); UNLOAD(bgtile); diff --git a/src/z_zone.c b/src/z_zone.c index 02f9a9920..b704e1a30 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -496,6 +496,33 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag) } } +/** Iterates through all memory for a given set of tags. + * + * \param lowtag The lowest tag to consider. + * \param hightag The highest tag to consider. + * \param iterfunc The iterator function. + */ +void Z_IterateTags(INT32 lowtag, INT32 hightag, boolean (*iterfunc)(void *)) +{ + memblock_t *block, *next; + + if (!iterfunc) + I_Error("Z_IterateTags: no iterator function was given"); + + for (block = head.next; block != &head; block = next) + { + next = block->next; // get link before possibly freeing + + if (block->tag >= lowtag && block->tag <= hightag) + { + void *mem = (UINT8 *)block->hdr + sizeof *block->hdr; + boolean free = iterfunc(mem); + if (free) + Z_Free(mem); + } + } +} + // ----------------- // Utility functions // ----------------- @@ -772,6 +799,11 @@ static void Command_Memfree_f(void) CONS_Printf(M_GetText("Static : %7s KB\n"), sizeu1(Z_TagUsage(PU_STATIC)>>10)); CONS_Printf(M_GetText("Static (sound) : %7s KB\n"), sizeu1(Z_TagUsage(PU_SOUND)>>10)); CONS_Printf(M_GetText("Static (music) : %7s KB\n"), sizeu1(Z_TagUsage(PU_MUSIC)>>10)); + CONS_Printf(M_GetText("Patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_PATCH)>>10)); + CONS_Printf(M_GetText("Patches (low) : %7s KB\n"), sizeu1(Z_TagUsage(PU_PATCH_LOWPRIORITY)>>10)); + CONS_Printf(M_GetText("Sprites : %7s KB\n"), sizeu1(Z_TagUsage(PU_SPRITE)>>10)); + CONS_Printf(M_GetText("Sprites (rotated) : %7s KB\n"), sizeu1(Z_TagUsage(PU_SPRITE_ROTATED)>>10)); + CONS_Printf(M_GetText("HUD graphics : %7s KB\n"), sizeu1(Z_TagUsage(PU_HUDGFX)>>10)); CONS_Printf(M_GetText("Locked cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_CACHE)>>10)); CONS_Printf(M_GetText("Level : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVEL)>>10)); CONS_Printf(M_GetText("Special thinker : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVSPEC)>>10)); diff --git a/src/z_zone.h b/src/z_zone.h index c9dafc1ae..90a6de8eb 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -42,8 +42,12 @@ enum PU_SOUND = 11, // static while playing PU_MUSIC = 12, // static while playing - PU_HUDGFX = 13, // static until WAD added - PU_PATCH = 14, // static until renderer change + + PU_PATCH = 14, // static entire execution time + PU_PATCH_LOWPRIORITY = 15, // lower priority patch, static until level exited + PU_SPRITE = 16, // sprite patch, static until WAD added + PU_SPRITE_ROTATED = 17, // sprite patch, static until level exited or WAD added + PU_HUDGFX = 18, // HUD patch, static until WAD added PU_HWRPATCHINFO = 21, // Hardware GLPatch_t struct for OpenGL texture cache PU_HWRPATCHCOLMIPMAP = 22, // Hardware GLMipmap_t struct colormap variation of patch @@ -63,7 +67,7 @@ enum PU_HWRCACHE_UNLOCKED = 102, // 'unlocked' PU_HWRCACHE memory: // 'second-level' cache for graphics // stored in hardware format and downloaded as needed - PU_HWRPATCHINFO_UNLOCKED = 103, // 'unlocked' PU_HWRPATCHINFO memory + PU_HWRPATCHINFO_UNLOCKED = 103, // 'unlocked' PU_HWRPATCHINFO memory PU_HWRMODELTEXTURE_UNLOCKED = 104, // 'unlocked' PU_HWRMODELTEXTURE memory }; @@ -107,6 +111,10 @@ void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignb #define Z_FreeTag(tagnum) Z_FreeTags(tagnum, tagnum) void Z_FreeTags(INT32 lowtag, INT32 hightag); +// Iterate memory by tag +#define Z_IterateTag(tagnum, func) Z_IterateTags(tagnum, tagnum, func) +void Z_IterateTags(INT32 lowtag, INT32 hightag, boolean (*iterfunc)(void *)); + // // Utility functions // From e23929a8998ff1bdc742e4d5c05db8f02018f076 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 10 Oct 2020 18:43:26 -0300 Subject: [PATCH 08/81] Refactor patch rotation --- src/CMakeLists.txt | 1 + src/Makefile | 1 + src/hardware/hw_main.c | 16 +- src/lua_hudlib.c | 10 +- src/p_setup.c | 4 +- src/r_defs.h | 22 ++- src/r_patch.c | 21 ++- src/r_patch.h | 8 + src/r_patchrotation.c | 248 +++++++++++++++++++++++++ src/r_picformats.c | 194 +------------------ src/r_picformats.h | 8 - src/r_things.c | 19 +- src/sdl/Srb2SDL-vc10.vcxproj | 4 + src/sdl/Srb2SDL-vc10.vcxproj.filters | 16 +- src/win32/Srb2win-vc10.vcxproj | 4 + src/win32/Srb2win-vc10.vcxproj.filters | 17 +- src/z_zone.c | 26 +-- src/z_zone.h | 7 +- 18 files changed, 371 insertions(+), 255 deletions(-) create mode 100644 src/r_patchrotation.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba574f414..9c2326399 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -129,6 +129,7 @@ set(SRB2_CORE_RENDER_SOURCES r_things.c r_textures.c r_patch.c + r_patchrotation.c r_picformats.c r_portal.c diff --git a/src/Makefile b/src/Makefile index f50840920..bdbb35363 100644 --- a/src/Makefile +++ b/src/Makefile @@ -519,6 +519,7 @@ OBJS:=$(i_main_o) \ $(OBJDIR)/r_things.o \ $(OBJDIR)/r_textures.o \ $(OBJDIR)/r_patch.o \ + $(OBJDIR)/r_patchrotation.o \ $(OBJDIR)/r_picformats.o \ $(OBJDIR)/r_portal.o \ $(OBJDIR)/screen.o \ diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e60645eb6..fe0aa2f35 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4754,7 +4754,9 @@ static void HWR_ProjectSprite(mobj_t *thing) float gz, gzt; spritedef_t *sprdef; spriteframe_t *sprframe; +#ifdef ROTSPRITE spriteinfo_t *sprinfo; +#endif md2_t *md2; size_t lumpoff; unsigned rot; @@ -4824,12 +4826,16 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->skin && thing->sprite == SPR_PLAY) { sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; +#ifdef ROTSPRITE sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; +#endif } else { sprdef = &sprites[thing->sprite]; - sprinfo = NULL; +#ifdef ROTSPRITE + sprinfo = &spriteinfo[thing->sprite]; +#endif } if (rot >= sprdef->numframes) @@ -4839,7 +4845,9 @@ static void HWR_ProjectSprite(mobj_t *thing) thing->sprite = states[S_UNKNOWN].sprite; thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; - sprinfo = NULL; +#ifdef ROTSPRITE + sprinfo = &spriteinfo[thing->sprite]; +#endif rot = thing->frame&FF_FRAMEMASK; thing->state->sprite = thing->sprite; thing->state->frame = thing->frame; @@ -4901,9 +4909,7 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->rollangle) { rollangle = R_GetRollAngle(thing->rollangle); - if (sprframe->rotsprite.patch[rot][rollangle] == NULL) - R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, rollangle, flip); - rotsprite = sprframe->rotsprite.patch[rot][rollangle]; + rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, sprinfo, rollangle); if (rotsprite != NULL) { spr_width = SHORT(rotsprite->width) << FRACBITS; diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index ba3342b44..335e6cfbc 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -458,9 +458,8 @@ static int libd_getSpritePatch(lua_State *L) INT32 rot = R_GetRollAngle(rollangle); if (rot) { - if (sprframe->rotsprite.patch[angle][rot] == NULL) - R_CacheRotSprite(i, frame, NULL, sprframe, angle, rot, sprframe->flip & (1<rotsprite.patch[angle][rot], META_PATCH); + patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<rotsprite.patch[angle][rot] == NULL) - R_CacheRotSprite(SPR_PLAY, frame, &skins[i].sprinfo[j], sprframe, angle, rot, sprframe->flip & (1<rotsprite.patch[angle][rot], META_PATCH); + patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<height = source->height; patch->leftoffset = source->leftoffset; patch->topoffset = source->topoffset; - patch->columnofs = Z_Calloc(size, PU_PATCH, NULL); + patch->columnofs = Z_Calloc(size, PU_PATCH_DATA, NULL); for (col = 0; col < source->width; col++) { @@ -53,7 +53,7 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest) if (colsize <= 0) I_Error("R_CreatePatch: no column data!"); - patch->columns = Z_Calloc(colsize, PU_PATCH, NULL); + patch->columns = Z_Calloc(colsize, PU_PATCH_DATA, NULL); M_Memcpy(patch->columns, ((UINT8 *)source + LONG(source->columnofs[0])), colsize); } @@ -71,6 +71,23 @@ static void Patch_FreeData(patch_t *patch) HWR_FreeTexture(patch); #endif +#ifdef ROTSPRITE + if (patch->rotated) + { + rotsprite_t *rotsprite = patch->rotated; + INT32 i = 0; + + for (; i < rotsprite->angles; i++) + { + if (rotsprite->patches[i]) + Patch_Free(rotsprite->patches[i]); + } + + Z_Free(rotsprite->patches); + Z_Free(rotsprite); + } +#endif + if (patch->columnofs) Z_Free(patch->columnofs); if (patch->columns) diff --git a/src/r_patch.h b/src/r_patch.h index c460e7d09..71f185c9d 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -27,4 +27,12 @@ void *Patch_AllocateHardwarePatch(patch_t *patch); void *Patch_CreateGL(patch_t *patch); #endif +#ifdef ROTSPRITE +void Patch_Rotate(patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip); +patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip); +patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spriteangle, boolean flip, void *info, INT32 rotationangle);INT32 R_GetRollAngle(angle_t rollangle); +extern fixed_t rollcosang[ROTANGLES]; +extern fixed_t rollsinang[ROTANGLES]; +#endif + #endif // __R_PATCH__ diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c new file mode 100644 index 000000000..77544c3ac --- /dev/null +++ b/src/r_patchrotation.c @@ -0,0 +1,248 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_patchrotation.c +/// \brief Patch rotation. + +#include "r_patch.h" +#include "r_picformats.h" +#include "r_things.h" // FEETADJUST +#include "z_zone.h" +#include "w_wad.h" + +#ifdef ROTSPRITE + +static rotsprite_t *RotatedPatch_Create(INT32 numangles); +static void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip); + +fixed_t rollcosang[ROTANGLES]; +fixed_t rollsinang[ROTANGLES]; + +INT32 R_GetRollAngle(angle_t rollangle) +{ + INT32 ra = AngleFixed(rollangle)>>FRACBITS; +#if (ROTANGDIFF > 1) + ra += (ROTANGDIFF/2); +#endif + ra /= ROTANGDIFF; + ra %= ROTANGLES; + return ra; +} + +patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip) +{ + rotsprite_t *rotsprite = patch->rotated; + if (rotsprite == NULL || angle < 1 || angle >= ROTANGLES) + return NULL; + + if (flip) + angle += rotsprite->angles; + + return rotsprite->patches[angle]; +} + +patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spriteangle, boolean flip, void *info, INT32 rotationangle) +{ + rotsprite_t *rotsprite = sprite->rotated[spriteangle]; + spriteinfo_t *sprinfo = (spriteinfo_t *)info; + INT32 idx = rotationangle; + + if (rotationangle < 1 || rotationangle >= ROTANGLES) + return NULL; + + if (rotsprite == NULL) + { + rotsprite = RotatedPatch_Create(ROTANGLES); + sprite->rotated[spriteangle] = rotsprite; + } + + if (flip) + idx += rotsprite->angles; + + if (rotsprite->patches[idx] == NULL) + { + patch_t *patch; + INT32 xpivot = 0, ypivot = 0; + lumpnum_t lump = sprite->lumppat[spriteangle]; + + if (lump == LUMPERROR) + return NULL; + + patch = W_CachePatchNum(lump, PU_SPRITE); + + if (sprinfo->available) + { + xpivot = sprinfo->pivot[frame].x; + ypivot = sprinfo->pivot[frame].y; + } + else + { + xpivot = patch->leftoffset; + ypivot = patch->height / 2; + } + + RotatedPatch_DoRotation(rotsprite, patch, rotationangle, xpivot, ypivot, flip); + } + + return rotsprite->patches[idx]; +} + +void Patch_Rotate(patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip) +{ + if (patch->rotated == NULL) + patch->rotated = RotatedPatch_Create(ROTANGLES); + RotatedPatch_DoRotation(patch->rotated, patch, angle, xpivot, ypivot, flip); +} + +rotsprite_t *RotatedPatch_Create(INT32 numangles) +{ + rotsprite_t *rotsprite = Z_Calloc(sizeof(rotsprite_t), PU_STATIC, NULL); + rotsprite->angles = numangles; + rotsprite->patches = Z_Calloc(rotsprite->angles * 2 * sizeof(void *), PU_STATIC, NULL); + return rotsprite; +} + +void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip) +{ + patch_t *rotated; + UINT16 *rawdst; + size_t size; + pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0; + + INT32 width = patch->width; + INT32 height = patch->height; + INT32 leftoffset = patch->leftoffset; + INT32 newwidth, newheight; + + INT32 dx, dy; + fixed_t ca = rollcosang[angle]; + fixed_t sa = rollsinang[angle]; + INT32 idx = angle; + + // Don't cache angle = 0 + if (angle < 1 || angle >= ROTANGLES) + return; + +#define ROTSPRITE_XCENTER (newwidth / 2) +#define ROTSPRITE_YCENTER (newheight / 2) + + if (flip) + idx += rotsprite->angles; + + if (rotsprite->patches[idx]) + return; + + if (bflip) + { + xpivot = width - xpivot; + leftoffset = width - leftoffset; + } + + // Find the dimensions of the rotated patch. + { + INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa)); + INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa)); + INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca)); + INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca)); + w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2))); + w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2))); + h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2))); + h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2))); + newwidth = max(width, max(w1, w2)); + newheight = max(height, max(h1, h2)); + } + + // check boundaries + { + fixed_t top[2][2]; + fixed_t bottom[2][2]; + + top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS); + top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS); + top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS); + top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS); + + bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS); + bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS); + bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS); + bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS); + + top[0][0] >>= FRACBITS; + top[0][1] >>= FRACBITS; + top[1][0] >>= FRACBITS; + top[1][1] >>= FRACBITS; + + bottom[0][0] >>= FRACBITS; + bottom[0][1] >>= FRACBITS; + bottom[1][0] >>= FRACBITS; + bottom[1][1] >>= FRACBITS; + +#define BOUNDARYWCHECK(b) (b[0] < 0 || b[0] >= width) +#define BOUNDARYHCHECK(b) (b[1] < 0 || b[1] >= height) +#define BOUNDARYADJUST(x) x *= 2 + // top left/right + if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1])) + BOUNDARYADJUST(newwidth); + // bottom left/right + else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1])) + BOUNDARYADJUST(newwidth); + // top left/right + if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1])) + BOUNDARYADJUST(newheight); + // bottom left/right + else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1])) + BOUNDARYADJUST(newheight); +#undef BOUNDARYWCHECK +#undef BOUNDARYHCHECK +#undef BOUNDARYADJUST + } + + // Draw the rotated sprite to a temporary buffer. + size = (newwidth * newheight); + if (!size) + size = (width * height); + rawdst = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL); + + for (dy = 0; dy < newheight; dy++) + { + for (dx = 0; dx < newwidth; dx++) + { + INT32 x = (dx-ROTSPRITE_XCENTER) << FRACBITS; + INT32 y = (dy-ROTSPRITE_YCENTER) << FRACBITS; + INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (xpivot << FRACBITS); + INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (ypivot << FRACBITS); + sx >>= FRACBITS; + sy >>= FRACBITS; + if (sx >= 0 && sy >= 0 && sx < width && sy < height) + { + void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip); + if (input != NULL) + rawdst[(dy*newwidth)+dx] = (0xFF00 | (*(UINT8 *)input)); + } + } + } + + // make patch + rotated = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0); + + Z_ChangeTag(rotated, PU_PATCH_ROTATED); + Z_SetUser(rotated, (void **)(&rotsprite->patches[angle])); + + rotated->leftoffset = (rotated->width / 2) + (leftoffset - xpivot); + rotated->topoffset = (rotated->height / 2) + (patch->topoffset - ypivot); + + //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer + rotated->topoffset += FEETADJUST>>FRACBITS; + + // free rotated image data + Z_Free(rawdst); + +#undef ROTSPRITE_XCENTER +#undef ROTSPRITE_YCENTER +} +#endif diff --git a/src/r_picformats.c b/src/r_picformats.c index 7b44d21f1..8ec78663e 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -17,11 +17,10 @@ #include "i_video.h" #include "r_data.h" #include "r_patch.h" -#include "r_textures.h" -#include "r_draw.h" -#include "r_patch.h" #include "r_picformats.h" +#include "r_textures.h" #include "r_things.h" +#include "r_draw.h" #include "v_video.h" #include "z_zone.h" #include "w_wad.h" @@ -1672,192 +1671,3 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) R_ParseSPRTINFOLump(wadnum, i); } } - -#ifdef ROTSPRITE -// -// R_GetRollAngle -// -// Angles precalculated in R_InitSprites. -// -fixed_t rollcosang[ROTANGLES]; -fixed_t rollsinang[ROTANGLES]; -INT32 R_GetRollAngle(angle_t rollangle) -{ - INT32 ra = AngleFixed(rollangle)>>FRACBITS; -#if (ROTANGDIFF > 1) - ra += (ROTANGDIFF/2); -#endif - ra /= ROTANGDIFF; - ra %= ROTANGLES; - return ra; -} - -// -// R_CacheRotSprite -// -// Create a rotated sprite. -// -void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, INT32 angle, UINT8 flip) -{ - patch_t *patch, *newpatch; - UINT16 *rawdst; - size_t size; - pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0; - - // Don't cache angle = 0 - if (angle < 1 || angle >= ROTANGLES) - return; - -#define SPRITE_XCENTER (leftoffset) -#define SPRITE_YCENTER (height / 2) -#define ROTSPRITE_XCENTER (newwidth / 2) -#define ROTSPRITE_YCENTER (newheight / 2) - - if (sprframe->rotsprite.patch[rot][angle] == NULL) - { - INT32 dx, dy; - INT32 px, py; - INT32 width, height, leftoffset; - INT32 newwidth, newheight; - fixed_t ca, sa; - lumpnum_t lump = sprframe->lumppat[rot]; - - if (lump == LUMPERROR) - return; - - patch = (patch_t *)W_CachePatchNum(lump, PU_STATIC); - width = patch->width; - height = patch->height; - leftoffset = patch->leftoffset; - - // rotation pivot - px = SPRITE_XCENTER; - py = SPRITE_YCENTER; - - // get correct sprite info for sprite - if (sprinfo == NULL) - sprinfo = &spriteinfo[sprnum]; - if (sprinfo->available) - { - px = sprinfo->pivot[frame].x; - py = sprinfo->pivot[frame].y; - } - if (bflip) - { - px = width - px; - leftoffset = width - leftoffset; - } - - ca = rollcosang[angle]; - sa = rollsinang[angle]; - - // Find the dimensions of the rotated patch. - { - INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa)); - INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa)); - INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca)); - INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca)); - w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2))); - w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2))); - h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2))); - h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2))); - newwidth = max(width, max(w1, w2)); - newheight = max(height, max(h1, h2)); - } - - // check boundaries - { - fixed_t top[2][2]; - fixed_t bottom[2][2]; - - top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - - bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - - top[0][0] >>= FRACBITS; - top[0][1] >>= FRACBITS; - top[1][0] >>= FRACBITS; - top[1][1] >>= FRACBITS; - - bottom[0][0] >>= FRACBITS; - bottom[0][1] >>= FRACBITS; - bottom[1][0] >>= FRACBITS; - bottom[1][1] >>= FRACBITS; - -#define BOUNDARYWCHECK(b) (b[0] < 0 || b[0] >= width) -#define BOUNDARYHCHECK(b) (b[1] < 0 || b[1] >= height) -#define BOUNDARYADJUST(x) x *= 2 - // top left/right - if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1])) - BOUNDARYADJUST(newwidth); - // bottom left/right - else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1])) - BOUNDARYADJUST(newwidth); - // top left/right - if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1])) - BOUNDARYADJUST(newheight); - // bottom left/right - else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1])) - BOUNDARYADJUST(newheight); -#undef BOUNDARYWCHECK -#undef BOUNDARYHCHECK -#undef BOUNDARYADJUST - } - - // Draw the rotated sprite to a temporary buffer. - size = (newwidth * newheight); - if (!size) - size = (width * height); - rawdst = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL); - - for (dy = 0; dy < newheight; dy++) - { - for (dx = 0; dx < newwidth; dx++) - { - INT32 x = (dx-ROTSPRITE_XCENTER) << FRACBITS; - INT32 y = (dy-ROTSPRITE_YCENTER) << FRACBITS; - INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (px << FRACBITS); - INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (py << FRACBITS); - sx >>= FRACBITS; - sy >>= FRACBITS; - if (sx >= 0 && sy >= 0 && sx < width && sy < height) - { - void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip); - if (input != NULL) - rawdst[(dy*newwidth)+dx] = (0xFF00 | (*(UINT8 *)input)); - } - } - } - - // make patch - newpatch = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0); - Z_ChangeTag(newpatch, PU_SPRITE_ROTATED); - { - newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px); - newpatch->topoffset = (newpatch->height / 2) + (patch->topoffset - py); - } - - //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer - if (rendermode != render_none) // not for psprite - newpatch->topoffset += FEETADJUST>>FRACBITS; - - // P_PrecacheLevel - if (devparm) spritememory += size; - - Z_SetUser(newpatch, &sprframe->rotsprite.patch[rot][angle]); - - // free rotated image data - Z_Free(rawdst); - } -#undef SPRITE_XCENTER -#undef SPRITE_YCENTER -#undef ROTSPRITE_XCENTER -#undef ROTSPRITE_YCENTER -} -#endif diff --git a/src/r_picformats.h b/src/r_picformats.h index e6c4aa17a..8d3999013 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -125,12 +125,4 @@ extern spriteinfo_t spriteinfo[NUMSPRITES]; void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps); void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); -// Sprite rotation -#ifdef ROTSPRITE -INT32 R_GetRollAngle(angle_t rollangle); -void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, INT32 angle, UINT8 flip); -extern fixed_t rollcosang[ROTANGLES]; -extern fixed_t rollsinang[ROTANGLES]; -#endif - #endif // __R_PICFORMATS__ diff --git a/src/r_things.c b/src/r_things.c index a9a5c42fc..b7d7302f8 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -97,7 +97,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch { char cn = R_Frame2Char(frame), cr = R_Rotation2Char(rotation); // for debugging - INT32 r, ang; + INT32 r; lumpnum_t lumppat = wad; lumppat <<= 16; lumppat += lump; @@ -105,14 +105,10 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch if (maxframe ==(size_t)-1 || frame > maxframe) maxframe = frame; - // rotsprite #ifdef ROTSPRITE for (r = 0; r < 16; r++) - { - for (ang = 0; ang < ROTANGLES; ang++) - sprtemp[frame].rotsprite.patch[r][ang] = NULL; - } -#endif/*ROTSPRITE*/ + sprtemp[frame].rotated[r] = NULL; +#endif if (rotation == 0) { @@ -1454,7 +1450,7 @@ static void R_ProjectSprite(mobj_t *thing) thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; #ifdef ROTSPRITE - sprinfo = NULL; + sprinfo = &spriteinfo[thing->sprite]; #endif frame = thing->frame&FF_FRAMEMASK; } @@ -1463,7 +1459,7 @@ static void R_ProjectSprite(mobj_t *thing) { sprdef = &sprites[thing->sprite]; #ifdef ROTSPRITE - sprinfo = NULL; + sprinfo = &spriteinfo[thing->sprite]; #endif if (frame >= sprdef->numframes) @@ -1478,6 +1474,7 @@ static void R_ProjectSprite(mobj_t *thing) thing->sprite = states[S_UNKNOWN].sprite; thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; + sprinfo = &spriteinfo[thing->sprite]; frame = thing->frame&FF_FRAMEMASK; } } @@ -1539,9 +1536,7 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->rollangle) { rollangle = R_GetRollAngle(thing->rollangle); - if (sprframe->rotsprite.patch[rot][rollangle] == NULL) - R_CacheRotSprite(thing->sprite, frame, sprinfo, sprframe, rot, rollangle, flip); - rotsprite = sprframe->rotsprite.patch[rot][rollangle]; + rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, sprinfo, rollangle); if (rotsprite != NULL) { spr_width = SHORT(rotsprite->width) << FRACBITS; diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 755fa68e6..b66cea963 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -282,6 +282,8 @@ + + @@ -449,6 +451,8 @@ true + + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index 3bbcd9cb5..3291db6c9 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -474,12 +474,18 @@ Hw_Hardware - + + R_Rend + + R_Rend R_Rend + + R_Rend + R_Rend @@ -952,12 +958,18 @@ Hw_Hardware - + + R_Rend + + R_Rend R_Rend + + R_Rend + R_Rend diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj index 52617037b..3e8af3b0e 100644 --- a/src/win32/Srb2win-vc10.vcxproj +++ b/src/win32/Srb2win-vc10.vcxproj @@ -298,6 +298,8 @@ true + + @@ -454,6 +456,8 @@ + + diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters index 0689a4ac0..7279368f1 100644 --- a/src/win32/Srb2win-vc10.vcxproj.filters +++ b/src/win32/Srb2win-vc10.vcxproj.filters @@ -469,9 +469,18 @@ Hw_Hardware + + R_Rend + + + R_Rend + R_Rend + + R_Rend + R_Rend @@ -886,12 +895,18 @@ Hw_Hardware - + + R_Rend + + R_Rend R_Rend + + R_Rend + R_Rend diff --git a/src/z_zone.c b/src/z_zone.c index b704e1a30..ad64a3a07 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -795,19 +795,19 @@ static void Command_Memfree_f(void) Z_CheckHeap(-1); CONS_Printf("\x82%s", M_GetText("Memory Info\n")); - CONS_Printf(M_GetText("Total heap used : %7s KB\n"), sizeu1(Z_TotalUsage()>>10)); - CONS_Printf(M_GetText("Static : %7s KB\n"), sizeu1(Z_TagUsage(PU_STATIC)>>10)); - CONS_Printf(M_GetText("Static (sound) : %7s KB\n"), sizeu1(Z_TagUsage(PU_SOUND)>>10)); - CONS_Printf(M_GetText("Static (music) : %7s KB\n"), sizeu1(Z_TagUsage(PU_MUSIC)>>10)); - CONS_Printf(M_GetText("Patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_PATCH)>>10)); - CONS_Printf(M_GetText("Patches (low) : %7s KB\n"), sizeu1(Z_TagUsage(PU_PATCH_LOWPRIORITY)>>10)); - CONS_Printf(M_GetText("Sprites : %7s KB\n"), sizeu1(Z_TagUsage(PU_SPRITE)>>10)); - CONS_Printf(M_GetText("Sprites (rotated) : %7s KB\n"), sizeu1(Z_TagUsage(PU_SPRITE_ROTATED)>>10)); - CONS_Printf(M_GetText("HUD graphics : %7s KB\n"), sizeu1(Z_TagUsage(PU_HUDGFX)>>10)); - CONS_Printf(M_GetText("Locked cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_CACHE)>>10)); - CONS_Printf(M_GetText("Level : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVEL)>>10)); - CONS_Printf(M_GetText("Special thinker : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVSPEC)>>10)); - CONS_Printf(M_GetText("All purgable : %7s KB\n"), + CONS_Printf(M_GetText("Total heap used : %7s KB\n"), sizeu1(Z_TotalUsage()>>10)); + CONS_Printf(M_GetText("Static : %7s KB\n"), sizeu1(Z_TagUsage(PU_STATIC)>>10)); + CONS_Printf(M_GetText("Static (sound) : %7s KB\n"), sizeu1(Z_TagUsage(PU_SOUND)>>10)); + CONS_Printf(M_GetText("Static (music) : %7s KB\n"), sizeu1(Z_TagUsage(PU_MUSIC)>>10)); + CONS_Printf(M_GetText("Patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_PATCH)>>10)); + CONS_Printf(M_GetText("Patches (low priority) : %7s KB\n"), sizeu1(Z_TagUsage(PU_PATCH_LOWPRIORITY)>>10)); + CONS_Printf(M_GetText("Patches (rotated) : %7s KB\n"), sizeu1(Z_TagUsage(PU_PATCH_ROTATED)>>10)); + CONS_Printf(M_GetText("Sprites : %7s KB\n"), sizeu1(Z_TagUsage(PU_SPRITE)>>10)); + CONS_Printf(M_GetText("HUD graphics : %7s KB\n"), sizeu1(Z_TagUsage(PU_HUDGFX)>>10)); + CONS_Printf(M_GetText("Locked cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_CACHE)>>10)); + CONS_Printf(M_GetText("Level : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVEL)>>10)); + CONS_Printf(M_GetText("Special thinker : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVSPEC)>>10)); + CONS_Printf(M_GetText("All purgable : %7s KB\n"), sizeu1(Z_TagsUsage(PU_PURGELEVEL, INT32_MAX)>>10)); #ifdef HWRENDER diff --git a/src/z_zone.h b/src/z_zone.h index 90a6de8eb..e80a45e7f 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -45,9 +45,10 @@ enum PU_PATCH = 14, // static entire execution time PU_PATCH_LOWPRIORITY = 15, // lower priority patch, static until level exited - PU_SPRITE = 16, // sprite patch, static until WAD added - PU_SPRITE_ROTATED = 17, // sprite patch, static until level exited or WAD added - PU_HUDGFX = 18, // HUD patch, static until WAD added + PU_PATCH_ROTATED = 16, // rotated patch, static until level exited or WAD added + PU_PATCH_DATA = 17, // patch data, lifetime depends on the patch that owns it + PU_SPRITE = 18, // sprite patch, static until WAD added + PU_HUDGFX = 19, // HUD patch, static until WAD added PU_HWRPATCHINFO = 21, // Hardware GLPatch_t struct for OpenGL texture cache PU_HWRPATCHCOLMIPMAP = 22, // Hardware GLMipmap_t struct colormap variation of patch From c40f2b3f2b5234c05e33f04a399fa098d9a3f531 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 10 Oct 2020 18:53:05 -0300 Subject: [PATCH 09/81] Add r_patchrotation.h --- src/CMakeLists.txt | 1 + src/r_patch.h | 2 -- src/r_patchrotation.c | 9 ++------- src/r_patchrotation.h | 21 +++++++++++++++++++++ src/r_things.c | 1 + 5 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 src/r_patchrotation.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9c2326399..819b9cc35 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -148,6 +148,7 @@ set(SRB2_CORE_RENDER_SOURCES r_things.h r_textures.h r_patch.h + r_patchrotation.h r_picformats.h r_portal.h ) diff --git a/src/r_patch.h b/src/r_patch.h index 71f185c9d..6991d3637 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -31,8 +31,6 @@ void *Patch_CreateGL(patch_t *patch); void Patch_Rotate(patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip); patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip); patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spriteangle, boolean flip, void *info, INT32 rotationangle);INT32 R_GetRollAngle(angle_t rollangle); -extern fixed_t rollcosang[ROTANGLES]; -extern fixed_t rollsinang[ROTANGLES]; #endif #endif // __R_PATCH__ diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 77544c3ac..83eb4eeba 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -9,17 +9,12 @@ /// \file r_patchrotation.c /// \brief Patch rotation. -#include "r_patch.h" -#include "r_picformats.h" +#include "r_patchrotation.h" #include "r_things.h" // FEETADJUST #include "z_zone.h" #include "w_wad.h" #ifdef ROTSPRITE - -static rotsprite_t *RotatedPatch_Create(INT32 numangles); -static void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip); - fixed_t rollcosang[ROTANGLES]; fixed_t rollsinang[ROTANGLES]; diff --git a/src/r_patchrotation.h b/src/r_patchrotation.h new file mode 100644 index 000000000..2744f71d2 --- /dev/null +++ b/src/r_patchrotation.h @@ -0,0 +1,21 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_patchrotation.h +/// \brief Patch rotation. + +#include "r_patch.h" +#include "r_picformats.h" + +#ifdef ROTSPRITE +rotsprite_t *RotatedPatch_Create(INT32 numangles); +void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip); + +extern fixed_t rollcosang[ROTANGLES]; +extern fixed_t rollsinang[ROTANGLES]; +#endif diff --git a/src/r_things.c b/src/r_things.c index b7d7302f8..33b9820c8 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -25,6 +25,7 @@ #include "i_system.h" #include "r_things.h" #include "r_patch.h" +#include "r_patchrotation.h" #include "r_picformats.h" #include "r_plane.h" #include "r_portal.h" From 63bdcb294e03f79f0f90ff3c93fb747a5c23e25d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 10 Oct 2020 19:06:29 -0300 Subject: [PATCH 10/81] Fix rotated flipped patches --- src/r_patchrotation.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 83eb4eeba..803e159ef 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -127,17 +127,15 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle #define ROTSPRITE_YCENTER (newheight / 2) if (flip) - idx += rotsprite->angles; - - if (rotsprite->patches[idx]) - return; - - if (bflip) { + idx += rotsprite->angles; xpivot = width - xpivot; leftoffset = width - leftoffset; } + if (rotsprite->patches[idx]) + return; + // Find the dimensions of the rotated patch. { INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa)); @@ -226,7 +224,7 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle rotated = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0); Z_ChangeTag(rotated, PU_PATCH_ROTATED); - Z_SetUser(rotated, (void **)(&rotsprite->patches[angle])); + Z_SetUser(rotated, (void **)(&rotsprite->patches[idx])); rotated->leftoffset = (rotated->width / 2) + (leftoffset - xpivot); rotated->topoffset = (rotated->height / 2) + (patch->topoffset - ypivot); From 3e06bd4985fd09fade2b5d97f22c92cb65849c1d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sun, 11 Oct 2020 03:39:31 -0300 Subject: [PATCH 11/81] Move calculation of rotated patch dimensions into its own function Simplify rotation code when the pivot isn't in the center --- src/r_patch.c | 4 +- src/r_patchrotation.c | 176 ++++++++++++++++++++++++------------------ 2 files changed, 102 insertions(+), 78 deletions(-) diff --git a/src/r_patch.c b/src/r_patch.c index e12341401..9ca04dd55 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -47,11 +47,11 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest) } if (!srcsize) - I_Error("R_CreatePatch: no source size!"); + I_Error("Patch_Create: no source size!"); colsize = (INT32)(srcsize) - (INT32)offs; if (colsize <= 0) - I_Error("R_CreatePatch: no column data!"); + I_Error("Patch_Create: no column data!"); patch->columns = Z_Calloc(colsize, PU_PATCH_DATA, NULL); M_Memcpy(patch->columns, ((UINT8 *)source + LONG(source->columnofs[0])), colsize); diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 803e159ef..98e3a7687 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -82,6 +82,9 @@ patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spri } RotatedPatch_DoRotation(rotsprite, patch, rotationangle, xpivot, ypivot, flip); + + //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer + ((patch_t *)rotsprite->patches[idx])->topoffset += FEETADJUST>>FRACBITS; } return rotsprite->patches[idx]; @@ -102,10 +105,32 @@ rotsprite_t *RotatedPatch_Create(INT32 numangles) return rotsprite; } +static void RotatedPatch_CalculateDimensions( + INT32 width, INT32 height, + fixed_t ca, fixed_t sa, + INT32 *newwidth, INT32 *newheight) +{ + fixed_t fixedwidth = (width * FRACUNIT); + fixed_t fixedheight = (height * FRACUNIT); + + fixed_t w1 = abs(FixedMul(fixedwidth, ca) - FixedMul(fixedheight, sa)); + fixed_t w2 = abs(FixedMul(-fixedwidth, ca) - FixedMul(fixedheight, sa)); + fixed_t h1 = abs(FixedMul(fixedwidth, sa) + FixedMul(fixedheight, ca)); + fixed_t h2 = abs(FixedMul(-fixedwidth, sa) + FixedMul(fixedheight, ca)); + + w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2))); + w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2))); + h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2))); + h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2))); + + *newwidth = max(width, max(w1, w2)); + *newheight = max(height, max(h1, h2)); +} + void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip) { patch_t *rotated; - UINT16 *rawdst; + UINT16 *rawdst, *rawconv; size_t size; pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0; @@ -114,18 +139,20 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle INT32 leftoffset = patch->leftoffset; INT32 newwidth, newheight; - INT32 dx, dy; fixed_t ca = rollcosang[angle]; fixed_t sa = rollsinang[angle]; + fixed_t xcenter, ycenter; INT32 idx = angle; + INT32 x, y; + INT32 sx, sy; + INT32 dx, dy; + INT32 ox, oy; + INT32 minx, miny, maxx, maxy; // Don't cache angle = 0 if (angle < 1 || angle >= ROTANGLES) return; -#define ROTSPRITE_XCENTER (newwidth / 2) -#define ROTSPRITE_YCENTER (newheight / 2) - if (flip) { idx += rotsprite->angles; @@ -137,63 +164,21 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle return; // Find the dimensions of the rotated patch. + RotatedPatch_CalculateDimensions(width, height, ca, sa, &newwidth, &newheight); + + xcenter = (xpivot * FRACUNIT); + ycenter = (ypivot * FRACUNIT); + + if (xpivot != width / 2 || ypivot != height / 2) { - INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa)); - INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa)); - INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca)); - INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca)); - w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2))); - w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2))); - h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2))); - h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2))); - newwidth = max(width, max(w1, w2)); - newheight = max(height, max(h1, h2)); + newwidth *= 2; + newheight *= 2; } - // check boundaries - { - fixed_t top[2][2]; - fixed_t bottom[2][2]; - - top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS); - top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS); - top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS); - top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS); - - bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS); - bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS); - bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS); - bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS); - - top[0][0] >>= FRACBITS; - top[0][1] >>= FRACBITS; - top[1][0] >>= FRACBITS; - top[1][1] >>= FRACBITS; - - bottom[0][0] >>= FRACBITS; - bottom[0][1] >>= FRACBITS; - bottom[1][0] >>= FRACBITS; - bottom[1][1] >>= FRACBITS; - -#define BOUNDARYWCHECK(b) (b[0] < 0 || b[0] >= width) -#define BOUNDARYHCHECK(b) (b[1] < 0 || b[1] >= height) -#define BOUNDARYADJUST(x) x *= 2 - // top left/right - if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1])) - BOUNDARYADJUST(newwidth); - // bottom left/right - else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1])) - BOUNDARYADJUST(newwidth); - // top left/right - if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1])) - BOUNDARYADJUST(newheight); - // bottom left/right - else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1])) - BOUNDARYADJUST(newheight); -#undef BOUNDARYWCHECK -#undef BOUNDARYHCHECK -#undef BOUNDARYADJUST - } + minx = newwidth; + miny = newheight; + maxx = 0; + maxy = 0; // Draw the rotated sprite to a temporary buffer. size = (newwidth * newheight); @@ -205,37 +190,76 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle { for (dx = 0; dx < newwidth; dx++) { - INT32 x = (dx-ROTSPRITE_XCENTER) << FRACBITS; - INT32 y = (dy-ROTSPRITE_YCENTER) << FRACBITS; - INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (xpivot << FRACBITS); - INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (ypivot << FRACBITS); + x = (dx - (newwidth / 2)) * FRACUNIT; + y = (dy - (newheight / 2)) * FRACUNIT; + sx = FixedMul(x, ca) + FixedMul(y, sa) + xcenter; + sy = -FixedMul(x, sa) + FixedMul(y, ca) + ycenter; + sx >>= FRACBITS; sy >>= FRACBITS; + if (sx >= 0 && sy >= 0 && sx < width && sy < height) { void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip); if (input != NULL) - rawdst[(dy*newwidth)+dx] = (0xFF00 | (*(UINT8 *)input)); + { + rawdst[(dy * newwidth) + dx] = (0xFF00 | (*(UINT8 *)input)); + if (dx < minx) + minx = dx; + if (dy < miny) + miny = dy; + if (dx > maxx) + maxx = dx; + if (dy > maxy) + maxy = dy; + } } } } + ox = (newwidth / 2) + (leftoffset - xpivot); + oy = (newheight / 2) + (patch->topoffset - ypivot); + width = (maxx - minx); + height = (maxy - miny); + + if ((unsigned)(width * height) != size) + { + UINT16 *src, *dest; + + size = (width * height); + rawconv = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL); + + src = &rawdst[(miny * newwidth) + minx]; + dest = rawconv; + dy = height; + + while (dy--) + { + M_Memcpy(dest, src, width * sizeof(UINT16)); + dest += width; + src += newwidth; + } + + ox -= minx; + oy -= miny; + + Z_Free(rawdst); + } + else + { + rawconv = rawdst; + width = newwidth; + height = newheight; + } + // make patch - rotated = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0); + rotated = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawconv, PICFMT_PATCH, 0, NULL, width, height, 0, 0, 0); Z_ChangeTag(rotated, PU_PATCH_ROTATED); Z_SetUser(rotated, (void **)(&rotsprite->patches[idx])); + Z_Free(rawconv); - rotated->leftoffset = (rotated->width / 2) + (leftoffset - xpivot); - rotated->topoffset = (rotated->height / 2) + (patch->topoffset - ypivot); - - //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer - rotated->topoffset += FEETADJUST>>FRACBITS; - - // free rotated image data - Z_Free(rawdst); - -#undef ROTSPRITE_XCENTER -#undef ROTSPRITE_YCENTER + rotated->leftoffset = ox; + rotated->topoffset = oy; } #endif From b4b4738c94117eaaf5ce2128df8f964f12e7ff68 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 12 Oct 2020 00:13:22 -0300 Subject: [PATCH 12/81] Changes to sprite rendering: - Added render flags (see r_defs.h) - Implemented floor splats - Drop shadow sprite rendering through render flags --- src/d_clisrv.c | 6 + src/d_clisrv.h | 3 + src/d_netcmd.c | 4 - src/d_netcmd.h | 3 - src/dehacked.c | 17 + src/doomdef.h | 3 + src/hardware/hw_main.c | 114 +---- src/lua_hudlib.c | 4 +- src/lua_mobjlib.c | 24 ++ src/p_mobj.c | 35 +- src/p_mobj.h | 3 + src/p_saveg.c | 23 +- src/p_setup.c | 13 +- src/p_user.c | 6 - src/r_bsp.c | 5 - src/r_defs.h | 31 +- src/r_draw.c | 1 + src/r_draw.h | 5 + src/r_draw8.c | 224 ++++++++++ src/r_draw8_npo2.c | 98 +++++ src/r_main.c | 6 - src/r_patch.c | 19 +- src/r_patch.h | 10 +- src/r_patchrotation.c | 16 +- src/r_plane.c | 31 +- src/r_segs.c | 179 +------- src/r_splats.c | 797 ++++++++++++---------------------- src/r_splats.h | 67 +-- src/r_things.c | 948 ++++++++++++++++++++++++++++------------- src/r_things.h | 44 +- src/screen.c | 4 + src/screen.h | 2 + src/tmap.nas | 4 +- 33 files changed, 1489 insertions(+), 1260 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index c9490410b..3db5a6207 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -648,12 +648,15 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->eflags = (UINT16)SHORT(players[i].mo->eflags); rsp->flags = LONG(players[i].mo->flags); rsp->flags2 = LONG(players[i].mo->flags2); + rsp->renderflags = LONG(players[i].mo->renderflags); rsp->radius = LONG(players[i].mo->radius); rsp->height = LONG(players[i].mo->height); rsp->scale = LONG(players[i].mo->scale); rsp->destscale = LONG(players[i].mo->destscale); rsp->scalespeed = LONG(players[i].mo->scalespeed); + rsp->spritexscale = LONG(players[i].mo->spritexscale); + rsp->spriteyscale = LONG(players[i].mo->spriteyscale); } static void resynch_read_player(resynch_pak *rsp) @@ -787,6 +790,7 @@ static void resynch_read_player(resynch_pak *rsp) players[i].mo->eflags = (UINT16)SHORT(rsp->eflags); players[i].mo->flags = LONG(rsp->flags); players[i].mo->flags2 = LONG(rsp->flags2); + players[i].mo->renderflags = LONG(rsp->renderflags); players[i].mo->friction = LONG(rsp->friction); players[i].mo->health = LONG(rsp->health); players[i].mo->momx = LONG(rsp->momx); @@ -813,6 +817,8 @@ static void resynch_read_player(resynch_pak *rsp) players[i].mo->scale = LONG(rsp->scale); players[i].mo->destscale = LONG(rsp->destscale); players[i].mo->scalespeed = LONG(rsp->scalespeed); + players[i].mo->spritexscale = LONG(rsp->spritexscale); + players[i].mo->spriteyscale = LONG(rsp->spriteyscale); // And finally, SET THE MOBJ SKIN damn it. if ((players[i].powers[pw_carry] == CR_NIGHTSMODE) && (skins[players[i].skin].sprites[SPR2_NFLY].numframes == 0)) diff --git a/src/d_clisrv.h b/src/d_clisrv.h index adc8a7cc9..0ed0b10f5 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -293,12 +293,15 @@ typedef struct UINT32 flags; UINT32 flags2; UINT16 eflags; + UINT32 renderflags; fixed_t radius; fixed_t height; fixed_t scale; fixed_t destscale; fixed_t scalespeed; + fixed_t spritexscale; + fixed_t spriteyscale; } ATTRPACK resynch_pak; typedef struct diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 6f4bcdb1d..7e0c84584 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -671,10 +671,6 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_gif_dynamicdelay); CV_RegisterVar(&cv_gif_localcolortable); -#ifdef WALLSPLATS - CV_RegisterVar(&cv_splats); -#endif - // register these so it is saved to config CV_RegisterVar(&cv_playername); CV_RegisterVar(&cv_playercolor); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 897c28968..3cd4b33c5 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -75,9 +75,6 @@ extern consvar_t cv_teamscramble; extern consvar_t cv_scrambleonchange; extern consvar_t cv_netstat; -#ifdef WALLSPLATS -extern consvar_t cv_splats; -#endif extern consvar_t cv_countdowntime; extern consvar_t cv_runscripts; diff --git a/src/dehacked.c b/src/dehacked.c index 80a0ad0ff..92a8ffe4e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9035,6 +9035,7 @@ static const char *const MOBJFLAG2_LIST[] = { "AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH "LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) "SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) + "SPLAT", // Object is a splat NULL }; @@ -9579,6 +9580,22 @@ struct { {"tr_trans90",tr_trans90}, {"NUMTRANSMAPS",NUMTRANSMAPS}, + // Render flags + {"RF_HORIZONTALFLIP",RF_HORIZONTALFLIP}, + {"RF_VERTICALFLIP",RF_VERTICALFLIP}, + {"RF_ONESIDED",RF_ONESIDED}, + {"RF_NOSPLATBILLBOARD",RF_NOSPLATBILLBOARD}, + {"RF_NOSPLATROLLANGLE",RF_NOSPLATROLLANGLE}, + {"RF_FULLBRIGHT",RF_FULLBRIGHT}, + {"RF_FULLDARK",RF_FULLDARK}, + {"RF_SPRITETYPEMASK",RF_SPRITETYPEMASK}, + {"RF_PAPERSPRITE",RF_PAPERSPRITE}, + {"RF_FLOORSPRITE",RF_FLOORSPRITE}, + {"RF_VOXELSPRITE",RF_VOXELSPRITE}, + {"RF_SHADOWDRAW",RF_SHADOWDRAW}, + {"RF_SHADOWEFFECTS",RF_SHADOWEFFECTS}, + {"RF_DROPSHADOW",RF_DROPSHADOW}, + // Level flags {"LF_SCRIPTISFILE",LF_SCRIPTISFILE}, {"LF_SPEEDMUSIC",LF_SPEEDMUSIC}, diff --git a/src/doomdef.h b/src/doomdef.h index d0b7ea0c2..98a22e5ab 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -641,6 +641,9 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Render flats on walls #define WALLFLATS +/// Floor splats +#define FLOORSPLATS + /// Maintain compatibility with older 2.2 demos #define OLD22DEMOCOMPAT diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index fe0aa2f35..cfcad29d0 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -700,79 +700,6 @@ static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight) #endif //doplanes -/* - wallVerts order is : - 3--2 - | /| - |/ | - 0--1 -*/ -#ifdef WALLSPLATS -static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) -{ - FOutVector wallVerts[4]; - wallsplat_t *splat; - patch_t *gpatch; - fixed_t i; - // seg bbox - fixed_t segbbox[4]; - - M_ClearBox(segbbox); - M_AddToBox(segbbox, - FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv1)->x), - FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv1)->y)); - M_AddToBox(segbbox, - FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->x), - FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->y)); - - splat = (wallsplat_t *)gl_curline->linedef->splats; - for (; splat; splat = splat->next) - { - //BP: don't draw splat extern to this seg - // this is quick fix best is explain in logboris.txt at 12-4-2000 - if (!M_PointInBox(segbbox,splat->v1.x,splat->v1.y) && !M_PointInBox(segbbox,splat->v2.x,splat->v2.y)) - continue; - - gpatch = W_CachePatchNum(splat->patch, PU_SPRITE); - HWR_GetPatch(gpatch); - - wallVerts[0].x = wallVerts[3].x = FIXED_TO_FLOAT(splat->v1.x); - wallVerts[0].z = wallVerts[3].z = FIXED_TO_FLOAT(splat->v1.y); - wallVerts[2].x = wallVerts[1].x = FIXED_TO_FLOAT(splat->v2.x); - wallVerts[2].z = wallVerts[1].z = FIXED_TO_FLOAT(splat->v2.y); - - i = splat->top; - if (splat->yoffset) - i += *splat->yoffset; - - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(i)+(gpatch->height>>1); - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(i)-(gpatch->height>>1); - - wallVerts[3].s = wallVerts[3].t = wallVerts[2].s = wallVerts[0].t = 0.0f; - wallVerts[1].s = wallVerts[1].t = wallVerts[2].t = wallVerts[0].s = 1.0f; - - switch (splat->flags & SPLATDRAWMODE_MASK) - { - case SPLATDRAWMODE_OPAQUE : - pSurf.PolyColor.s.alpha = 0xff; - i = PF_Translucent; - break; - case SPLATDRAWMODE_TRANS : - pSurf.PolyColor.s.alpha = 128; - i = PF_Translucent; - break; - case SPLATDRAWMODE_SHADE : - pSurf.PolyColor.s.alpha = 0xff; - i = PF_Substractive; - break; - } - - HWD.pfnSetShader(2); // wall shader - HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal); - } -} -#endif - FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) { switch (transtablenum) @@ -797,19 +724,21 @@ static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, I // Wall generation from subsector segs // ========================================================================== +/* + wallVerts order is : + 3--2 + | /| + |/ | + 0--1 +*/ + // // HWR_ProjectWall // static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) { HWR_Lighting(pSurf, lightlevel, wallcolormap); - HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, 2, false); // wall shader - -#ifdef WALLSPLATS - if (gl_curline->linedef->splats && cv_splats.value) - HWR_DrawSegsSplats(pSurf); -#endif } // ========================================================================== @@ -3977,7 +3906,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) patch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); - //const boolean papersprite = (spr->mobj && (spr->mobj->frame & FF_PAPERSPRITE)); + //const boolean papersprite = R_ThingIsPaperSprite(spr->mobj); if (spr->mobj) this_scale = FIXED_TO_FLOAT(spr->mobj->scale); if (hires) @@ -4761,14 +4690,14 @@ static void HWR_ProjectSprite(mobj_t *thing) size_t lumpoff; unsigned rot; UINT16 flip; - boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); + boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !R_ThingVerticallyFlipped(thing)); boolean mirrored = thing->mirrored; - boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored); + boolean hflip = (!R_ThingHorizontallyFlipped(thing) != !mirrored); INT32 dispoffset; angle_t ang; INT32 heightsec, phs; - const boolean papersprite = (thing->frame & FF_PAPERSPRITE); + const boolean papersprite = R_ThingIsPaperSprite(thing); angle_t mobjangle = (thing->player ? thing->player->drawangle : thing->angle); float z1, z2; @@ -4909,13 +4838,16 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->rollangle) { rollangle = R_GetRollAngle(thing->rollangle); - rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, sprinfo, rollangle); + rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); + if (rotsprite != NULL) { - spr_width = SHORT(rotsprite->width) << FRACBITS; - spr_height = SHORT(rotsprite->height) << FRACBITS; - spr_offset = SHORT(rotsprite->leftoffset) << FRACBITS; - spr_topoffset = SHORT(rotsprite->topoffset) << FRACBITS; + spr_width = rotsprite->width << FRACBITS; + spr_height = rotsprite->height << FRACBITS; + spr_offset = rotsprite->leftoffset << FRACBITS; + spr_topoffset = rotsprite->topoffset << FRACBITS; + spr_topoffset += FEETADJUST; + // flip -> rotate, not rotate -> flip flip = 0; } @@ -6224,13 +6156,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, } blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency - HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode, shader, false); - -#ifdef WALLSPLATS - if (gl_curline->linedef->splats && cv_splats.value) - HWR_DrawSegsSplats(pSurf); -#endif } INT32 HWR_GetTextureUsed(void) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 335e6cfbc..7b290bf3f 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -458,7 +458,7 @@ static int libd_getSpritePatch(lua_State *L) INT32 rot = R_GetRollAngle(rollangle); if (rot) { - patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<flip & (1<flip & (1<flip & (1<eflags); break; + case mobj_renderflags: + lua_pushinteger(L, mo->renderflags); + break; case mobj_skin: // skin name or nil, not struct if (!mo->skin) return 0; @@ -381,6 +390,12 @@ static int mobj_get(lua_State *L) case mobj_scalespeed: lua_pushfixed(L, mo->scalespeed); break; + case mobj_spritexscale: + lua_pushfixed(L, mo->spritexscale); + break; + case mobj_spriteyscale: + lua_pushfixed(L, mo->spriteyscale); + break; case mobj_extravalue1: lua_pushinteger(L, mo->extravalue1); break; @@ -580,6 +595,9 @@ static int mobj_set(lua_State *L) case mobj_eflags: mo->eflags = (UINT32)luaL_checkinteger(L, 3); break; + case mobj_renderflags: + mo->renderflags = (UINT32)luaL_checkinteger(L, 3); + break; case mobj_skin: // set skin by name { INT32 i; @@ -721,6 +739,12 @@ static int mobj_set(lua_State *L) case mobj_scalespeed: mo->scalespeed = luaL_checkfixed(L, 3); break; + case mobj_spritexscale: + mo->spritexscale = luaL_checkfixed(L, 3); + break; + case mobj_spriteyscale: + mo->spriteyscale = luaL_checkfixed(L, 3); + break; case mobj_extravalue1: mo->extravalue1 = luaL_checkinteger(L, 3); break; diff --git a/src/p_mobj.c b/src/p_mobj.c index de4385fa7..827650ce6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -38,10 +38,6 @@ static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}}; consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL); -#ifdef WALLSPLATS -consvar_t cv_splats = CVAR_INIT ("splats", "On", CV_SAVE, CV_OnOff, NULL); -#endif - actioncache_t actioncachehead; static mobj_t *overlaycap = NULL; @@ -1961,29 +1957,6 @@ void P_XYMovement(mobj_t *mo) return; } - // draw damage on wall - //SPLAT TEST ---------------------------------------------------------- -#ifdef WALLSPLATS - if (blockingline && mo->type != MT_REDRING && mo->type != MT_FIREBALL - && !(mo->flags2 & (MF2_AUTOMATIC|MF2_RAILRING|MF2_BOUNCERING|MF2_EXPLOSION|MF2_SCATTER))) - // set by last P_TryMove() that failed - { - divline_t divl; - divline_t misl; - fixed_t frac; - - P_MakeDivline(blockingline, &divl); - misl.x = mo->x; - misl.y = mo->y; - misl.dx = mo->momx; - misl.dy = mo->momy; - frac = P_InterceptVector(&divl, &misl); - R_AddWallSplat(blockingline, P_PointOnLineSide(mo->x,mo->y,blockingline), - "A_DMG3", mo->z, frac, SPLATDRAWMODE_SHADE); - } -#endif - // --------------------------------------------------------- SPLAT TEST - P_ExplodeMissile(mo); return; } @@ -9614,12 +9587,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->fuse = 1; // Return to base. break; } - case MT_CANNONBALL: -#ifdef FLOORSPLATS - R_AddFloorSplat(mobj->tracer->subsector, mobj->tracer, "TARGET", mobj->tracer->x, - mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE); -#endif - break; case MT_SPINDUST: // Spindash dust mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000 mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same @@ -10487,6 +10454,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits.. + mobj->renderflags = 0; P_SetupStateAnimation(mobj, st); mobj->friction = ORIG_FRICTION; @@ -10497,6 +10465,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->scale = FRACUNIT; mobj->destscale = mobj->scale; mobj->scalespeed = FRACUNIT/12; + mobj->spritexscale = mobj->spriteyscale = mobj->scale; // TODO: Make this a special map header if ((maptol & TOL_ERZ3) && !(mobj->type == MT_BLACKEGGMAN)) diff --git a/src/p_mobj.h b/src/p_mobj.h index 27a6ef4f0..eb8a9ccc2 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -194,6 +194,7 @@ typedef enum MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) + MF2_SPLAT = 1<<30, // Renders as a splat // free: to and including 1<<31 } mobjflag2_t; @@ -308,6 +309,7 @@ typedef struct mobj_s UINT32 flags; // flags from mobjinfo tables UINT32 flags2; // MF2_ flags UINT16 eflags; // extra flags + UINT32 renderflags; // render flags void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin) // Player and mobj sprites in multiplayer modes are modified @@ -360,6 +362,7 @@ typedef struct mobj_s fixed_t scale; fixed_t destscale; fixed_t scalespeed; + fixed_t spritexscale, spriteyscale; // Extra values are for internal use for whatever you want INT32 extravalue1; diff --git a/src/p_saveg.c b/src/p_saveg.c index 4f6f31803..d613efd70 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1393,7 +1393,10 @@ typedef enum MD2_COLORIZED = 1<<12, MD2_MIRRORED = 1<<13, MD2_ROLLANGLE = 1<<14, - MD2_SHADOWSCALE = 1<<15, + MD2_SPRITEXSCALE = 1<<15, + MD2_SPRITEYSCALE = 1<<16, + MD2_SHADOWSCALE = 1<<17, + MD2_RENDERFLAGS = 1<<18, } mobj_diff2_t; typedef enum @@ -1604,8 +1607,14 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_MIRRORED; if (mobj->rollangle) diff2 |= MD2_ROLLANGLE; + if (mobj->spritexscale != FRACUNIT) + diff2 |= MD2_SPRITEXSCALE; + if (mobj->spriteyscale != FRACUNIT) + diff2 |= MD2_SPRITEYSCALE; if (mobj->shadowscale) diff2 |= MD2_SHADOWSCALE; + if (mobj->renderflags) + diff2 |= MD2_RENDERFLAGS; if (diff2 != 0) diff |= MD_MORE; @@ -1746,8 +1755,14 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, mobj->mirrored); if (diff2 & MD2_ROLLANGLE) WRITEANGLE(save_p, mobj->rollangle); + if (diff2 & MD2_SPRITEXSCALE) + WRITEFIXED(save_p, mobj->spritexscale); + if (diff2 & MD2_SPRITEYSCALE) + WRITEFIXED(save_p, mobj->spriteyscale); if (diff2 & MD2_SHADOWSCALE) WRITEFIXED(save_p, mobj->shadowscale); + if (diff2 & MD2_RENDERFLAGS) + WRITEUINT32(save_p, mobj->renderflags); WRITEUINT32(save_p, mobj->mobjnum); } @@ -2755,8 +2770,14 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->mirrored = READUINT8(save_p); if (diff2 & MD2_ROLLANGLE) mobj->rollangle = READANGLE(save_p); + if (diff2 & MD2_SPRITEXSCALE) + mobj->spritexscale = READFIXED(save_p); + if (diff2 & MD2_SPRITEYSCALE) + mobj->spriteyscale = READFIXED(save_p); if (diff2 & MD2_SHADOWSCALE) mobj->shadowscale = READFIXED(save_p); + if (diff2 & MD2_RENDERFLAGS) + mobj->renderflags = READUINT32(save_p); if (diff & MD_REDFLAG) { diff --git a/src/p_setup.c b/src/p_setup.c index 4dbb70e0c..349b0582d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1080,9 +1080,6 @@ static void P_InitializeLinedef(line_t *ld) ld->frontsector = ld->backsector = NULL; ld->validcount = 0; -#ifdef WALLSPLATS - ld->splats = NULL; -#endif ld->firsttag = ld->nexttag = -1; ld->polyobj = NULL; @@ -2081,9 +2078,6 @@ static boolean P_LoadMapData(const virtres_t *virt) static void P_InitializeSubsector(subsector_t *ss) { ss->sector = NULL; -#ifdef FLOORSPLATS - ss->splats = NULL; -#endif ss->validcount = 0; } @@ -2128,7 +2122,7 @@ static void P_LoadNodes(UINT8 *data) * \param seg Seg to compute length for. * \return Length in fracunits. */ -fixed_t P_SegLength(seg_t *seg) +static fixed_t P_SegLength(seg_t *seg) { INT64 dx = (seg->v2->x - seg->v1->x)>>1; INT64 dy = (seg->v2->y - seg->v1->y)>>1; @@ -4094,11 +4088,6 @@ boolean P_LoadLevel(boolean fromnetsave) Patch_FreeTag(PU_PATCH_ROTATED); Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); -#if defined (WALLSPLATS) || defined (FLOORSPLATS) - // clear the splats from previous level - R_ClearLevelSplats(); -#endif - P_InitThinkers(); P_InitCachedActions(); diff --git a/src/p_user.c b/src/p_user.c index 7bc45bfc4..0341128d5 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8678,12 +8678,6 @@ void P_MovePlayer(player_t *player) player->fovadd = 0; #endif -#ifdef FLOORSPLATS - if (cv_shadow.value && rendermode == render_soft) - R_AddFloorSplat(player->mo->subsector, player->mo, "SHADOW", player->mo->x, - player->mo->y, player->mo->floorz, SPLATDRAWMODE_OPAQUE); -#endif - // Look for blocks to bust up // Because of FF_SHATTER, we should look for blocks constantly, // not just when spinning or playing as Knuckles diff --git a/src/r_bsp.c b/src/r_bsp.c index a430ef040..d2c8e9f86 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -1048,11 +1048,6 @@ static void R_Subsector(size_t num) } } -#ifdef FLOORSPLATS - if (sub->splats) - R_AddVisibleFloorSplats(sub); -#endif - // killough 9/18/98: Fix underwater slowdown, by passing real sector // instead of fake one. Improve sprite lighting by basing sprite // lightlevels on floor & ceiling lightlevels in the surrounding area. diff --git a/src/r_defs.h b/src/r_defs.h index 4dfba0691..d32313a46 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -409,9 +409,6 @@ typedef struct line_s sector_t *backsector; size_t validcount; // if == validcount, already checked -#if 1//#ifdef WALLSPLATS - void *splats; // wallsplat_t list -#endif INT32 firsttag, nexttag; // improves searches for tags. polyobj_t *polyobj; // Belongs to a polyobject? @@ -457,9 +454,6 @@ typedef struct subsector_s INT16 numlines; UINT16 firstline; struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects -#if 1//#ifdef FLOORSPLATS - void *splats; // floorsplat_t list -#endif size_t validcount; } subsector_t; @@ -674,6 +668,7 @@ typedef struct UINT8 *columns; // Software column data void *hardware; // OpenGL patch, allocated whenever necessary + void *flats[4]; // The patch as flats #ifdef ROTSPRITE rotsprite_t *rotated; // Rotated patches @@ -718,6 +713,28 @@ typedef struct #pragma pack() #endif +typedef enum +{ + RF_HORIZONTALFLIP = 0x0001, // Flip sprite horizontally + RF_VERTICALFLIP = 0x0002, // Flip sprite vertically + RF_ONESIDED = 0x0004, // Wall/floor sprite is visible from front only + RF_NOSPLATBILLBOARD = 0x0008, // Don't billboard floor sprites (faces forward from the view angle) + RF_NOSPLATROLLANGLE = 0x0010, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead) + + RF_BLENDMASK = 0x0F00, // --Blending modes + RF_FULLBRIGHT = 0x0100, // Sprite is drawn at full brightness + RF_FULLDARK = 0x0200, // Sprite is drawn completely dark + + RF_SPRITETYPEMASK = 0x7000, // ---Different sprite types, not all implemented + RF_PAPERSPRITE = 0x1000, // Paper sprite + RF_FLOORSPRITE = 0x2000, // Floor sprite + RF_VOXELSPRITE = 0x3000, // Voxel object + + RF_SHADOWDRAW = 0x10000, // Stretches and skews the sprite like a shadow. + RF_SHADOWEFFECTS = 0x20000, // Scales and becomes transparent like a shadow. + RF_DROPSHADOW = (RF_SHADOWDRAW | RF_SHADOWEFFECTS | RF_FULLDARK), +} renderflags_t; + typedef enum { SRF_SINGLE = 0, // 0-angle for all rotations @@ -759,7 +776,7 @@ typedef struct UINT16 flip; #ifdef ROTSPRITE - rotsprite_t *rotated[16]; // Rotated patches + rotsprite_t *rotated[2][16]; // Rotated patches #endif } spriteframe_t; diff --git a/src/r_draw.c b/src/r_draw.c index 2b798c3bf..e10d6e399 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -98,6 +98,7 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight; INT32 ds_y, ds_x1, ds_x2; lighttable_t *ds_colormap; +lighttable_t *ds_translation; // Lactozilla: Sprite splat drawer fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; UINT16 ds_flatwidth, ds_flatheight; boolean ds_powersoftwo; diff --git a/src/r_draw.h b/src/r_draw.h index 1ca22f18a..d77bbedd3 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -56,6 +56,7 @@ extern INT32 dc_texheight; extern INT32 ds_y, ds_x1, ds_x2; extern lighttable_t *ds_colormap; +extern lighttable_t *ds_translation; extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; extern UINT16 ds_flatwidth, ds_flatheight; extern boolean ds_powersoftwo; @@ -151,8 +152,10 @@ void R_DrawColumnShadowed_8(void); void R_DrawSpan_8(void); void R_DrawSplat_8(void); +void R_DrawFloorSprite_8(void); void R_DrawTranslucentSpan_8(void); void R_DrawTranslucentSplat_8(void); +void R_DrawTranslucentFloorSprite_8(void); void R_DrawTiltedSpan_8(void); void R_DrawTiltedTranslucentSpan_8(void); #ifndef NOWATER @@ -171,8 +174,10 @@ void R_DrawFogSpan_8(void); // Lactozilla: Non-powers-of-two void R_DrawSpan_NPO2_8(void); void R_DrawTranslucentSpan_NPO2_8(void); +void R_DrawFloorSprite_NPO2_8(void); void R_DrawSplat_NPO2_8(void); void R_DrawTranslucentSplat_NPO2_8(void); +void R_DrawTranslucentFloorSprite_NPO2_8(void); void R_DrawTiltedSpan_NPO2_8(void); void R_DrawTiltedTranslucentSpan_NPO2_8(void); #ifndef NOWATER diff --git a/src/r_draw8.c b/src/r_draw8.c index 940ea724b..bc39e91a5 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1419,6 +1419,230 @@ void R_DrawTranslucentSplat_8 (void) } } +/** \brief The R_DrawFloorSprite_8 function + Just like R_DrawSplat_8, but for floor sprites. +*/ +void R_DrawFloorSprite_8 (void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + + UINT16 *source; + UINT8 *colormap; + UINT8 *translation; + 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; + + // 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 <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + + source = (UINT16 *)ds_source; + colormap = ds_colormap; + translation = ds_translation; + dest = ylookup[ds_y] + columnofs[ds_x1]; + + 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 & 0xFF00) + dest[0] = colormap[translation[val & 0xFF]]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val & 0xFF00) + dest[1] = colormap[translation[val & 0xFF]]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val & 0xFF00) + dest[2] = colormap[translation[val & 0xFF]]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val & 0xFF00) + dest[3] = colormap[translation[val & 0xFF]]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val & 0xFF00) + dest[4] = colormap[translation[val & 0xFF]]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val & 0xFF00) + dest[5] = colormap[translation[val & 0xFF]]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val & 0xFF00) + dest[6] = colormap[translation[val & 0xFF]]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val & 0xFF00) + dest[7] = colormap[translation[val & 0xFF]]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count-- && dest <= deststop) + { + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val & 0xFF00) + *dest = colormap[translation[val & 0xFF]]; + dest++; + xposition += xstep; + yposition += ystep; + } +} + +/** \brief The R_DrawTranslucentFloorSplat_8 function + Just like R_DrawFloorSprite_8, but is translucent! +*/ +void R_DrawTranslucentFloorSprite_8 (void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + + UINT16 *source; + UINT8 *colormap; + UINT8 *translation; + 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; + + // 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 <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + + source = (UINT16 *)ds_source; + colormap = ds_colormap; + translation = ds_translation; + dest = ylookup[ds_y] + columnofs[ds_x1]; + + 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 & 0xFF00) + dest[0] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val & 0xFF00) + dest[1] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val & 0xFF00) + dest[2] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val & 0xFF00) + dest[3] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val & 0xFF00) + dest[4] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val & 0xFF00) + dest[5] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val & 0xFF00) + dest[6] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val & 0xFF00) + dest[7] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 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 & 0xFF00) + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } +} + /** \brief The R_DrawTranslucentSpan_8 function Draws the actual span with translucency. */ diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 020155694..087a8d30c 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -754,6 +754,104 @@ void R_DrawTranslucentSplat_NPO2_8 (void) } } +/** \brief The R_DrawFloorSprite_NPO2_8 function + Just like R_DrawSplat_NPO2_8, but for floor sprites. +*/ +void R_DrawFloorSprite_NPO2_8 (void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + + UINT16 *source; + UINT8 *translation; + 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; + + source = (UINT16 *)ds_source; + colormap = ds_colormap; + translation = ds_translation; + dest = ylookup[ds_y] + columnofs[ds_x1]; + + 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; + + val = source[((y * ds_flatwidth) + x)]; + if (val & 0xFF00) + *dest = colormap[translation[val & 0xFF]]; + dest++; + xposition += xstep; + yposition += ystep; + } +} + +/** \brief The R_DrawTranslucentFloorSprite_NPO2_8 function + Just like R_DrawFloorSprite_NPO2_8, but is translucent! +*/ +void R_DrawTranslucentFloorSprite_NPO2_8 (void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + + UINT16 *source; + UINT8 *translation; + 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; + + source = (UINT16 *)ds_source; + colormap = ds_colormap; + translation = ds_translation; + dest = ylookup[ds_y] + columnofs[ds_x1]; + + 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; + + val = source[((y * ds_flatwidth) + x)]; + if (val & 0xFF00) + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } +} + /** \brief The R_DrawTranslucentSpan_NPO2_8 function Draws the actual span with translucency. */ diff --git a/src/r_main.c b/src/r_main.c index 3568e2116..03f9c6818 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1472,9 +1472,6 @@ void R_RenderPlayerView(player_t *player) } R_ClearDrawSegs(); R_ClearSprites(); -#ifdef FLOORSPLATS - R_ClearVisibleFloorSplats(); -#endif Portal_InitList(); // check for new console commands. @@ -1555,9 +1552,6 @@ void R_RenderPlayerView(player_t *player) rs_sw_planetime = I_GetTimeMicros(); R_DrawPlanes(); -#ifdef FLOORSPLATS - R_DrawVisibleFloorSplats(); -#endif rs_sw_planetime = I_GetTimeMicros() - rs_sw_planetime; // draw mid texture and sprite diff --git a/src/r_patch.c b/src/r_patch.c index 9ca04dd55..9b1e7d1b8 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -11,6 +11,7 @@ #include "doomdef.h" #include "r_patch.h" +#include "r_picformats.h" #include "r_defs.h" #include "z_zone.h" @@ -66,18 +67,25 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest) static void Patch_FreeData(patch_t *patch) { + INT32 i; + #ifdef HWRENDER if (patch->hardware) HWR_FreeTexture(patch); #endif + for (i = 0; i < 2; i++) + { + if (patch->flats[i]) + Patch_Free(patch->flats[i]); + } + #ifdef ROTSPRITE if (patch->rotated) { rotsprite_t *rotsprite = patch->rotated; - INT32 i = 0; - for (; i < rotsprite->angles; i++) + for (i = 0; i < rotsprite->angles; i++) { if (rotsprite->patches[i]) Patch_Free(rotsprite->patches[i]); @@ -116,6 +124,13 @@ void Patch_FreeTags(INT32 lowtag, INT32 hightag) Z_IterateTags(lowtag, hightag, Patch_FreeTagsCallback); } +void Patch_GenerateFlat(patch_t *patch, pictureflags_t flags) +{ + UINT8 flip = (flags & (PICFLAGS_XFLIP | PICFLAGS_YFLIP)); + if (patch->flats[flip] == NULL) + patch->flats[flip] = Picture_Convert(PICFMT_PATCH, patch, PICFMT_FLAT16, 0, NULL, 0, 0, 0, 0, flags); +} + #ifdef HWRENDER // // Allocates a hardware patch. diff --git a/src/r_patch.h b/src/r_patch.h index 6991d3637..32bcb3909 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -13,6 +13,7 @@ #define __R_PATCH__ #include "r_defs.h" +#include "r_picformats.h" #include "doomdef.h" // Patch functions @@ -22,6 +23,8 @@ void Patch_Free(patch_t *patch); #define Patch_FreeTag(tagnum) Patch_FreeTags(tagnum, tagnum) void Patch_FreeTags(INT32 lowtag, INT32 hightag); +void Patch_GenerateFlat(patch_t *patch, pictureflags_t flags); + #ifdef HWRENDER void *Patch_AllocateHardwarePatch(patch_t *patch); void *Patch_CreateGL(patch_t *patch); @@ -30,7 +33,12 @@ void *Patch_CreateGL(patch_t *patch); #ifdef ROTSPRITE void Patch_Rotate(patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip); patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip); -patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spriteangle, boolean flip, void *info, INT32 rotationangle);INT32 R_GetRollAngle(angle_t rollangle); +patch_t *Patch_GetRotatedSprite( + spriteframe_t *sprite, + size_t frame, size_t spriteangle, + boolean flip, boolean adjustfeet, + void *info, INT32 rotationangle); +INT32 R_GetRollAngle(angle_t rollangle); #endif #endif // __R_PATCH__ diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 98e3a7687..123c4eef2 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -41,19 +41,26 @@ patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip) return rotsprite->patches[angle]; } -patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spriteangle, boolean flip, void *info, INT32 rotationangle) +patch_t *Patch_GetRotatedSprite( + spriteframe_t *sprite, + size_t frame, size_t spriteangle, + boolean flip, boolean adjustfeet, + void *info, INT32 rotationangle) { - rotsprite_t *rotsprite = sprite->rotated[spriteangle]; + rotsprite_t *rotsprite; spriteinfo_t *sprinfo = (spriteinfo_t *)info; INT32 idx = rotationangle; + UINT8 type = (adjustfeet ? 1 : 0); if (rotationangle < 1 || rotationangle >= ROTANGLES) return NULL; + rotsprite = sprite->rotated[type][spriteangle]; + if (rotsprite == NULL) { rotsprite = RotatedPatch_Create(ROTANGLES); - sprite->rotated[spriteangle] = rotsprite; + sprite->rotated[type][spriteangle] = rotsprite; } if (flip) @@ -84,7 +91,8 @@ patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spri RotatedPatch_DoRotation(rotsprite, patch, rotationangle, xpivot, ypivot, flip); //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer - ((patch_t *)rotsprite->patches[idx])->topoffset += FEETADJUST>>FRACBITS; + if (adjustfeet) + ((patch_t *)rotsprite->patches[idx])->topoffset += FEETADJUST>>FRACBITS; } return rotsprite->patches[idx]; diff --git a/src/r_plane.c b/src/r_plane.c index 6c238896c..797919a9f 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -745,6 +745,7 @@ void R_DrawSinglePlane(visplane_t *pl) ffloor_t *rover; int type; int spanfunctype = BASEDRAWFUNC; + angle_t viewang = viewangle; if (!(pl->minx <= pl->maxx)) return; @@ -871,20 +872,6 @@ void R_DrawSinglePlane(visplane_t *pl) light = (pl->lightlevel >> LIGHTSEGSHIFT); } - if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later - && viewangle != pl->viewangle+pl->plangle) - { - memset(cachedheight, 0, sizeof (cachedheight)); - angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT; - basexscale = FixedDiv(FINECOSINE(angle),centerxfrac); - baseyscale = -FixedDiv(FINESINE(angle),centerxfrac); - viewangle = pl->viewangle+pl->plangle; - } - - xoffs = pl->xoffs; - yoffs = pl->yoffs; - planeheight = abs(pl->height - pl->viewz); - currentplane = pl; levelflat = &levelflats[pl->picnum]; @@ -909,6 +896,20 @@ void R_DrawSinglePlane(visplane_t *pl) R_CheckFlatLength(ds_flatwidth * ds_flatheight); } + if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later + && viewangle != pl->viewangle+pl->plangle) + { + memset(cachedheight, 0, sizeof (cachedheight)); + angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT; + basexscale = FixedDiv(FINECOSINE(angle),centerxfrac); + baseyscale = -FixedDiv(FINESINE(angle),centerxfrac); + viewangle = pl->viewangle+pl->plangle; + } + + xoffs = pl->xoffs; + yoffs = pl->yoffs; + planeheight = abs(pl->height - pl->viewz); + if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; @@ -1121,6 +1122,8 @@ using the palette colors. } } #endif + + viewangle = viewang; } void R_PlaneBounds(visplane_t *plane) diff --git a/src/r_segs.c b/src/r_segs.c index 177827892..77425d345 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -63,170 +63,6 @@ static lighttable_t **walllights; static INT16 *maskedtexturecol; static fixed_t *maskedtextureheight = NULL; -// ========================================================================== -// R_Splats Wall Splats Drawer -// ========================================================================== - -#ifdef WALLSPLATS -static INT16 last_ceilingclip[MAXVIDWIDTH]; -static INT16 last_floorclip[MAXVIDWIDTH]; - -static void R_DrawSplatColumn(column_t *column) -{ - INT32 topscreen, bottomscreen; - fixed_t basetexturemid; - INT32 topdelta, prevdelta = -1; - - basetexturemid = dc_texturemid; - - for (; column->topdelta != 0xff ;) - { - // calculate unclipped screen coordinates for post - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - topscreen = sprtopscreen + spryscale*topdelta; - bottomscreen = topscreen + spryscale*column->length; - - dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; - dc_yh = (bottomscreen-1)>>FRACBITS; - - if (dc_yh >= last_floorclip[dc_x]) - dc_yh = last_floorclip[dc_x] - 1; - if (dc_yl <= last_ceilingclip[dc_x]) - dc_yl = last_ceilingclip[dc_x] + 1; - if (dc_yl <= dc_yh && dl_yh < vid.height && yh > 0) - { - dc_source = (UINT8 *)column + 3; - dc_texturemid = basetexturemid - (topdelta<length + 4); - } - - dc_texturemid = basetexturemid; -} - -static void R_DrawWallSplats(void) -{ - wallsplat_t *splat; - seg_t *seg; - angle_t angle, angle1, angle2; - INT32 x1, x2; - size_t pindex; - column_t *col; - patch_t *patch; - fixed_t texturecolumn; - - splat = (wallsplat_t *)linedef->splats; - - I_Assert(splat != NULL); - - seg = ds_p->curline; - - // draw all splats from the line that touches the range of the seg - for (; splat; splat = splat->next) - { - angle1 = R_PointToAngle(splat->v1.x, splat->v1.y); - angle2 = R_PointToAngle(splat->v2.x, splat->v2.y); - angle1 = (angle1 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT; - angle2 = (angle2 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT; - // out of the viewangletox lut - /// \todo clip it to the screen - if (angle1 > FINEANGLES/2 || angle2 > FINEANGLES/2) - continue; - x1 = viewangletox[angle1]; - x2 = viewangletox[angle2]; - - if (x1 >= x2) - continue; // does not cross a pixel - - // splat is not in this seg range - if (x2 < ds_p->x1 || x1 > ds_p->x2) - continue; - - if (x1 < ds_p->x1) - x1 = ds_p->x1; - if (x2 > ds_p->x2) - x2 = ds_p->x2; - if (x2 <= x1) - continue; - - // calculate incremental stepping values for texture edges - rw_scalestep = ds_p->scalestep; - spryscale = ds_p->scale1 + (x1 - ds_p->x1)*rw_scalestep; - mfloorclip = floorclip; - mceilingclip = ceilingclip; - - patch = W_CachePatchNum(splat->patch, PU_PATCH); - - dc_texturemid = splat->top + (SHORT(patch->height)<<(FRACBITS-1)) - viewz; - if (splat->yoffset) - dc_texturemid += *splat->yoffset; - - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - - // set drawing mode - switch (splat->flags & SPLATDRAWMODE_MASK) - { - case SPLATDRAWMODE_OPAQUE: - colfunc = colfuncs[BASEDRAWFUNC]; - break; - case SPLATDRAWMODE_TRANS: - if (!cv_translucency.value) - colfunc = colfuncs[BASEDRAWFUNC]; - else - { - dc_transmap = transtables + ((tr_trans50 - 1)<>LIGHTSCALESHIFT; - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - dc_colormap = walllights[pindex]; - - if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = 0xffffffffu / (unsigned)spryscale; - - // find column of patch, from perspective - angle = (rw_centerangle + xtoviewangle[dc_x])>>ANGLETOFINESHIFT; - texturecolumn = rw_offset2 - splat->offset - - FixedMul(FINETANGENT(angle), rw_distance); - - // FIXME! - texturecolumn >>= FRACBITS; - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) - continue; - - // draw the texture - col = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - R_DrawSplatColumn(col); - } - } // next splat - - colfunc = colfuncs[BASEDRAWFUNC]; -} - -#endif //WALLSPLATS - // ========================================================================== // R_RenderMaskedSegRange // ========================================================================== @@ -2786,20 +2622,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) } } -#ifdef WALLSPLATS - if (linedef->splats && cv_splats.value) - { - // Isn't a bit wasteful to copy the ENTIRE array for every drawseg? - M_Memcpy(last_ceilingclip + ds_p->x1, ceilingclip + ds_p->x1, - sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1)); - M_Memcpy(last_floorclip + ds_p->x1, floorclip + ds_p->x1, - sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1)); - R_RenderSegLoop(); - R_DrawWallSplats(); - } - else -#endif - R_RenderSegLoop(); + R_RenderSegLoop(); colfunc = colfuncs[BASEDRAWFUNC]; if (portalline) // if curline is a portal, set portalrender for drawseg diff --git a/src/r_splats.c b/src/r_splats.c index dfec185a1..0b2826107 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -8,459 +8,253 @@ // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file r_splats.c -/// \brief floor and wall splats +/// \brief Floor splats #include "r_draw.h" #include "r_main.h" -#include "r_plane.h" #include "r_splats.h" +#include "r_bsp.h" #include "w_wad.h" #include "z_zone.h" -#include "d_netcmd.h" -#ifdef WALLSPLATS -static wallsplat_t wallsplats[MAXLEVELSPLATS]; // WALL splats -static INT32 freewallsplat; -#endif - -#ifdef USEASM -/// \brief for floorsplats \note accessed by asm code -struct rastery_s *prastertab; -#endif +struct rastery_s *prastertab; // for ASM code #ifdef FLOORSPLATS -static floorsplat_t floorsplats[1]; // FLOOR splats -static INT32 freefloorsplat; - -struct rastery_s -{ - fixed_t minx, maxx; // for each raster line starting at line 0 - fixed_t tx1, ty1; - fixed_t tx2, ty2; // start/end points in texture at this line -}; static struct rastery_s rastertab[MAXVIDHEIGHT]; - static void prepare_rastertab(void); -#endif -// -------------------------------------------------------------------------- -// setup splat cache -// -------------------------------------------------------------------------- -void R_ClearLevelSplats(void) -{ -#ifdef WALLSPLATS - freewallsplat = 0; - memset(wallsplats, 0, sizeof (wallsplats)); -#endif -#ifdef FLOORSPLATS - freefloorsplat = 0; - memset(floorsplats, 0, sizeof (floorsplats)); - - // setup to draw floorsplats - prastertab = rastertab; - prepare_rastertab(); -#endif -} - -// ========================================================================== -// WALL SPLATS -// ========================================================================== -#ifdef WALLSPLATS -// -------------------------------------------------------------------------- -// Return a pointer to a splat free for use, or NULL if no more splats are -// available -// -------------------------------------------------------------------------- -static wallsplat_t *R_AllocWallSplat(void) -{ - wallsplat_t *splat; - wallsplat_t *p_splat; - line_t *li; - - // clear the splat from the line if it was in use - splat = &wallsplats[freewallsplat]; - li = splat->line; - if (li) - { - // remove splat from line splats list - if (li->splats == splat) - li->splats = splat->next; // remove from head - else - { - I_Assert(li->splats != NULL); - for (p_splat = li->splats; p_splat->next; p_splat = p_splat->next) - if (p_splat->next == splat) - { - p_splat->next = splat->next; - break; - } - } - } - - memset(splat, 0, sizeof (wallsplat_t)); - - // for next allocation - freewallsplat++; - if (freewallsplat >= 20) - freewallsplat = 0; - - return splat; -} - -// Add a new splat to the linedef: -// top: top z coord -// wallfrac: frac along the linedef vector (0 to FRACUNIT) -// splatpatchname: name of patch to draw -void R_AddWallSplat(line_t *wallline, INT16 sectorside, const char *patchname, fixed_t top, - fixed_t wallfrac, INT32 flags) -{ - fixed_t fracsplat, linelength; - wallsplat_t *splat = NULL; - wallsplat_t *p_splat; - patch_t *patch; - sector_t *backsector = NULL; - - if (W_CheckNumForName(patchname) != LUMPERROR) - splat = R_AllocWallSplat(); - if (!splat) - return; - - // set the splat - splat->patch = W_GetNumForName(patchname); - sectorside ^= 1; - if (wallline->sidenum[sectorside] != 0xffff) - { - backsector = sides[wallline->sidenum[sectorside]].sector; - - if (top < backsector->floorheight) - { - splat->yoffset = &backsector->floorheight; - top -= backsector->floorheight; - } - else if (top > backsector->ceilingheight) - { - splat->yoffset = &backsector->ceilingheight; - top -= backsector->ceilingheight; - } - } - - splat->top = top; - splat->flags = flags; - - // bad.. but will be needed for drawing anyway.. - patch = W_CachePatchNum(splat->patch, PU_PATCH); - - // offset needed by draw code for texture mapping - linelength = P_SegLength((seg_t *)wallline); - splat->offset = FixedMul(wallfrac, linelength) - (SHORT(patch->width)<<(FRACBITS-1)); - fracsplat = FixedDiv(((SHORT(patch->width)<>1), linelength); - - wallfrac -= fracsplat; - if (wallfrac > linelength) - return; - splat->v1.x = wallline->v1->x + FixedMul(wallline->dx, wallfrac); - splat->v1.y = wallline->v1->y + FixedMul(wallline->dy, wallfrac); - wallfrac += fracsplat + fracsplat; - if (wallfrac < 0) - return; - splat->v2.x = wallline->v1->x + FixedMul(wallline->dx, wallfrac); - splat->v2.y = wallline->v1->y + FixedMul(wallline->dy, wallfrac); - - if (wallline->frontsector && wallline->frontsector == backsector) - return; - - // insert splat in the linedef splat list - // BP: why not insert in head is much more simple? - // BP: because for remove it is more simple! - splat->line = wallline; - splat->next = NULL; - if (wallline->splats) - { - p_splat = wallline->splats; - while (p_splat->next) - p_splat = p_splat->next; - p_splat->next = splat; - } - else - wallline->splats = splat; -} -#endif // WALLSPLATS +UINT8 ds_splatclip[MAXVIDWIDTH]; // ========================================================================== // FLOOR SPLATS // ========================================================================== -#ifdef FLOORSPLATS -// -------------------------------------------------------------------------- -// Return a pointer to a splat free for use, or NULL if no more splats are -// available -// -------------------------------------------------------------------------- -static floorsplat_t *R_AllocFloorSplat(void) +#ifdef USEASM +void ASMCALL rasterize_segment_tex_asm(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir); +#endif + +// Lactozilla +static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir) { - floorsplat_t *splat; - floorsplat_t *p_splat; - subsector_t *sub; - - // find splat to use - freefloorsplat++; - if (freefloorsplat >= 1) - freefloorsplat = 0; - - // clear the splat from the line if it was in use - splat = &floorsplats[freefloorsplat]; - sub = splat->subsector; - if (sub) +#ifdef USEASM + if (R_ASM) { - // remove splat from subsector splats list - if (sub->splats == splat) - sub->splats = splat->next; // remove from head + rasterize_segment_tex_asm(x1, y1, x2, y2, tv1, tv2, tc, dir); + return; + } + else +#endif + { + fixed_t xs, xe, count; + fixed_t dx0, dx1; + + if (y1 == y2) + return; + + if (y2 > y1) + { + count = (y2-y1)+1; + + dx0 = FixedDiv((x2-x1)<splats; - while (p_splat->next) + count = (y1-y2)+1; + + dx0 = FixedDiv((x1-x2)<next == splat) - p_splat->next = splat->next; + for (;;) + { + rastertab[y2].minx = xs; + rastertab[y2].tx1 = xe; + rastertab[y2].ty1 = tc; + + xs += dx0; + xe += dx1; + y2++; + + if (count-- < 1) break; + } + } + else + { + for (;;) + { + rastertab[y2].minx = xs; + rastertab[y2].tx1 = tc; + rastertab[y2].ty1 = xe; + + xs += dx0; + xe += dx1; + y2++; + + if (count-- < 1) break; + } } } } - - memset(splat, 0, sizeof (floorsplat_t)); - return splat; } -// -------------------------------------------------------------------------- -// Add a floor splat to the subsector -// -------------------------------------------------------------------------- -void R_AddFloorSplat(subsector_t *subsec, mobj_t *mobj, const char *picname, fixed_t x, fixed_t y, fixed_t z, - INT32 flags) -{ - floorsplat_t *splat = NULL; - floorsplat_t *p_splat; - INT32 size; - - if (W_CheckNumForName(picname) != LUMPERROR) - splat = R_AllocFloorSplat(); - if (!splat) - return; - - // set the splat - splat->pic = W_GetNumForName(picname); - splat->flags = flags; - splat->mobj = mobj; - - splat->z = z; - - size = W_LumpLength(splat->pic); - - switch (size) - { - case 4194304: // 2048x2048 lump - splat->size = 1024; - break; - case 1048576: // 1024x1024 lump - splat->size = 512; - break; - case 262144:// 512x512 lump - splat->size = 256; - break; - case 65536: // 256x256 lump - splat->size = 128; - break; - case 16384: // 128x128 lump - splat->size = 64; - break; - case 1024: // 32x32 lump - splat->size = 16; - break; - default: // 64x64 lump - splat->size = 32; - break; - } - - // 3--2 - // | | - // 0--1 - // - splat->verts[0].x = splat->verts[3].x = x - (splat->size<verts[2].x = splat->verts[1].x = x + ((splat->size-1)<verts[3].y = splat->verts[2].y = y + ((splat->size-1)<verts[0].y = splat->verts[1].y = y - (splat->size<subsector = subsec; - splat->next = NULL; - if (subsec->splats) - { - p_splat = subsec->splats; - while (p_splat->next) - p_splat = p_splat->next; - p_splat->next = splat; - } - else - subsec->splats = splat; -} - -// -------------------------------------------------------------------------- -// Before each frame being rendered, clear the visible floorsplats list -// -------------------------------------------------------------------------- -static floorsplat_t *visfloorsplats; - -void R_ClearVisibleFloorSplats(void) -{ - visfloorsplats = NULL; -} - -// -------------------------------------------------------------------------- -// Add a floorsplat to the visible floorsplats list, for the current frame -// -------------------------------------------------------------------------- -void R_AddVisibleFloorSplats(subsector_t *subsec) -{ - floorsplat_t *pSplat; - I_Assert(subsec->splats != NULL); - - pSplat = subsec->splats; - // the splat is not visible from below - // FIXME: depending on some flag in pSplat->flags, some splats may be visible from 2 sides - // (above/below) - if (pSplat->z < viewz) - { - pSplat->nextvis = visfloorsplats; - visfloorsplats = pSplat; - } - - while (pSplat->next) - { - pSplat = pSplat->next; - if (pSplat->z < viewz) - { - pSplat->nextvis = visfloorsplats; - visfloorsplats = pSplat; - } - } -} - -#ifdef USEASM -// tv1, tv2 = x/y qui varie dans la texture, tc = x/y qui est constant. -void ASMCALL rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, - INT32 tc, INT32 dir); -#endif - -// current test with floor tile -//#define FLOORSPLATSOLIDCOLOR - // -------------------------------------------------------------------------- // Rasterize the four edges of a floor splat polygon, // fill the polygon with linear interpolation, call span drawer for each // scan line // -------------------------------------------------------------------------- -static void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, UINT8 *pTex) +void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis) { // rasterizing - INT32 miny = vid.height + 1, maxy = 0, y, x1, ry1, x2, y2; - fixed_t offsetx, offsety; + INT32 miny = viewheight + 1, maxy = 0, y, x1, ry1, x2, y2, i; + fixed_t offsetx = 0, offsety = 0; + fixed_t step; -#ifdef FLOORSPLATSOLIDCOLOR - UINT8 *pDest; - INT32 tdx, tdy, ty, tx, x; -#else - lighttable_t **planezlight; fixed_t planeheight; + fixed_t xstep, ystep; angle_t angle, planecos, planesin; fixed_t distance, span; - size_t indexr; - INT32 light; -#endif - (void)pTex; - offsetx = pSplat->verts[0].x & ((pSplat->size << FRACBITS)-1); - offsety = pSplat->verts[0].y & ((pSplat->size << FRACBITS)-1); + int spanfunctype = SPANDRAWFUNC_SPRITE; + + prepare_rastertab(); + +#define RASTERPARAMS(vnum1, vnum2, tv1, tv2, tc, dir) \ + x1 = verts[vnum1].x; \ + ry1 = verts[vnum1].y; \ + x2 = verts[vnum2].x; \ + y2 = verts[vnum2].y; \ + if (y2 > ry1) \ + step = FixedDiv(x2-x1, y2-ry1+1); \ + else if (y2 == ry1) \ + step = 0; \ + else \ + step = FixedDiv(x2-x1, ry1-y2+1); \ + if (ry1 < 0) { \ + if (step) { \ + x1 <<= FRACBITS; \ + x1 += (-ry1)*step; \ + x1 >>= FRACBITS; \ + } \ + ry1 = 0; \ + } \ + if (ry1 >= vid.height) { \ + if (step) { \ + x1 <<= FRACBITS; \ + x1 -= (vid.height-1-ry1)*step; \ + x1 >>= FRACBITS; \ + } \ + ry1 = vid.height - 1; \ + } \ + if (y2 < 0) { \ + if (step) { \ + x2 <<= FRACBITS; \ + x2 -= (-y2)*step; \ + x2 >>= FRACBITS; \ + } \ + y2 = 0; \ + } \ + if (y2 >= vid.height) { \ + if (step) { \ + x2 <<= FRACBITS; \ + x2 += (vid.height-1-y2)*step; \ + x2 >>= FRACBITS; \ + } \ + y2 = vid.height - 1; \ + } \ + rasterize_segment_tex(x1, ry1, x2, y2, tv1, tv2, tc, dir); \ + if (ry1 < miny) \ + miny = ry1; \ + if (ry1 > maxy) \ + maxy = ry1; // do segment a -> top of texture - x1 = verts[3].x; - ry1 = verts[3].y; - x2 = verts[2].x; - y2 = verts[2].y; - if (ry1 < 0) - ry1 = 0; - if (ry1 >= vid.height) - ry1 = vid.height - 1; - if (y2 < 0) - y2 = 0; - if (y2 >= vid.height) - y2 = vid.height - 1; - rasterize_segment_tex(x1, ry1, x2, y2, 0, pSplat->size - 1, 0, 0); - if (ry1 < miny) - miny = ry1; - if (ry1 > maxy) - maxy = ry1; - + RASTERPARAMS(3,2,0,pSplat->width-1,0,0); // do segment b -> right side of texture - x1 = x2; - ry1 = y2; - x2 = verts[1].x; - y2 = verts[1].y; - if (ry1 < 0) - ry1 = 0; - if (ry1 >= vid.height) - ry1 = vid.height - 1; - if (y2 < 0) - y2 = 0; - if (y2 >= vid.height) - y2 = vid.height - 1; - rasterize_segment_tex(x1, ry1, x2, y2, 0, pSplat->size - 1, pSplat->size - 1, 1); - if (ry1 < miny) - miny = ry1; - if (ry1 > maxy) - maxy = ry1; - + RASTERPARAMS(2,1,0,pSplat->width-1,pSplat->height-1,0); // do segment c -> bottom of texture - x1 = x2; - ry1 = y2; - x2 = verts[0].x; - y2 = verts[0].y; - if (ry1 < 0) - ry1 = 0; - if (ry1 >= vid.height) - ry1 = vid.height - 1; - if (y2 < 0) - y2 = 0; - if (y2 >= vid.height) - y2 = vid.height - 1; - rasterize_segment_tex(x1, ry1, x2, y2, pSplat->size - 1, 0, pSplat->size - 1, 0); - if (ry1 < miny) - miny = ry1; - if (ry1 > maxy) - maxy = ry1; - + RASTERPARAMS(1,0,pSplat->width-1,0,pSplat->height-1,0); // do segment d -> left side of texture - x1 = x2; - ry1 = y2; - x2 = verts[3].x; - y2 = verts[3].y; - if (ry1 < 0) - ry1 = 0; - if (ry1 >= vid.height) - ry1 = vid.height - 1; - if (y2 < 0) - y2 = 0; - if (y2 >= vid.height) - y2 = vid.height - 1; - rasterize_segment_tex(x1, ry1, x2, y2, pSplat->size - 1, 0, 0, 1); - if (ry1 < miny) - miny = ry1; - if (ry1 > maxy) - maxy = ry1; + RASTERPARAMS(0,3,pSplat->width-1,0,0,1); + + ds_source = pSplat->pic; + ds_flatwidth = pSplat->width; + ds_flatheight = pSplat->height; + + if (R_CheckPowersOfTwo()) + R_CheckFlatLength(ds_flatwidth * ds_flatheight); + + ds_transmap = NULL; + + if (vis->transmap) + { + ds_transmap = vis->transmap; + spanfunctype = SPANDRAWFUNC_TRANSSPRITE; + } + + if (ds_powersoftwo) + spanfunc = spanfuncs[spanfunctype]; + else + spanfunc = spanfuncs_npo2[spanfunctype]; + + if (pSplat->angle) + { + memset(cachedheight, 0, sizeof(cachedheight)); + angle = (viewangle + pSplat->angle - ANGLE_90) >> ANGLETOFINESHIFT; + basexscale = FixedDiv(FINECOSINE(angle), centerxfrac); + baseyscale = -FixedDiv(FINESINE(angle), centerxfrac); + } + else + { + angle = (viewangle - ANGLE_90) >> ANGLETOFINESHIFT; + basexscale = FixedDiv(FINECOSINE(angle), centerxfrac); + baseyscale = -FixedDiv(FINESINE(angle), centerxfrac); + } -#ifndef FLOORSPLATSOLIDCOLOR - // prepare values for all the splat - ds_source = W_CacheLumpNum(pSplat->pic, PU_CACHE); planeheight = abs(pSplat->z - viewz); - light = (pSplat->subsector->sector->lightlevel >> LIGHTSEGSHIFT); - if (light >= LIGHTLEVELS) - light = LIGHTLEVELS - 1; - if (light < 0) - light = 0; - planezlight = zlight[light]; + + if (maxy >= vid.height) + maxy = vid.height-1; for (y = miny; y <= maxy; y++) { @@ -472,7 +266,7 @@ static void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, UINT8 *pTe if (x2 >= vid.width) x2 = vid.width - 1; - angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT; + angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT; planecos = FINECOSINE(angle); planesin = FINESINE(angle); @@ -480,146 +274,115 @@ static void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, UINT8 *pTe { cachedheight[y] = planeheight; distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); - ds_xstep = cachedxstep[y] = FixedMul(distance,basexscale); - ds_ystep = cachedystep[y] = FixedMul(distance,baseyscale); - + xstep = cachedxstep[y] = FixedMul(distance, basexscale); + ystep = cachedystep[y] = FixedMul(distance, baseyscale); + // don't divide by zero if ((span = abs(centery-y))) { - ds_xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span; - ds_ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span; + xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span; + ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span; } } else { distance = cacheddistance[y]; - ds_xstep = cachedxstep[y]; - ds_ystep = cachedystep[y]; + xstep = cachedxstep[y]; + ystep = cachedystep[y]; } - ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; - ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; - ds_xfrac -= offsetx; - ds_yfrac += offsety; + ds_xstep = FixedDiv(xstep, pSplat->xscale); + ds_ystep = FixedDiv(ystep, pSplat->yscale); - indexr = distance >> LIGHTZSHIFT; - if (indexr >= MAXLIGHTZ) - indexr = MAXLIGHTZ - 1; - ds_colormap = planezlight[indexr]; + ds_colormap = vis->colormap; + ds_translation = R_GetSpriteTranslation(vis); + if (ds_translation == NULL) + ds_translation = colormaps; - ds_y = y; - if (x2 >= x1) // sanity check + if (vis->extra_colormap) { - ds_x1 = x1; - ds_x2 = x2; - ds_transmap = transtables + ((tr_trans50-1)<extra_colormap->colormap; + else + ds_colormap = &vis->extra_colormap->colormap[ds_colormap - colormaps]; } - // reset for next calls to edge rasterizer - rastertab[y].minx = INT32_MAX; - rastertab[y].maxx = INT32_MIN; - } - -#else - for (y = miny; y <= maxy; y++) - { - x1 = rastertab[y].minx>>FRACBITS; - x2 = rastertab[y].maxx>>FRACBITS; - if (x1 < 0) - x1 = 0; - if (x2 >= vid.width) - x2 = vid.width - 1; - -// pDest = ylookup[y] + columnofs[x1]; - pDest = &topleft[y*vid.width + x1]; - - x = x2 - x1 + 1; - - // starting point of the texture - tx = rastertab[y].tx1; - ty = rastertab[y].ty1; - - // HORRIBLE BUG!!! - if (x > 0) + if (pSplat->angle) { - tdx = (rastertab[y].tx2 - tx) / x; - tdy = (rastertab[y].ty2 - ty) / x; + // Add the view offset, rotated by the plane angle. + fixed_t a = -pSplat->verts[0].x + viewx; + fixed_t b = -pSplat->verts[0].y + viewy; + angle = (pSplat->angle >> ANGLETOFINESHIFT); + offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b,FINESINE(angle)); + offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b,FINECOSINE(angle)); + } + else + { + offsetx = viewx - pSplat->verts[0].x; + offsety = pSplat->verts[0].y - viewy; + } - while (x-- > 0) + if (vis != NULL) + { + INT32 xclip; + + mfloorclip = vis->clipbot; + mceilingclip = vis->cliptop; + + R_ClipVisSprite(vis, x1-1, x2+1, drawsegs, NULL); + memset(ds_splatclip, 0, sizeof(ds_splatclip)); + + if (x2 >= x1 && x1 < viewwidth && x1 >= 0) { - *(pDest++) = (UINT8)(y&1); - tx += tdx; - ty += tdy; + for (xclip = x1; xclip <= x2; xclip++) + { + if (y >= mfloorclip[xclip]) + ds_splatclip[xclip] = 1; + } + } + + while (ds_splatclip[x1]) + x1++; + i = x2; + while (i > x1) + { + if (ds_splatclip[i]) + x2 = i-1; + i--; } } - // reinitialise the minimum and maximum for the next approach + ds_xfrac = FixedDiv(offsetx + FixedMul(planecos, distance) + (x1 - centerx) * xstep, pSplat->xscale); + ds_yfrac = FixedDiv(offsety - FixedMul(planesin, distance) + (x1 - centerx) * ystep, pSplat->yscale); + + if (x2 >= x1) + { + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + spanfunc(); + } + rastertab[y].minx = INT32_MAX; rastertab[y].maxx = INT32_MIN; } -#endif -} -// -------------------------------------------------------------------------- -// R_DrawVisibleFloorSplats -// draw the flat floor/ceiling splats -// -------------------------------------------------------------------------- -void R_DrawVisibleFloorSplats(void) -{ - floorsplat_t *pSplat; - INT32 iCount = 0, i; - fixed_t tr_x, tr_y, rot_x, rot_y, rot_z, xscale, yscale; - vertex_t *v3d; - vertex_t v2d[4]; - - pSplat = visfloorsplats; - while (pSplat) + if (pSplat->angle) { - iCount++; - - // Draw a floor splat - // 3--2 - // | | - // 0--1 - - rot_z = pSplat->z - viewz; - for (i = 0; i < 4; i++) - { - v3d = &pSplat->verts[i]; - - // transform the origin point - tr_x = v3d->x - viewx; - tr_y = v3d->y - viewy; - - // rotation around vertical y axis - rot_x = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); - rot_y = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); - - if (rot_y < 4*FRACUNIT) - goto skipit; - - // note: y from view above of map, is distance far away - xscale = FixedDiv(projection, rot_y); - yscale = -FixedDiv(projectiony, rot_y); - - // projection - v2d[i].x = (centerxfrac + FixedMul (rot_x, xscale))>>FRACBITS; - v2d[i].y = (centeryfrac + FixedMul (rot_z, yscale))>>FRACBITS; - } - - R_RenderFloorSplat(pSplat, v2d, NULL); -skipit: - pSplat = pSplat->nextvis; + memset(cachedheight, 0, sizeof(cachedheight)); + angle = (viewangle - ANGLE_90) >> ANGLETOFINESHIFT; + basexscale = FixedDiv(FINECOSINE(angle), centerxfrac); + baseyscale = -FixedDiv(FINESINE(angle), centerxfrac); } } static void prepare_rastertab(void) { - INT32 iLine; - for (iLine = 0; iLine < vid.height; iLine++) + INT32 i; + prastertab = rastertab; + for (i = 0; i < vid.height; i++) { - rastertab[iLine].minx = INT32_MAX; - rastertab[iLine].maxx = INT32_MIN; + rastertab[i].minx = INT32_MAX; + rastertab[i].maxx = INT32_MIN; } } diff --git a/src/r_splats.h b/src/r_splats.h index 4ad893abb..9c01084cf 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -14,68 +14,35 @@ #define __R_SPLATS_H__ #include "r_defs.h" - -//#define WALLSPLATS // comment this out to compile without splat effects -/*#ifdef USEASM -#define FLOORSPLATS -#endif*/ - -#define MAXLEVELSPLATS 1024 - -// splat flags -#define SPLATDRAWMODE_MASK 0x03 // mask to get drawmode from flags -#define SPLATDRAWMODE_OPAQUE 0x00 -#define SPLATDRAWMODE_SHADE 0x01 -#define SPLATDRAWMODE_TRANS 0x02 +#include "r_things.h" // ========================================================================== // DEFINITIONS // ========================================================================== -// WALL SPLATS are patches drawn on top of wall segs -typedef struct wallsplat_s +struct rastery_s { - lumpnum_t patch; // lump id. - vertex_t v1, v2; // vertices along the linedef - fixed_t top; - fixed_t offset; // offset in columns<cut & SC_PRECIP) + && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) + && (vis->mobj->flags2 & MF2_FRET) + && !(vis->mobj->flags & MF_GRENADEBOUNCE) + && (leveltime & 1)); +} + +UINT8 *R_GetSpriteTranslation(vissprite_t *vis) +{ + if (R_SpriteIsFlashing(vis)) // Bosses "flash" + { + if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) + return R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); + else if (vis->mobj->type == MT_METALSONIC_BATTLE) + return R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); + else + return R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); + } + else if (vis->mobj->color && vis->transmap) // Color mapping + { + if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) + return R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + else if (!(vis->cut & SC_PRECIP) + && vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD + && (vis->mobj->player->charflags & SF_DASHMODE) + && ((leveltime/2) & 1)) + { + if (vis->mobj->player->charflags & SF_MACHINE) + return R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); + else + return R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + } + else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> + { + size_t skinnum = (skin_t*)vis->mobj->skin-skins; + return R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); + } + else // Use the defaults + return R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); + } + else if (vis->mobj->color) + { + // New colormap stuff for skins Tails 06-07-2002 + if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) + return R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + else if (!(vis->cut & SC_PRECIP) + && vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD + && (vis->mobj->player->charflags & SF_DASHMODE) + && ((leveltime/2) & 1)) + { + if (vis->mobj->player->charflags & SF_MACHINE) + return R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); + else + return R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + } + else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! + { + size_t skinnum = (skin_t*)vis->mobj->skin-skins; + return R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); + } + else // Use the defaults + return R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); + } + else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome. + return R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE); + + return NULL; +} + // // R_DrawVisSprite // mfloorclip and mceilingclip should also be set. @@ -770,77 +845,24 @@ static void R_DrawVisSprite(vissprite_t *vis) colfunc = colfuncs[BASEDRAWFUNC]; // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; - if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" - { - // translate certain pixels to white - colfunc = colfuncs[COLDRAWFUNC_TRANS]; - if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) - dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); - else if (vis->mobj->type == MT_METALSONIC_BATTLE) - dc_translation = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); - else - dc_translation = R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); - } + dc_translation = R_GetSpriteTranslation(vis); + + if (R_SpriteIsFlashing(vis)) // Bosses "flash" + colfunc = colfuncs[COLDRAWFUNC_TRANS]; // translate certain pixels to white else if (vis->mobj->color && vis->transmap) // Color mapping { colfunc = colfuncs[COLDRAWFUNC_TRANSTRANS]; dc_transmap = vis->transmap; - if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) - dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - else if (!(vis->cut & SC_PRECIP) - && vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD - && (vis->mobj->player->charflags & SF_DASHMODE) - && ((leveltime/2) & 1)) - { - if (vis->mobj->player->charflags & SF_MACHINE) - dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); - else - dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - } - else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> - { - size_t skinnum = (skin_t*)vis->mobj->skin-skins; - dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); - } - else // Use the defaults - dc_translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); } else if (vis->transmap) { colfunc = colfuncs[COLDRAWFUNC_FUZZY]; dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table } - else if (vis->mobj->color) - { - // translate green skin to another color + else if (vis->mobj->color) // translate green skin to another color colfunc = colfuncs[COLDRAWFUNC_TRANS]; - - // New colormap stuff for skins Tails 06-07-2002 - if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) - dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - else if (!(vis->cut & SC_PRECIP) - && vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD - && (vis->mobj->player->charflags & SF_DASHMODE) - && ((leveltime/2) & 1)) - { - if (vis->mobj->player->charflags & SF_MACHINE) - dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); - else - dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - } - else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! - { - size_t skinnum = (skin_t*)vis->mobj->skin-skins; - dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); - } - else // Use the defaults - dc_translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); - } else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome. - { colfunc = colfuncs[COLDRAWFUNC_TRANS]; - dc_translation = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE); - } if (vis->extra_colormap) { @@ -923,6 +945,28 @@ static void R_DrawVisSprite(vissprite_t *vis) localcolfunc (column); } } + else if (vis->cut & SC_SHEAR) + { +#ifdef RANGECHECK + pwidth = SHORT(patch->width); +#endif + + // Vertically sheared sprite + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, dc_texturemid -= vis->shear.tan) + { +#ifdef RANGECHECK + texturecolumn = frac>>FRACBITS; + if (texturecolumn < 0 || texturecolumn >= pwidth) + I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); +#else + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); +#endif + + sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); + localcolfunc (column); + } + } else { #ifdef RANGECHECK @@ -1217,6 +1261,29 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) #undef CHECKZ } +static void R_SkewShadowSprite( + mobj_t *thing, pslope_t *groundslope, + fixed_t groundz, INT32 spriteheight, fixed_t scalemul, + fixed_t *shadowyscale, fixed_t *shadowskew) +{ + // haha let's try some dumb stuff + fixed_t xslope, zslope; + angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - groundslope->xydirection) >> ANGLETOFINESHIFT; + + xslope = FixedMul(FINESINE(sloperelang), groundslope->zdelta); + zslope = FixedMul(FINECOSINE(sloperelang), groundslope->zdelta); + + //CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope); + + if (viewz < groundz) + *shadowyscale += FixedMul(FixedMul(thing->radius*2 / spriteheight, scalemul), zslope); + else + *shadowyscale -= FixedMul(FixedMul(thing->radius*2 / spriteheight, scalemul), zslope); + + *shadowyscale = abs((*shadowyscale)); + *shadowskew = xslope; +} + static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz) { vissprite_t *shadow; @@ -1245,40 +1312,22 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, yscale = FixedDiv(projectiony, tz); shadowxscale = FixedMul(thing->radius*2, scalemul); shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz)); - shadowyscale = min(shadowyscale, shadowxscale) / SHORT(patch->height); - shadowxscale /= SHORT(patch->width); + shadowyscale = min(shadowyscale, shadowxscale) / patch->height; + shadowxscale /= patch->width; shadowskew = 0; if (groundslope) - { - // haha let's try some dumb stuff - fixed_t xslope, zslope; - angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - groundslope->xydirection) >> ANGLETOFINESHIFT; + R_SkewShadowSprite(thing, groundslope, groundz, patch->height, scalemul, &shadowyscale, &shadowskew); - xslope = FixedMul(FINESINE(sloperelang), groundslope->zdelta); - zslope = FixedMul(FINECOSINE(sloperelang), groundslope->zdelta); - - //CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope); - - if (viewz < groundz) - shadowyscale += FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope); - else - shadowyscale -= FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope); - - shadowyscale = abs(shadowyscale); - - shadowskew = xslope; - } - - tx -= SHORT(patch->width) * shadowxscale/2; + tx -= patch->width * shadowxscale/2; x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; if (x1 >= viewwidth) return; - tx += SHORT(patch->width) * shadowxscale; + tx += patch->width * shadowxscale; x2 = ((centerxfrac + FixedMul(tx,xscale))>>FRACBITS); x2--; if (x2 < 0 || x2 <= x1) return; - if (shadowyscale < FRACUNIT/SHORT(patch->height)) return; // fix some crashes? + if (shadowyscale < FRACUNIT/patch->height) return; // fix some crashes? shadow = R_NewVisSprite(); shadow->patch = patch; @@ -1293,8 +1342,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, shadow->dispoffset = vis->dispoffset - 5; shadow->gx = thing->x; shadow->gy = thing->y; - shadow->gzt = (isflipped ? shadow->pzt : shadow->pz) + SHORT(patch->height) * shadowyscale / 2; - shadow->gz = shadow->gzt - SHORT(patch->height) * shadowyscale; + shadow->gzt = (isflipped ? shadow->pzt : shadow->pz) + patch->height * shadowyscale / 2; + shadow->gz = shadow->gzt - patch->height * shadowyscale; shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) shadow->texturemid = FixedMul(shadow->texturemid, ((skin_t *)thing->skin)->highresscale); @@ -1315,7 +1364,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, shadow->startfrac = 0; //shadow->xiscale = 0x7ffffff0 / (shadow->xscale/2); - shadow->xiscale = (SHORT(patch->width)<xiscale = (patch->width<x1 > x1) shadow->startfrac += shadow->xiscale*(shadow->x1-x1); @@ -1374,13 +1423,15 @@ static void R_ProjectSprite(mobj_t *thing) size_t frame, rot; UINT16 flip; - boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); + boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !R_ThingVerticallyFlipped(thing)); boolean mirrored = thing->mirrored; - boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored); + boolean hflip = (!R_ThingHorizontallyFlipped(thing) != !mirrored); INT32 lindex; + INT32 trans; vissprite_t *vis; + patch_t *patch; spritecut_e cut = SC_NONE; @@ -1389,10 +1440,15 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t scalestep; fixed_t offset, offset2; + fixed_t sheartan = 0; + fixed_t shadowscale = FRACUNIT; fixed_t basetx; // drop shadows - boolean papersprite = !!(thing->frame & FF_PAPERSPRITE); - fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; + boolean shadowdraw, shadoweffects, shadowskew; + boolean splat = R_ThingIsFloorSprite(thing); + boolean papersprite = (R_ThingIsPaperSprite(thing) && !splat); + fixed_t paperoffset = 0, paperdistance = 0; + angle_t centerangle = 0; INT32 dispoffset = thing->info->dispoffset; @@ -1401,10 +1457,12 @@ static void R_ProjectSprite(mobj_t *thing) INT32 heightsec, phs; INT32 light = 0; fixed_t this_scale = thing->scale; + fixed_t spritexscale, spriteyscale; // rotsprite fixed_t spr_width, spr_height; fixed_t spr_offset, spr_topoffset; + #ifdef ROTSPRITE patch_t *rotsprite = NULL; INT32 rollangle = 0; @@ -1533,17 +1591,28 @@ static void R_ProjectSprite(mobj_t *thing) spr_offset = spritecachedinfo[lump].offset; spr_topoffset = spritecachedinfo[lump].topoffset; + //Fab: lumppat is the lump number of the patch to use, this is different + // than lumpid for sprites-in-pwad : the graphics are patched + patch = W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); + #ifdef ROTSPRITE - if (thing->rollangle) + if (thing->rollangle + && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { rollangle = R_GetRollAngle(thing->rollangle); - rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, sprinfo, rollangle); + rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); + if (rotsprite != NULL) { - spr_width = SHORT(rotsprite->width) << FRACBITS; - spr_height = SHORT(rotsprite->height) << FRACBITS; - spr_offset = SHORT(rotsprite->leftoffset) << FRACBITS; - spr_topoffset = SHORT(rotsprite->topoffset) << FRACBITS; + patch = rotsprite; + cut |= SC_ISROTATED; + + spr_width = rotsprite->width << FRACBITS; + spr_height = rotsprite->height << FRACBITS; + spr_offset = rotsprite->leftoffset << FRACBITS; + spr_topoffset = rotsprite->topoffset << FRACBITS; + spr_topoffset += FEETADJUST; + // flip -> rotate, not rotate -> flip flip = 0; } @@ -1553,12 +1622,18 @@ static void R_ProjectSprite(mobj_t *thing) flip = !flip != !hflip; // calculate edges of the shape + spritexscale = thing->spritexscale; + spriteyscale = thing->spriteyscale; + if (spritexscale < 1 || spriteyscale < 1) + return; + if (flip) offset = spr_offset - spr_width; else offset = -spr_offset; - offset = FixedMul(offset, this_scale); - offset2 = FixedMul(spr_width, this_scale); + + offset = FixedMul(offset, FixedMul(spritexscale, this_scale)); + offset2 = FixedMul(spr_width, FixedMul(spritexscale, this_scale)); if (papersprite) { @@ -1686,7 +1761,7 @@ static void R_ProjectSprite(mobj_t *thing) dispoffset *= -1; // if it's physically behind, make sure it's ordered behind (if dispoffset > 0) sortscale = linkscale; // now make sure it's linked - cut = SC_LINKDRAW; + cut |= SC_LINKDRAW; } // PORTAL SPRITE CLIPPING @@ -1699,19 +1774,87 @@ static void R_ProjectSprite(mobj_t *thing) return; } - //SoM: 3/17/2000: Disregard sprites that are out of view.. - if (vflip) - { - // When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned. - // sprite height - sprite topoffset is the proper inverse of the vertical offset, of course. - // remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes! - gz = oldthing->z + oldthing->height - FixedMul(spr_topoffset, this_scale); - gzt = gz + FixedMul(spr_height, this_scale); - } + // Determine the translucency value. + if (oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) + trans = tr_trans80; // because now the translucency is set through FF_TRANSMASK + else if (oldthing->frame & FF_TRANSMASK) + trans = (oldthing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; else + trans = 0; + + // Check if this sprite needs to be rendered like a shadow + shadowdraw = (!!(thing->renderflags & RF_SHADOWDRAW) && !(papersprite || splat)); + shadoweffects = (thing->renderflags & RF_SHADOWEFFECTS); + shadowskew = (shadowdraw && thing->standingslope); + + if (shadowdraw || shadoweffects) { - gzt = oldthing->z + FixedMul(spr_topoffset, this_scale); - gz = gzt - FixedMul(spr_height, this_scale); + fixed_t groundz = R_GetShadowZ(thing, NULL); + boolean isflipped = (thing->eflags & MFE_VERTICALFLIP); + + if (shadoweffects) + { + mobj_t *caster = thing->target; + + if (caster && !P_MobjWasRemoved(caster)) + { + fixed_t floordiff; + + if (abs(groundz-viewz)/tz > 4) + return; // Prevent stretchy shadows and possible crashes + + floordiff = abs((isflipped ? caster->height : 0) + caster->z - groundz); + trans += ((floordiff / (100*FRACUNIT)) + 3); + shadowscale = FixedMul(FRACUNIT - floordiff/640, caster->scale); + } + else + trans += 3; + + if (trans >= 9) + return; + + trans--; + } + + if (shadowdraw) + { + spritexscale = FixedMul(thing->radius * 2, shadowscale); + spriteyscale = FixedMul(thing->radius * 2, shadowscale); + spriteyscale = FixedMul(spriteyscale, FixedDiv(abs(groundz - viewz), tz)); + spriteyscale = min(spriteyscale, spritexscale) / patch->height; + } + else + spritexscale = spriteyscale = shadowscale; + + spritexscale /= patch->width; + + if (shadowskew) + { + R_SkewShadowSprite(thing, thing->standingslope, groundz, patch->height, shadowscale, &spriteyscale, &sheartan); + + gzt = (isflipped ? (thing->z + thing->height) : thing->z) + patch->height * spriteyscale / 2; + gz = gzt - patch->height * spriteyscale; + + cut |= SC_SHEAR; + } + } + + if (!shadowskew) + { + //SoM: 3/17/2000: Disregard sprites that are out of view.. + if (vflip) + { + // When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned. + // sprite height - sprite topoffset is the proper inverse of the vertical offset, of course. + // remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes! + gz = oldthing->z + oldthing->height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); + gzt = gz + FixedMul(spr_height, FixedMul(spriteyscale, this_scale)); + } + else + { + gzt = oldthing->z + FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); + gz = gzt - FixedMul(spr_height, FixedMul(spriteyscale, this_scale)); + } } if (thing->subsector->sector->cullheight) @@ -1764,9 +1907,10 @@ static void R_ProjectSprite(mobj_t *thing) // store information in a vissprite vis = R_NewVisSprite(); + vis->renderflags = thing->renderflags; + vis->rotateflags = sprframe->rotate; vis->heightsec = heightsec; //SoM: 3/17/2000 vis->mobjflags = thing->flags; - vis->scale = yscale; //<sortscale = sortscale; vis->dispoffset = dispoffset; // Monster Iestyn: 23/11/15 vis->gx = thing->x; @@ -1776,12 +1920,12 @@ static void R_ProjectSprite(mobj_t *thing) vis->thingheight = thing->height; vis->pz = thing->z; vis->pzt = vis->pz + vis->thingheight; - vis->texturemid = vis->gzt - viewz; + vis->texturemid = FixedDiv(gzt - viewz, spriteyscale); vis->scalestep = scalestep; vis->paperoffset = paperoffset; vis->paperdistance = paperdistance; vis->centerangle = centerangle; - vis->shear.tan = 0; + vis->shear.tan = sheartan; vis->shear.offset = 0; vis->mobj = thing; // Easy access! Tails 06-07-2002 @@ -1789,17 +1933,28 @@ static void R_ProjectSprite(mobj_t *thing) vis->x1 = x1 < portalclipstart ? portalclipstart : x1; vis->x2 = x2 >= portalclipend ? portalclipend-1 : x2; - vis->xscale = xscale; //SoM: 4/17/2000 vis->sector = thing->subsector->sector; vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, sortscale))>>FRACBITS); vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, sortscale))>>FRACBITS); vis->cut = cut; + if (thing->subsector->sector->numlights) vis->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap; else vis->extra_colormap = thing->subsector->sector->extra_colormap; - iscale = FixedDiv(FRACUNIT, xscale); + vis->xscale = FixedMul(spritexscale, xscale); //SoM: 4/17/2000 + vis->scale = FixedMul(spriteyscale, yscale); //<width<shear.offset = vis->x1-x1; + vis->shadowscale = shadowscale; + } + else + iscale = FixedDiv(FRACUNIT, vis->xscale); if (flip) { @@ -1818,14 +1973,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->scale += scalestep*(vis->x1 - x1); } - //Fab: lumppat is the lump number of the patch to use, this is different - // than lumpid for sprites-in-pwad : the graphics are patched -#ifdef ROTSPRITE - if (rotsprite != NULL) - vis->patch = rotsprite; - else -#endif - vis->patch = W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); + vis->patch = patch; // // determine the colormap (lightlevel & special effects) @@ -1835,13 +1983,13 @@ static void R_ProjectSprite(mobj_t *thing) // specific translucency if (!cv_translucency.value) ; // no translucency - else if (oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) - vis->transmap = transtables + ((tr_trans80-1)<frame & FF_TRANSMASK) - vis->transmap = transtables + (oldthing->frame & FF_TRANSMASK) - 0x10000; + else if (trans) + vis->transmap = transtables + ((trans-1)<frame & FF_FULLBRIGHT || oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) + if (R_ThingIsFullBright(oldthing) || oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) vis->cut |= SC_FULLBRIGHT; + else if (R_ThingIsFullDark(oldthing)) + vis->cut |= SC_FULLDARK; if (vis->cut & SC_FULLBRIGHT && (!vis->extra_colormap || !(vis->extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES))) @@ -1849,6 +1997,8 @@ static void R_ProjectSprite(mobj_t *thing) // full bright: goggles vis->colormap = colormaps; } + else if (vis->cut & SC_FULLDARK) + vis->colormap = scalelight[0][0]; else { // diminished light @@ -1862,8 +2012,10 @@ static void R_ProjectSprite(mobj_t *thing) if (vflip) vis->cut |= SC_VFLIP; + if (splat) + vis->cut |= SC_SPLAT; // I like ya cut g - if (thing->subsector->sector->numlights) + if (thing->subsector->sector->numlights && !(shadowdraw || splat)) R_SplitSprite(vis); if (oldthing->shadowscale && cv_shadow.value) @@ -2470,10 +2622,13 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps } else if (r2->sprite) { - if (r2->sprite->x1 > rover->x2 || r2->sprite->x2 < rover->x1) - continue; - if (r2->sprite->szt > rover->sz || r2->sprite->sz < rover->szt) - continue; + if (!(r2->sprite->cut & SC_SPLAT || rover->cut & SC_SPLAT)) + { + if (r2->sprite->x1 > rover->x2 || r2->sprite->x2 < rover->x1) + continue; + if (r2->sprite->szt > rover->sz || r2->sprite->sz < rover->szt) + continue; + } if (r2->sprite->sortscale > rover->sortscale || (r2->sprite->sortscale == rover->sortscale && r2->sprite->dispoffset > rover->dispoffset)) @@ -2552,6 +2707,146 @@ void R_InitDrawNodes(void) nodebankhead.next = nodebankhead.prev = &nodebankhead; } +static void R_DrawVisSplat(vissprite_t *spr) +{ +#ifdef FLOORSPLATS + floorsplat_t splat; + fixed_t tr_x, tr_y, rot_x, rot_y, rot_z; + vertex_t *v3d; + vertex_t v2d[4]; + fixed_t x, y; + fixed_t w, h; + angle_t splatangle, angle; + fixed_t ca, sa; + fixed_t xscale, yscale; + fixed_t xoffset, yoffset; + fixed_t leftoffset, topoffset; + boolean hflip = (spr->xiscale < 0); + boolean vflip = (spr->cut & SC_VFLIP); + UINT8 flipflags = 0; + vector2_t rotated[4]; + INT32 i; + + if (hflip) + flipflags |= PICFLAGS_XFLIP; + if (vflip) + flipflags |= PICFLAGS_YFLIP; + + Patch_GenerateFlat(spr->patch, flipflags); + splat.pic = spr->patch->flats[flipflags]; + if (splat.pic == NULL) + return; + + splat.mobj = spr->mobj; + splat.width = spr->patch->width; + splat.height = spr->patch->height; + splat.scale = spr->mobj->scale; + + if (spr->renderflags & RF_SHADOWEFFECTS) + splat.scale = FixedMul(splat.scale, spr->shadowscale); + + if (spr->rotateflags & SRF_3D || spr->renderflags & RF_NOSPLATBILLBOARD) + splatangle = spr->mobj->angle; + else + splatangle = viewangle; + + if (!(spr->cut & SC_ISROTATED)) + splatangle += spr->mobj->rollangle; + + splat.angle = -splatangle; + splat.angle += ANGLE_90; + + topoffset = (spr->patch->topoffset * FRACUNIT); + leftoffset = (spr->patch->leftoffset * FRACUNIT); + if (hflip) + leftoffset = ((splat.width * FRACUNIT) - leftoffset); + + xscale = spr->mobj->spritexscale; + yscale = spr->mobj->spriteyscale; + + splat.xscale = FixedMul(splat.scale, xscale); + splat.yscale = FixedMul(splat.scale, yscale); + + xoffset = FixedMul(leftoffset, splat.xscale); + yoffset = FixedMul(topoffset, splat.yscale); + + x = spr->mobj->x; + y = spr->mobj->y; + w = (splat.width * splat.xscale); + h = (splat.height * splat.yscale); + + splat.x = x; + splat.y = y; + splat.z = spr->mobj->z; + + // Set positions + + // 3--2 + // | | + // 0--1 + + splat.verts[0].x = w - xoffset; + splat.verts[0].y = yoffset; + + splat.verts[1].x = -xoffset; + splat.verts[1].y = yoffset; + + splat.verts[2].x = -xoffset; + splat.verts[2].y = -h + yoffset; + + splat.verts[3].x = w - xoffset; + splat.verts[3].y = -h + yoffset; + + angle = -splat.angle; + ca = FINECOSINE(angle>>ANGLETOFINESHIFT); + sa = FINESINE(angle>>ANGLETOFINESHIFT); + + // Rotate + for (i = 0; i < 4; i++) + { + rotated[i].x = FixedMul(splat.verts[i].x, ca) - FixedMul(splat.verts[i].y, sa); + rotated[i].y = FixedMul(splat.verts[i].x, sa) + FixedMul(splat.verts[i].y, ca); + } + + // Translate + for (i = 0; i < 4; i++) + { + splat.verts[i].x = rotated[i].x + x; + splat.verts[i].y = rotated[i].y + y; + } + + rot_z = splat.z - viewz; + + for (i = 0; i < 4; i++) + { + v3d = &splat.verts[i]; + + // transform the origin point + tr_x = v3d->x - viewx; + tr_y = v3d->y - viewy; + + // rotation around vertical y axis + rot_x = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); + rot_y = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); + + if (!rot_y || rot_y < FixedDiv(4*FRACUNIT, splat.scale)) + return; + + // note: y from view above of map, is distance far away + xscale = FixedDiv(projection, rot_y); + yscale = -FixedDiv(projectiony, rot_y); + + // projection + v2d[i].x = (centerxfrac + FixedMul(rot_x, xscale))>>FRACBITS; + v2d[i].y = (centeryfrac + FixedMul(rot_z, yscale))>>FRACBITS; + } + + R_RenderFloorSplat(&splat, v2d, spr); +#else + (void)spr; +#endif +} + // // R_DrawSprite // @@ -2562,7 +2857,11 @@ static void R_DrawSprite(vissprite_t *spr) { mfloorclip = spr->clipbot; mceilingclip = spr->cliptop; - R_DrawVisSprite(spr); + + if (spr->cut & SC_SPLAT) + R_DrawVisSplat(spr); + else + R_DrawVisSprite(spr); } // Special drawer for precipitation sprites Tails 08-18-2002 @@ -2573,205 +2872,208 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr) R_DrawPrecipitationVisSprite(spr); } -// R_ClipSprites +// R_ClipVisSprite // Clips vissprites without drawing, so that portals can work. -Red -void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) +void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal) { - vissprite_t *spr; - for (; clippedvissprites < visspritecount; clippedvissprites++) + drawseg_t *ds; + INT32 x; + INT32 r1; + INT32 r2; + fixed_t scale; + fixed_t lowscale; + INT32 silhouette; + + for (x = x1; x <= x2; x++) + spr->clipbot[x] = spr->cliptop[x] = -2; + + // Scan drawsegs from end to start for obscuring segs. + // The first drawseg that has a greater scale + // is the clip seg. + //SoM: 4/8/2000: + // Pointer check was originally nonportable + // and buggy, by going past LEFT end of array: + + // for (ds = ds_p-1; ds >= drawsegs; ds--) old buggy code + for (ds = ds_p; ds-- > dsstart;) { - drawseg_t *ds; - INT32 x; - INT32 r1; - INT32 r2; - fixed_t scale; - fixed_t lowscale; - INT32 silhouette; - - spr = R_GetVisSprite(clippedvissprites); - - for (x = spr->x1; x <= spr->x2; x++) - spr->clipbot[x] = spr->cliptop[x] = -2; - - // Scan drawsegs from end to start for obscuring segs. - // The first drawseg that has a greater scale - // is the clip seg. - //SoM: 4/8/2000: - // Pointer check was originally nonportable - // and buggy, by going past LEFT end of array: - - // for (ds = ds_p-1; ds >= drawsegs; ds--) old buggy code - for (ds = ds_p; ds-- > dsstart;) + // determine if the drawseg obscures the sprite + if (ds->x1 > x2 || + ds->x2 < x1 || + (!ds->silhouette + && !ds->maskedtexturecol)) { - // determine if the drawseg obscures the sprite - if (ds->x1 > spr->x2 || - ds->x2 < spr->x1 || - (!ds->silhouette - && !ds->maskedtexturecol)) + // does not cover sprite + continue; + } + + if (ds->portalpass != 66) + { + if (ds->portalpass > 0 && ds->portalpass <= portalrender) + continue; // is a portal + + if (ds->scale1 > ds->scale2) { - // does not cover sprite + lowscale = ds->scale2; + scale = ds->scale1; + } + else + { + lowscale = ds->scale1; + scale = ds->scale2; + } + + if (scale < spr->sortscale || + (lowscale < spr->sortscale && + !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) + { + // masked mid texture? + /*if (ds->maskedtexturecol) + R_RenderMaskedSegRange (ds, r1, r2);*/ + // seg is behind sprite continue; } - - if (ds->portalpass != 66) - { - if (ds->portalpass > 0 && ds->portalpass <= portalrender) - continue; // is a portal - - if (ds->scale1 > ds->scale2) - { - lowscale = ds->scale2; - scale = ds->scale1; - } - else - { - lowscale = ds->scale1; - scale = ds->scale2; - } - - if (scale < spr->sortscale || - (lowscale < spr->sortscale && - !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) - { - // masked mid texture? - /*if (ds->maskedtexturecol) - R_RenderMaskedSegRange (ds, r1, r2);*/ - // seg is behind sprite - continue; - } - } - - r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; - r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; - - // clip this piece of the sprite - silhouette = ds->silhouette; - - if (spr->gz >= ds->bsilheight) - silhouette &= ~SIL_BOTTOM; - - if (spr->gzt <= ds->tsilheight) - silhouette &= ~SIL_TOP; - - if (silhouette == SIL_BOTTOM) - { - // bottom sil - for (x = r1; x <= r2; x++) - if (spr->clipbot[x] == -2) - spr->clipbot[x] = ds->sprbottomclip[x]; - } - else if (silhouette == SIL_TOP) - { - // top sil - for (x = r1; x <= r2; x++) - if (spr->cliptop[x] == -2) - spr->cliptop[x] = ds->sprtopclip[x]; - } - else if (silhouette == (SIL_TOP|SIL_BOTTOM)) - { - // both - for (x = r1; x <= r2; x++) - { - if (spr->clipbot[x] == -2) - spr->clipbot[x] = ds->sprbottomclip[x]; - if (spr->cliptop[x] == -2) - spr->cliptop[x] = ds->sprtopclip[x]; - } - } } - //SoM: 3/17/2000: Clip sprites in water. - if (spr->heightsec != -1) // only things in specially marked sectors + + r1 = ds->x1 < x1 ? x1 : ds->x1; + r2 = ds->x2 > x2 ? x2 : ds->x2; + + // clip this piece of the sprite + silhouette = ds->silhouette; + + if (spr->gz >= ds->bsilheight) + silhouette &= ~SIL_BOTTOM; + + if (spr->gzt <= ds->tsilheight) + silhouette &= ~SIL_TOP; + + if (silhouette == SIL_BOTTOM) { - fixed_t mh, h; - INT32 phs = viewplayer->mo->subsector->sector->heightsec; - if ((mh = sectors[spr->heightsec].floorheight) > spr->gz && - (h = centeryfrac - FixedMul(mh -= viewz, spr->sortscale)) >= 0 && - (h >>= FRACBITS) < viewheight) - { - if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight)) - { // clip bottom - for (x = spr->x1; x <= spr->x2; x++) - if (spr->clipbot[x] == -2 || h < spr->clipbot[x]) - spr->clipbot[x] = (INT16)h; - } - else // clip top - { - for (x = spr->x1; x <= spr->x2; x++) - if (spr->cliptop[x] == -2 || h > spr->cliptop[x]) - spr->cliptop[x] = (INT16)h; - } - } - - if ((mh = sectors[spr->heightsec].ceilingheight) < spr->gzt && - (h = centeryfrac - FixedMul(mh-viewz, spr->sortscale)) >= 0 && - (h >>= FRACBITS) < viewheight) - { - if (phs != -1 && viewz >= sectors[phs].ceilingheight) - { // clip bottom - for (x = spr->x1; x <= spr->x2; x++) - if (spr->clipbot[x] == -2 || h < spr->clipbot[x]) - spr->clipbot[x] = (INT16)h; - } - else // clip top - { - for (x = spr->x1; x <= spr->x2; x++) - if (spr->cliptop[x] == -2 || h > spr->cliptop[x]) - spr->cliptop[x] = (INT16)h; - } - } + // bottom sil + for (x = r1; x <= r2; x++) + if (spr->clipbot[x] == -2) + spr->clipbot[x] = ds->sprbottomclip[x]; } - if (spr->cut & SC_TOP && spr->cut & SC_BOTTOM) + else if (silhouette == SIL_TOP) { - for (x = spr->x1; x <= spr->x2; x++) + // top sil + for (x = r1; x <= r2; x++) + if (spr->cliptop[x] == -2) + spr->cliptop[x] = ds->sprtopclip[x]; + } + else if (silhouette == (SIL_TOP|SIL_BOTTOM)) + { + // both + for (x = r1; x <= r2; x++) { - if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x]) - spr->cliptop[x] = spr->szt; - - if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x]) - spr->clipbot[x] = spr->sz; + if (spr->clipbot[x] == -2) + spr->clipbot[x] = ds->sprbottomclip[x]; + if (spr->cliptop[x] == -2) + spr->cliptop[x] = ds->sprtopclip[x]; } } - else if (spr->cut & SC_TOP) + } + //SoM: 3/17/2000: Clip sprites in water. + if (spr->heightsec != -1) // only things in specially marked sectors + { + fixed_t mh, h; + INT32 phs = viewplayer->mo->subsector->sector->heightsec; + if ((mh = sectors[spr->heightsec].floorheight) > spr->gz && + (h = centeryfrac - FixedMul(mh -= viewz, spr->sortscale)) >= 0 && + (h >>= FRACBITS) < viewheight) { - for (x = spr->x1; x <= spr->x2; x++) - { - if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x]) - spr->cliptop[x] = spr->szt; + if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight)) + { // clip bottom + for (x = x1; x <= x2; x++) + if (spr->clipbot[x] == -2 || h < spr->clipbot[x]) + spr->clipbot[x] = (INT16)h; } - } - else if (spr->cut & SC_BOTTOM) - { - for (x = spr->x1; x <= spr->x2; x++) + else // clip top { - if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x]) - spr->clipbot[x] = spr->sz; + for (x = x1; x <= x2; x++) + if (spr->cliptop[x] == -2 || h > spr->cliptop[x]) + spr->cliptop[x] = (INT16)h; } } - // all clipping has been performed, so store the values - what, did you think we were drawing them NOW? - - // check for unclipped columns - for (x = spr->x1; x <= spr->x2; x++) + if ((mh = sectors[spr->heightsec].ceilingheight) < spr->gzt && + (h = centeryfrac - FixedMul(mh-viewz, spr->sortscale)) >= 0 && + (h >>= FRACBITS) < viewheight) { - if (spr->clipbot[x] == -2) - spr->clipbot[x] = (INT16)viewheight; - - if (spr->cliptop[x] == -2) - //Fab : 26-04-98: was -1, now clips against console bottom - spr->cliptop[x] = (INT16)con_clipviewtop; - } - - if (portal) - { - for (x = spr->x1; x <= spr->x2; x++) + if (phs != -1 && viewz >= sectors[phs].ceilingheight) + { // clip bottom + for (x = x1; x <= x2; x++) + if (spr->clipbot[x] == -2 || h < spr->clipbot[x]) + spr->clipbot[x] = (INT16)h; + } + else // clip top { - if (spr->clipbot[x] > portal->floorclip[x - portal->start]) - spr->clipbot[x] = portal->floorclip[x - portal->start]; - if (spr->cliptop[x] < portal->ceilingclip[x - portal->start]) - spr->cliptop[x] = portal->ceilingclip[x - portal->start]; + for (x = x1; x <= x2; x++) + if (spr->cliptop[x] == -2 || h > spr->cliptop[x]) + spr->cliptop[x] = (INT16)h; } } } + if (spr->cut & SC_TOP && spr->cut & SC_BOTTOM) + { + for (x = x1; x <= x2; x++) + { + if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x]) + spr->cliptop[x] = spr->szt; + + if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x]) + spr->clipbot[x] = spr->sz; + } + } + else if (spr->cut & SC_TOP) + { + for (x = x1; x <= x2; x++) + { + if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x]) + spr->cliptop[x] = spr->szt; + } + } + else if (spr->cut & SC_BOTTOM) + { + for (x = x1; x <= x2; x++) + { + if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x]) + spr->clipbot[x] = spr->sz; + } + } + + // all clipping has been performed, so store the values - what, did you think we were drawing them NOW? + + // check for unclipped columns + for (x = x1; x <= x2; x++) + { + if (spr->clipbot[x] == -2) + spr->clipbot[x] = (INT16)viewheight; + + if (spr->cliptop[x] == -2) + //Fab : 26-04-98: was -1, now clips against console bottom + spr->cliptop[x] = (INT16)con_clipviewtop; + } + + if (portal) + { + for (x = x1; x <= x2; x++) + { + if (spr->clipbot[x] > portal->floorclip[x - portal->start]) + spr->clipbot[x] = portal->floorclip[x - portal->start]; + if (spr->cliptop[x] < portal->ceilingclip[x - portal->start]) + spr->cliptop[x] = portal->ceilingclip[x - portal->start]; + } + } +} + +void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) +{ + for (; clippedvissprites < visspritecount; clippedvissprites++) + { + vissprite_t *spr = R_GetVisSprite(clippedvissprites); + R_ClipVisSprite(spr, spr->x1, spr->x2, dsstart, portal); + } } /* Check if thing may be drawn from our current view. */ @@ -2823,6 +3125,36 @@ boolean R_PrecipThingVisible (precipmobj_t *precipthing, return ( approx_dist <= limit_dist ); } +boolean R_ThingHorizontallyFlipped(mobj_t *thing) +{ + return (thing->frame & FF_HORIZONTALFLIP || thing->renderflags & RF_HORIZONTALFLIP); +} + +boolean R_ThingVerticallyFlipped(mobj_t *thing) +{ + return (thing->frame & FF_VERTICALFLIP || thing->renderflags & RF_VERTICALFLIP); +} + +boolean R_ThingIsPaperSprite(mobj_t *thing) +{ + return (thing->frame & FF_PAPERSPRITE || thing->renderflags & RF_PAPERSPRITE); +} + +boolean R_ThingIsFloorSprite(mobj_t *thing) +{ + return (thing->flags2 & MF2_SPLAT || thing->renderflags & RF_FLOORSPRITE); +} + +boolean R_ThingIsFullBright (mobj_t *thing) +{ + return (thing->frame & FF_FULLBRIGHT || thing->renderflags & RF_FULLBRIGHT); +} + +boolean R_ThingIsFullDark (mobj_t *thing) +{ + return (thing->renderflags & RF_FULLDARK); +} + // // R_DrawMasked // diff --git a/src/r_things.h b/src/r_things.h index f241a78ba..2addcb7ca 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -65,7 +65,6 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope); void R_AddSprites(sector_t *sec, INT32 lightlevel); void R_InitSprites(void); void R_ClearSprites(void); -void R_ClipSprites(drawseg_t* dsstart, portal_t* portal); boolean R_ThingVisible (mobj_t *thing); @@ -76,6 +75,15 @@ boolean R_ThingVisibleWithinDist (mobj_t *thing, boolean R_PrecipThingVisible (precipmobj_t *precipthing, fixed_t precip_draw_dist); +boolean R_ThingHorizontallyFlipped (mobj_t *thing); +boolean R_ThingVerticallyFlipped (mobj_t *thing); + +boolean R_ThingIsPaperSprite (mobj_t *thing); +boolean R_ThingIsFloorSprite (mobj_t *thing); + +boolean R_ThingIsFullBright (mobj_t *thing); +boolean R_ThingIsFullDark (mobj_t *thing); + // -------------- // MASKED DRAWING // -------------- @@ -108,19 +116,23 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks); typedef enum { // actual cuts - SC_NONE = 0, - SC_TOP = 1, - SC_BOTTOM = 1<<1, + SC_NONE = 0, + SC_TOP = 1, + SC_BOTTOM = 1<<1, // other flags - SC_PRECIP = 1<<2, - SC_LINKDRAW = 1<<3, + SC_PRECIP = 1<<2, + SC_LINKDRAW = 1<<3, SC_FULLBRIGHT = 1<<4, - SC_VFLIP = 1<<5, - SC_ISSCALED = 1<<6, - SC_SHADOW = 1<<7, + SC_FULLDARK = 1<<5, + SC_VFLIP = 1<<6, + SC_ISSCALED = 1<<7, + SC_ISROTATED = 1<<8, + SC_SHADOW = 1<<9, + SC_SHEAR = 1<<10, + SC_SPLAT = 1<<11, // masks - SC_CUTMASK = SC_TOP|SC_BOTTOM, - SC_FLAGMASK = ~SC_CUTMASK + SC_CUTMASK = SC_TOP|SC_BOTTOM, + SC_FLAGMASK = ~SC_CUTMASK } spritecut_e; // A vissprite_t is a thing that will be drawn during a refresh, @@ -177,6 +189,10 @@ typedef struct vissprite_s INT16 sz, szt; spritecut_e cut; + UINT32 renderflags; + UINT8 rotateflags; + + fixed_t shadowscale; INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; @@ -185,6 +201,12 @@ typedef struct vissprite_s extern UINT32 visspritecount; +void R_ClipSprites(drawseg_t* dsstart, portal_t* portal); +void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal); + +boolean R_SpriteIsFlashing(vissprite_t *vis); +UINT8 *R_GetSpriteTranslation(vissprite_t *vis); + // ---------- // DRAW NODES // ---------- diff --git a/src/screen.c b/src/screen.c index adda4ba2f..f5d182f34 100644 --- a/src/screen.c +++ b/src/screen.c @@ -124,6 +124,8 @@ void SCR_SetDrawFuncs(void) spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8; spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8; spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8; + spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8; + spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8; spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8; #ifndef NOWATER spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8; @@ -140,6 +142,8 @@ void SCR_SetDrawFuncs(void) spanfuncs_npo2[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed #ifndef NOWATER spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8; diff --git a/src/screen.h b/src/screen.h index acc08f001..021c644ba 100644 --- a/src/screen.h +++ b/src/screen.h @@ -142,6 +142,8 @@ enum SPANDRAWFUNC_TRANS, SPANDRAWFUNC_SPLAT, SPANDRAWFUNC_TRANSSPLAT, + SPANDRAWFUNC_SPRITE, + SPANDRAWFUNC_TRANSSPRITE, SPANDRAWFUNC_FOG, #ifndef NOWATER SPANDRAWFUNC_WATER, diff --git a/src/tmap.nas b/src/tmap.nas index 106f38e96..69282d0b4 100644 --- a/src/tmap.nas +++ b/src/tmap.nas @@ -763,8 +763,8 @@ TX2 EQU 16 TY2 EQU 20 RASTERY_SIZEOF EQU 24 -cglobal rasterize_segment_tex -rasterize_segment_tex: +cglobal rasterize_segment_tex_asm +rasterize_segment_tex_asm: push ebp mov ebp,esp From 37ed2a6b265068c5e65a42df7ba03c4c17456cec Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 12 Oct 2020 17:25:18 -0300 Subject: [PATCH 13/81] Support spritexscale and spriteyscale in OpenGL Fix papersprite scaling with spritexscale and spriteyscale in Software --- src/hardware/hw_glob.h | 3 +- src/hardware/hw_main.c | 88 +++++++++++++++++++++--------------------- src/r_things.c | 14 +++++-- src/r_things.h | 1 + 4 files changed, 56 insertions(+), 50 deletions(-) diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index b16a0f231..0d33d185a 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -62,7 +62,8 @@ typedef struct typedef struct gl_vissprite_s { float x1, x2; - float tz, ty; + float gz, gzt; + float tz; float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting patch_t *gpatch; boolean flip; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index cfcad29d0..35611c9f3 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3605,17 +3605,17 @@ static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts // X, Y, AND Z need to be manipulated for the polys to rotate around the // origin, because of how the origin setting works I believe that should // be mobj->z or mobj->z + mobj->height - wallVerts[2].y = wallVerts[3].y = (spr->ty - basey) * gl_viewludsin + basey; + wallVerts[2].y = wallVerts[3].y = (spr->gzt - basey) * gl_viewludsin + basey; wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gl_viewludsin + basey; // translate back to be around 0 before translating back - wallVerts[3].x += ((spr->ty - basey) * gl_viewludcos) * gl_viewcos; - wallVerts[2].x += ((spr->ty - basey) * gl_viewludcos) * gl_viewcos; + wallVerts[3].x += ((spr->gzt - basey) * gl_viewludcos) * gl_viewcos; + wallVerts[2].x += ((spr->gzt - basey) * gl_viewludcos) * gl_viewcos; wallVerts[0].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos; wallVerts[1].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos; - wallVerts[3].z += ((spr->ty - basey) * gl_viewludcos) * gl_viewsin; - wallVerts[2].z += ((spr->ty - basey) * gl_viewludcos) * gl_viewsin; + wallVerts[3].z += ((spr->gzt - basey) * gl_viewludcos) * gl_viewsin; + wallVerts[2].z += ((spr->gzt - basey) * gl_viewludcos) * gl_viewsin; wallVerts[0].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin; wallVerts[1].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin; @@ -3624,14 +3624,13 @@ static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts static void HWR_SplitSprite(gl_vissprite_t *spr) { - float this_scale = 1.0f; FOutVector wallVerts[4]; FOutVector baseWallVerts[4]; // This is what the verts should end up as patch_t *gpatch; FSurfaceInfo Surf; - const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); extracolormap_t *colormap; FUINT lightlevel; + boolean lightset = true; FBITFIELD blend = 0; FBITFIELD occlusion; boolean use_linkdraw_hack = false; @@ -3650,11 +3649,6 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) fixed_t temp; fixed_t v1x, v1y, v2x, v2y; - this_scale = FIXED_TO_FLOAT(spr->mobj->scale); - - if (hires) - this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)spr->mobj->skin)->highresscale); - gpatch = spr->gpatch; // cache the patch in the graphics card memory @@ -3667,11 +3661,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) baseWallVerts[0].z = baseWallVerts[3].z = spr->z1; baseWallVerts[1].z = baseWallVerts[2].z = spr->z2; - baseWallVerts[2].y = baseWallVerts[3].y = spr->ty; - if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f) - baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height * this_scale; - else - baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height; + baseWallVerts[2].y = baseWallVerts[3].y = spr->gzt; + baseWallVerts[0].y = baseWallVerts[1].y = spr->gz; v1x = FLOAT_TO_FIXED(spr->x1); v1y = FLOAT_TO_FIXED(spr->z1); @@ -3767,15 +3758,19 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) i = 0; temp = FLOAT_TO_FIXED(realtop); - if (spr->mobj->frame & FF_FULLBRIGHT) + if (R_ThingIsFullBright(spr->mobj)) lightlevel = 255; + else if (R_ThingIsFullDark(spr->mobj)) + lightlevel = 0; + else + lightset = false; for (i = 1; i < sector->numlights; i++) { fixed_t h = P_GetLightZAt(§or->lightlist[i], spr->mobj->x, spr->mobj->y); if (h <= temp) { - if (!(spr->mobj->frame & FF_FULLBRIGHT)) + if (!lightset) lightlevel = *list[i-1].lightlevel > 255 ? 255 : *list[i-1].lightlevel; colormap = *list[i-1].extra_colormap; break; @@ -3790,7 +3785,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) // even if we aren't changing colormap or lightlevel, we still need to continue drawing down the sprite if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES)) { - if (!(spr->mobj->frame & FF_FULLBRIGHT)) + if (!lightset) lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel; colormap = *list[i].extra_colormap; } @@ -3901,16 +3896,10 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) // -----------------+ static void HWR_DrawSprite(gl_vissprite_t *spr) { - float this_scale = 1.0f; FOutVector wallVerts[4]; patch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; - const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); //const boolean papersprite = R_ThingIsPaperSprite(spr->mobj); - if (spr->mobj) - this_scale = FIXED_TO_FLOAT(spr->mobj->scale); - if (hires) - this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)spr->mobj->skin)->highresscale); if (!spr->mobj) return; @@ -3948,11 +3937,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) // these were already scaled in HWR_ProjectSprite wallVerts[0].x = wallVerts[3].x = spr->x1; wallVerts[2].x = wallVerts[1].x = spr->x2; - wallVerts[2].y = wallVerts[3].y = spr->ty; - if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f) - wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height * this_scale; - else - wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height; + wallVerts[2].y = wallVerts[3].y = spr->gzt; + wallVerts[0].y = wallVerts[1].y = spr->gz; // make a wall polygon (with 2 triangles), using the floor/ceiling heights, // and the 2d map coords of start/end vertices @@ -4003,10 +3989,14 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) // colormap test { sector_t *sector = spr->mobj->subsector->sector; - UINT8 lightlevel = 255; + UINT8 lightlevel; extracolormap_t *colormap = sector->extra_colormap; - if (!(spr->mobj->frame & FF_FULLBRIGHT)) + if (R_ThingIsFullBright(spr->mobj)) + lightlevel = 255; + else if (R_ThingIsFullDark(spr->mobj)) + lightlevel = 0; + else lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; HWR_Lighting(&Surf, lightlevel, colormap); @@ -4081,8 +4071,8 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) // 0--1 wallVerts[0].x = wallVerts[3].x = spr->x1; wallVerts[2].x = wallVerts[1].x = spr->x2; - wallVerts[2].y = wallVerts[3].y = spr->ty; - wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height; + wallVerts[2].y = wallVerts[3].y = spr->gzt; + wallVerts[0].y = wallVerts[1].y = spr->gz; // make a wall polygon (with 2 triangles), using the floor/ceiling heights, // and the 2d map coords of start/end vertices @@ -4680,6 +4670,7 @@ static void HWR_ProjectSprite(mobj_t *thing) float x1, x2; float rightsin, rightcos; float this_scale; + float spritexscale, spriteyscale; float gz, gzt; spritedef_t *sprdef; spriteframe_t *sprframe; @@ -4714,6 +4705,8 @@ static void HWR_ProjectSprite(mobj_t *thing) dispoffset = thing->info->dispoffset; this_scale = FIXED_TO_FLOAT(thing->scale); + spritexscale = FIXED_TO_FLOAT(thing->spritexscale); + spriteyscale = FIXED_TO_FLOAT(thing->spriteyscale); // transform the origin point tr_x = FIXED_TO_FLOAT(thing->x) - gl_viewx; @@ -4867,15 +4860,18 @@ static void HWR_ProjectSprite(mobj_t *thing) flip = !flip != !hflip; + spritexscale *= this_scale; + spriteyscale *= this_scale; + if (flip) { - x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_scale); - x2 = (FIXED_TO_FLOAT(spr_offset) * this_scale); + x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * spritexscale); + x2 = (FIXED_TO_FLOAT(spr_offset) * spritexscale); } else { - x1 = (FIXED_TO_FLOAT(spr_offset) * this_scale); - x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_scale); + x1 = (FIXED_TO_FLOAT(spr_offset) * spritexscale); + x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * spritexscale); } // test if too close @@ -4897,13 +4893,13 @@ static void HWR_ProjectSprite(mobj_t *thing) if (vflip) { - gz = FIXED_TO_FLOAT(thing->z+thing->height) - FIXED_TO_FLOAT(spr_topoffset) * this_scale; - gzt = gz + FIXED_TO_FLOAT(spr_height) * this_scale; + gz = FIXED_TO_FLOAT(thing->z+thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * spriteyscale); + gzt = gz + (FIXED_TO_FLOAT(spr_height) * spriteyscale); } else { - gzt = FIXED_TO_FLOAT(thing->z) + FIXED_TO_FLOAT(spr_topoffset) * this_scale; - gz = gzt - FIXED_TO_FLOAT(spr_height) * this_scale; + gzt = FIXED_TO_FLOAT(thing->z) + (FIXED_TO_FLOAT(spr_topoffset) * spriteyscale); + gz = gzt - (FIXED_TO_FLOAT(spr_height) * spriteyscale); } if (thing->subsector->sector->cullheight) @@ -5010,7 +5006,8 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->colormap = colormaps; // set top/bottom coords - vis->ty = gzt; + vis->gzt = gzt; + vis->gz = gz; //CONS_Debug(DBG_RENDER, "------------------\nH: sprite : %d\nH: frame : %x\nH: type : %d\nH: sname : %s\n\n", // thing->sprite, thing->frame, thing->type, sprnames[thing->sprite]); @@ -5110,7 +5107,8 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->colormap = colormaps; // set top/bottom coords - vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); + vis->gzt = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); + vis->gz = vis->gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height); vis->precip = true; diff --git a/src/r_things.c b/src/r_things.c index ac9c357a4..00bb0b32a 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -923,13 +923,16 @@ static void R_DrawVisSprite(vissprite_t *vis) // Split drawing loops for paper and non-paper to reduce conditional checks per sprite if (vis->scalestep) { + fixed_t horzscale = FixedMul(vis->spritexscale, this_scale); + fixed_t scalestep = FixedMul(vis->scalestep, vis->spriteyscale); + pwidth = SHORT(patch->width); // Papersprite drawing loop - for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += vis->scalestep) + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += scalestep) { angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF; - texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / this_scale; + texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / horzscale; if (texturecolumn < 0 || texturecolumn >= pwidth) continue; @@ -1946,6 +1949,9 @@ static void R_ProjectSprite(mobj_t *thing) vis->xscale = FixedMul(spritexscale, xscale); //SoM: 4/17/2000 vis->scale = FixedMul(spriteyscale, yscale); //<spritexscale = spritexscale; + vis->spriteyscale = spriteyscale; + if (shadowdraw || shadoweffects) { iscale = (patch->width<x1 > x1) { - vis->startfrac += FixedDiv(vis->xiscale, this_scale)*(vis->x1-x1); - vis->scale += scalestep*(vis->x1 - x1); + vis->startfrac += FixedDiv(vis->xiscale, this_scale) * (vis->x1 - x1); + vis->scale += FixedMul(scalestep, spriteyscale) * (vis->x1 - x1); } vis->patch = patch; diff --git a/src/r_things.h b/src/r_things.h index 2addcb7ca..16cf5088f 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -192,6 +192,7 @@ typedef struct vissprite_s UINT32 renderflags; UINT8 rotateflags; + fixed_t spritexscale, spriteyscale; fixed_t shadowscale; INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; From 9bb09cdc8cb5177644422853b7a5bbb848c52a3f Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 12 Oct 2020 19:53:21 -0300 Subject: [PATCH 14/81] OpenGL support for splats, fix some shadow draw bugs in Software --- src/dehacked.c | 1 + src/hardware/hw_glob.h | 25 ++-- src/hardware/hw_main.c | 268 +++++++++++++++++++++++++++++++++-------- src/r_defs.h | 5 +- src/r_things.c | 21 ++-- 5 files changed, 250 insertions(+), 70 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 92a8ffe4e..aa4a04be4 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9584,6 +9584,7 @@ struct { {"RF_HORIZONTALFLIP",RF_HORIZONTALFLIP}, {"RF_VERTICALFLIP",RF_VERTICALFLIP}, {"RF_ONESIDED",RF_ONESIDED}, + {"RF_SLOPESPLAT",RF_SLOPESPLAT}, {"RF_NOSPLATBILLBOARD",RF_NOSPLATBILLBOARD}, {"RF_NOSPLATROLLANGLE",RF_NOSPLATROLLANGLE}, {"RF_FULLBRIGHT",RF_FULLBRIGHT}, diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 0d33d185a..cb517b611 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -62,19 +62,30 @@ typedef struct typedef struct gl_vissprite_s { float x1, x2; + float z1, z2; float gz, gzt; + float tz; float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting - patch_t *gpatch; - boolean flip; - UINT8 translucency; //alpha level 0-255 - mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out. + + float scale; + float spritexscale, spriteyscale; + float shadowheight, shadowscale; + + UINT32 renderflags; + UINT8 rotateflags; + + boolean flip, vflip; boolean precip; // Tails 08-25-2002 - boolean vflip; - //Hurdler: 25/04/2000: now support colormap in hardware mode + boolean rotated; + UINT8 translucency; //alpha level 0-255 + + //Hurdler: 25/04/2000: now support colormap in hardware mode UINT8 *colormap; INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing - float z1, z2; + + patch_t *gpatch; + mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out. } gl_vissprite_t; // -------- diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 35611c9f3..98f3d69da 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3634,6 +3634,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) FBITFIELD blend = 0; FBITFIELD occlusion; boolean use_linkdraw_hack = false; + boolean splat = R_ThingIsFloorSprite(spr->mobj); UINT8 alpha; INT32 i; @@ -3692,18 +3693,21 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) baseWallVerts[0].t = baseWallVerts[1].t = ((GLPatch_t *)gpatch->hardware)->max_t; } - // if it has a dispoffset, push it a little towards the camera - if (spr->dispoffset) { - float co = -gl_viewcos*(0.05f*spr->dispoffset); - float si = -gl_viewsin*(0.05f*spr->dispoffset); - baseWallVerts[0].z = baseWallVerts[3].z = baseWallVerts[0].z+si; - baseWallVerts[1].z = baseWallVerts[2].z = baseWallVerts[1].z+si; - baseWallVerts[0].x = baseWallVerts[3].x = baseWallVerts[0].x+co; - baseWallVerts[1].x = baseWallVerts[2].x = baseWallVerts[1].x+co; - } + if (!splat) + { + // if it has a dispoffset, push it a little towards the camera + if (spr->dispoffset) { + float co = -gl_viewcos*(0.05f*spr->dispoffset); + float si = -gl_viewsin*(0.05f*spr->dispoffset); + baseWallVerts[0].z = baseWallVerts[3].z = baseWallVerts[0].z+si; + baseWallVerts[1].z = baseWallVerts[2].z = baseWallVerts[1].z+si; + baseWallVerts[0].x = baseWallVerts[3].x = baseWallVerts[0].x+co; + baseWallVerts[1].x = baseWallVerts[2].x = baseWallVerts[1].x+co; + } - // Let dispoffset work first since this adjust each vertex - HWR_RotateSpritePolyToAim(spr, baseWallVerts, false); + // Let dispoffset work first since this adjust each vertex + HWR_RotateSpritePolyToAim(spr, baseWallVerts, false); + } realtop = top = baseWallVerts[3].y; realbot = bot = baseWallVerts[0].y; @@ -3899,7 +3903,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) FOutVector wallVerts[4]; patch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; - //const boolean papersprite = R_ThingIsPaperSprite(spr->mobj); + const boolean splat = R_ThingIsFloorSprite(spr->mobj); if (!spr->mobj) return; @@ -3907,7 +3911,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) if (!spr->mobj->subsector) return; - if (spr->mobj->subsector->sector->numlights) + if (spr->mobj->subsector->sector->numlights && !splat) { HWR_SplitSprite(spr); return; @@ -3934,16 +3938,112 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) // |/ | // 0--1 - // these were already scaled in HWR_ProjectSprite - wallVerts[0].x = wallVerts[3].x = spr->x1; - wallVerts[2].x = wallVerts[1].x = spr->x2; - wallVerts[2].y = wallVerts[3].y = spr->gzt; - wallVerts[0].y = wallVerts[1].y = spr->gz; + if (splat) + { + F2DCoord verts[4]; + F2DCoord rotated[4]; + angle_t angle; + float ca, sa; + float w, h; + float xscale, yscale; + float xoffset, yoffset; + float leftoffset, topoffset; + float scale = spr->scale; + float zoffset = (P_MobjFlip(spr->mobj) * 0.05f); + INT32 i; - // make a wall polygon (with 2 triangles), using the floor/ceiling heights, - // and the 2d map coords of start/end vertices - wallVerts[0].z = wallVerts[3].z = spr->z1; - wallVerts[1].z = wallVerts[2].z = spr->z2; + if (spr->renderflags & RF_SHADOWEFFECTS) + scale *= spr->shadowscale; + + if (spr->rotateflags & SRF_3D || spr->renderflags & RF_NOSPLATBILLBOARD) + angle = spr->mobj->angle; + else + angle = viewangle; + + if (!spr->rotated) + angle += spr->mobj->rollangle; + + angle = -angle; + angle += ANGLE_90; + + topoffset = (float)gpatch->topoffset; + leftoffset = (float)gpatch->leftoffset; + if (spr->flip) + leftoffset = ((float)gpatch->width - leftoffset); + + xscale = spr->scale * spr->spritexscale; + yscale = spr->scale * spr->spriteyscale; + + xoffset = leftoffset * xscale; + yoffset = topoffset * yscale; + + w = (float)gpatch->width * xscale; + h = (float)gpatch->height * yscale; + + // Set positions + + // 3--2 + // | | + // 0--1 + + verts[3].x = -xoffset; + verts[3].y = yoffset; + + verts[2].x = w - xoffset; + verts[2].y = yoffset; + + verts[1].x = w - xoffset; + verts[1].y = -h + yoffset; + + verts[0].x = -xoffset; + verts[0].y = -h + yoffset; + + ca = FIXED_TO_FLOAT(FINECOSINE((-angle)>>ANGLETOFINESHIFT)); + sa = FIXED_TO_FLOAT(FINESINE((-angle)>>ANGLETOFINESHIFT)); + + // Rotate + for (i = 0; i < 4; i++) + { + rotated[i].x = (verts[i].x * ca) - (verts[i].y * sa); + rotated[i].y = (verts[i].x * sa) + (verts[i].y * ca); + } + + // Translate + for (i = 0; i < 4; i++) + { + wallVerts[i].x = rotated[i].x + FIXED_TO_FLOAT(spr->mobj->x); + wallVerts[i].z = rotated[i].y + FIXED_TO_FLOAT(spr->mobj->y); + } + + if (spr->renderflags & RF_SLOPESPLAT && spr->mobj->standingslope) + { + pslope_t *slope = spr->mobj->standingslope; + + for (i = 0; i < 4; i++) + { + fixed_t slopez = P_GetSlopeZAt(slope, FLOAT_TO_FIXED(wallVerts[i].x), FLOAT_TO_FIXED(wallVerts[i].z)); + wallVerts[i].y = FIXED_TO_FLOAT(slopez) + zoffset; + } + } + else + { + for (i = 0; i < 4; i++) + wallVerts[i].y = FIXED_TO_FLOAT(spr->mobj->z) + zoffset; + } + } + else + { + // these were already scaled in HWR_ProjectSprite + wallVerts[0].x = wallVerts[3].x = spr->x1; + wallVerts[2].x = wallVerts[1].x = spr->x2; + wallVerts[2].y = wallVerts[3].y = spr->gzt; + wallVerts[0].y = wallVerts[1].y = spr->gz; + + // make a wall polygon (with 2 triangles), using the floor/ceiling heights, + // and the 2d map coords of start/end vertices + wallVerts[0].z = wallVerts[3].z = spr->z1; + wallVerts[1].z = wallVerts[2].z = spr->z2; + } if (spr->flip) { @@ -3969,18 +4069,21 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) //Hurdler: 25/04/2000: now support colormap in hardware mode HWR_GetMappedPatch(gpatch, spr->colormap); - // if it has a dispoffset, push it a little towards the camera - if (spr->dispoffset) { - float co = -gl_viewcos*(0.05f*spr->dispoffset); - float si = -gl_viewsin*(0.05f*spr->dispoffset); - wallVerts[0].z = wallVerts[3].z = wallVerts[0].z+si; - wallVerts[1].z = wallVerts[2].z = wallVerts[1].z+si; - wallVerts[0].x = wallVerts[3].x = wallVerts[0].x+co; - wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co; - } + if (!splat) + { + // if it has a dispoffset, push it a little towards the camera + if (spr->dispoffset) { + float co = -gl_viewcos*(0.05f*spr->dispoffset); + float si = -gl_viewsin*(0.05f*spr->dispoffset); + wallVerts[0].z = wallVerts[3].z = wallVerts[0].z+si; + wallVerts[1].z = wallVerts[2].z = wallVerts[1].z+si; + wallVerts[0].x = wallVerts[3].x = wallVerts[0].x+co; + wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co; + } - // Let dispoffset work first since this adjust each vertex - HWR_RotateSpritePolyToAim(spr, wallVerts, false); + // Let dispoffset work first since this adjust each vertex + HWR_RotateSpritePolyToAim(spr, wallVerts, false); + } // This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black. // sprite lighting by modulating the RGB components @@ -3990,6 +4093,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) { sector_t *sector = spr->mobj->subsector->sector; UINT8 lightlevel; + boolean lightset = true; extracolormap_t *colormap = sector->extra_colormap; if (R_ThingIsFullBright(spr->mobj)) @@ -3997,6 +4101,19 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) else if (R_ThingIsFullDark(spr->mobj)) lightlevel = 0; else + lightset = false; + + if (splat && sector->numlights) + { + INT32 light = R_GetPlaneLight(sector, spr->mobj->z, false); + + if (!lightset) + lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel; + + if (*sector->lightlist[light].extra_colormap) + colormap = *sector->lightlist[light].extra_colormap; + } + else if (!lightset) lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; HWR_Lighting(&Surf, lightlevel, colormap); @@ -4038,6 +4155,18 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) if (!occlusion) use_linkdraw_hack = true; } + if (spr->renderflags & RF_SHADOWEFFECTS) + { + INT32 alpha = Surf.PolyColor.s.alpha; + alpha -= ((INT32)(spr->shadowheight / 4.0f)) + 75; + if (alpha < 1) + return; + + Surf.PolyColor.s.alpha = (UINT8)(alpha); + blend = PF_Translucent|occlusion; + if (!occlusion) use_linkdraw_hack = true; + } + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader if (use_linkdraw_hack) @@ -4669,8 +4798,9 @@ static void HWR_ProjectSprite(mobj_t *thing) float tracertz = 0.0f; float x1, x2; float rightsin, rightcos; - float this_scale; + float this_scale, this_xscale, this_yscale; float spritexscale, spriteyscale; + float shadowheight = 1.0f, shadowscale = 1.0f; float gz, gzt; spritedef_t *sprdef; spriteframe_t *sprframe; @@ -4689,6 +4819,7 @@ static void HWR_ProjectSprite(mobj_t *thing) angle_t ang; INT32 heightsec, phs; const boolean papersprite = R_ThingIsPaperSprite(thing); + const boolean splat = R_ThingIsFloorSprite(thing); angle_t mobjangle = (thing->player ? thing->player->drawangle : thing->angle); float z1, z2; @@ -4716,7 +4847,7 @@ static void HWR_ProjectSprite(mobj_t *thing) tz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin); // thing is behind view plane? - if (tz < ZCLIP_PLANE && !papersprite) + if (tz < ZCLIP_PLANE && !(papersprite || splat)) { if (cv_glmodels.value) //Yellow: Only MD2's dont disappear { @@ -4820,7 +4951,7 @@ static void HWR_ProjectSprite(mobj_t *thing) } if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) - this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale); + this_scale *= FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale); spr_width = spritecachedinfo[lumpoff].width; spr_height = spritecachedinfo[lumpoff].height; @@ -4828,7 +4959,8 @@ static void HWR_ProjectSprite(mobj_t *thing) spr_topoffset = spritecachedinfo[lumpoff].topoffset; #ifdef ROTSPRITE - if (thing->rollangle) + if (thing->rollangle + && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { rollangle = R_GetRollAngle(thing->rollangle); rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); @@ -4860,18 +4992,36 @@ static void HWR_ProjectSprite(mobj_t *thing) flip = !flip != !hflip; - spritexscale *= this_scale; - spriteyscale *= this_scale; + if (thing->renderflags & RF_SHADOWEFFECTS) + { + mobj_t *caster = thing->target; + + if (caster && !P_MobjWasRemoved(caster)) + { + fixed_t groundz = R_GetShadowZ(thing, NULL); + fixed_t floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? caster->height : 0) + caster->z - groundz); + + shadowheight = FIXED_TO_FLOAT(floordiff); + shadowscale = FIXED_TO_FLOAT(FixedMul(FRACUNIT - floordiff/640, caster->scale)); + + if (splat) + spritexscale *= shadowscale; + spriteyscale *= shadowscale; + } + } + + this_xscale = spritexscale * this_scale; + this_yscale = spriteyscale * this_scale; if (flip) { - x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * spritexscale); - x2 = (FIXED_TO_FLOAT(spr_offset) * spritexscale); + x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_xscale); + x2 = (FIXED_TO_FLOAT(spr_offset) * this_xscale); } else { - x1 = (FIXED_TO_FLOAT(spr_offset) * spritexscale); - x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * spritexscale); + x1 = (FIXED_TO_FLOAT(spr_offset) * this_xscale); + x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_xscale); } // test if too close @@ -4893,13 +5043,13 @@ static void HWR_ProjectSprite(mobj_t *thing) if (vflip) { - gz = FIXED_TO_FLOAT(thing->z+thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * spriteyscale); - gzt = gz + (FIXED_TO_FLOAT(spr_height) * spriteyscale); + gz = FIXED_TO_FLOAT(thing->z + thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale); + gzt = gz + (FIXED_TO_FLOAT(spr_height) * this_yscale); } else { - gzt = FIXED_TO_FLOAT(thing->z) + (FIXED_TO_FLOAT(spr_topoffset) * spriteyscale); - gz = gzt - (FIXED_TO_FLOAT(spr_height) * spriteyscale); + gzt = FIXED_TO_FLOAT(thing->z) + (FIXED_TO_FLOAT(spr_topoffset) * this_yscale); + gz = gzt - (FIXED_TO_FLOAT(spr_height) * this_yscale); } if (thing->subsector->sector->cullheight) @@ -4956,19 +5106,37 @@ static void HWR_ProjectSprite(mobj_t *thing) vis = HWR_NewVisSprite(); vis->x1 = x1; vis->x2 = x2; + vis->z1 = z1; + vis->z2 = z2; + vis->tz = tz; // Keep tz for the simple sprite sorting that happens vis->tracertz = tracertz; + + vis->renderflags = thing->renderflags; + vis->rotateflags = sprframe->rotate; + + vis->shadowheight = shadowheight; + vis->shadowscale = shadowscale; vis->dispoffset = dispoffset; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST + vis->flip = flip; + + vis->scale = this_scale; + vis->spritexscale = spritexscale; + vis->spriteyscale = spriteyscale; + + vis->rotated = false; + #ifdef ROTSPRITE if (rotsprite) + { vis->gpatch = (patch_t *)rotsprite; + vis->rotated = true; + } else #endif vis->gpatch = (patch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); - vis->flip = flip; + vis->mobj = thing; - vis->z1 = z1; - vis->z2 = z2; //Hurdler: 25/04/2000: now support colormap in hardware mode if ((vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" diff --git a/src/r_defs.h b/src/r_defs.h index d32313a46..749638db3 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -718,8 +718,9 @@ typedef enum RF_HORIZONTALFLIP = 0x0001, // Flip sprite horizontally RF_VERTICALFLIP = 0x0002, // Flip sprite vertically RF_ONESIDED = 0x0004, // Wall/floor sprite is visible from front only - RF_NOSPLATBILLBOARD = 0x0008, // Don't billboard floor sprites (faces forward from the view angle) - RF_NOSPLATROLLANGLE = 0x0010, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead) + RF_SLOPESPLAT = 0x0008, // Rotate floor sprites by the object's standing slope + RF_NOSPLATBILLBOARD = 0x0010, // Don't billboard floor sprites (faces forward from the view angle) + RF_NOSPLATROLLANGLE = 0x0020, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead) RF_BLENDMASK = 0x0F00, // --Blending modes RF_FULLBRIGHT = 0x0100, // Sprite is drawn at full brightness diff --git a/src/r_things.c b/src/r_things.c index 00bb0b32a..79be4c5bd 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1821,15 +1821,17 @@ static void R_ProjectSprite(mobj_t *thing) if (shadowdraw) { - spritexscale = FixedMul(thing->radius * 2, shadowscale); - spriteyscale = FixedMul(thing->radius * 2, shadowscale); + spritexscale = FixedMul(thing->radius * 2, FixedMul(shadowscale, spritexscale)); + spriteyscale = FixedMul(thing->radius * 2, FixedMul(shadowscale, spriteyscale)); spriteyscale = FixedMul(spriteyscale, FixedDiv(abs(groundz - viewz), tz)); spriteyscale = min(spriteyscale, spritexscale) / patch->height; + spritexscale /= patch->width; } else - spritexscale = spriteyscale = shadowscale; - - spritexscale /= patch->width; + { + spritexscale = FixedMul(shadowscale, spritexscale); + spriteyscale = FixedMul(shadowscale, spriteyscale); + } if (shadowskew) { @@ -1951,13 +1953,13 @@ static void R_ProjectSprite(mobj_t *thing) vis->spritexscale = spritexscale; vis->spriteyscale = spriteyscale; + vis->shadowscale = shadowscale; if (shadowdraw || shadoweffects) { iscale = (patch->width<shear.offset = vis->x1-x1; - vis->shadowscale = shadowscale; } else iscale = FixedDiv(FRACUNIT, vis->xscale); @@ -2748,9 +2750,6 @@ static void R_DrawVisSplat(vissprite_t *spr) splat.height = spr->patch->height; splat.scale = spr->mobj->scale; - if (spr->renderflags & RF_SHADOWEFFECTS) - splat.scale = FixedMul(splat.scale, spr->shadowscale); - if (spr->rotateflags & SRF_3D || spr->renderflags & RF_NOSPLATBILLBOARD) splatangle = spr->mobj->angle; else @@ -2767,8 +2766,8 @@ static void R_DrawVisSplat(vissprite_t *spr) if (hflip) leftoffset = ((splat.width * FRACUNIT) - leftoffset); - xscale = spr->mobj->spritexscale; - yscale = spr->mobj->spriteyscale; + xscale = spr->spritexscale; + yscale = spr->spriteyscale; splat.xscale = FixedMul(splat.scale, xscale); splat.yscale = FixedMul(splat.scale, yscale); From a91a55fb580b5b22fef1a1f94d3c46998173c787 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 12 Oct 2020 22:07:11 -0300 Subject: [PATCH 15/81] Fix floorsprites not being rendered when viewed from the bottom --- src/r_splats.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/r_splats.c b/src/r_splats.c index 0b2826107..cddbbf85f 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -261,6 +261,13 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis) x1 = rastertab[y].minx>>FRACBITS; x2 = rastertab[y].maxx>>FRACBITS; + if (x1 > x2) + { + INT32 swap = x1; + x1 = x2; + x2 = swap; + } + if (x1 < 0) x1 = 0; if (x2 >= vid.width) From b7590971f42125cf47e34509568be4d3ebc94f2a Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 12 Oct 2020 22:08:45 -0300 Subject: [PATCH 16/81] Fix uninitialized variable warning --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 98f3d69da..5c450e9d2 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4092,7 +4092,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) // colormap test { sector_t *sector = spr->mobj->subsector->sector; - UINT8 lightlevel; + UINT8 lightlevel = 0; boolean lightset = true; extracolormap_t *colormap = sector->extra_colormap; From 3849b4ac6c972809154fcec675b4081b6663903c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 13 Oct 2020 00:14:27 -0300 Subject: [PATCH 17/81] Fix other uninitialized variable warnings --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 79be4c5bd..f1d564362 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1456,7 +1456,7 @@ static void R_ProjectSprite(mobj_t *thing) INT32 dispoffset = thing->info->dispoffset; //SoM: 3/17/2000 - fixed_t gz, gzt; + fixed_t gz = 0, gzt = 0; INT32 heightsec, phs; INT32 light = 0; fixed_t this_scale = thing->scale; From cd87c6a5fbe4cf19df582932f47662a1aacb3d36 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 13 Oct 2020 01:09:17 -0300 Subject: [PATCH 18/81] Fix splat sorting --- src/r_things.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index f1d564362..d873b806b 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2630,7 +2630,32 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps } else if (r2->sprite) { - if (!(r2->sprite->cut & SC_SPLAT || rover->cut & SC_SPLAT)) + boolean infront = (r2->sprite->sortscale > rover->sortscale + || (r2->sprite->sortscale == rover->sortscale && r2->sprite->dispoffset > rover->dispoffset)); + + if (rover->cut & SC_SPLAT + && r2->sprite->cut & SC_SPLAT) + { + fixed_t z1 = 0, z2 = 0; + + if (rover->mobj->z - viewz > 0) + { + z1 = rover->pz; + z2 = r2->sprite->pz; + } + else + { + z1 = r2->sprite->pz; + z2 = rover->pz; + } + + z1 -= viewz; + z2 -= viewz; + + if (z1 >= z2) + infront = true; + } + else { if (r2->sprite->x1 > rover->x2 || r2->sprite->x2 < rover->x1) continue; @@ -2638,8 +2663,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps continue; } - if (r2->sprite->sortscale > rover->sortscale - || (r2->sprite->sortscale == rover->sortscale && r2->sprite->dispoffset > rover->dispoffset)) + if (infront) { entry = R_CreateDrawNode(NULL); (entry->prev = r2->prev)->next = entry; From ecd3ef99fcca2f527312b3c047cd20a881925d27 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 13 Oct 2020 01:45:18 -0300 Subject: [PATCH 19/81] Improve splat sorting: Adjust the sort scale of splats Do splat sorting in R_CreateDrawNodes if either vissprite is a splat, instead of if both are --- src/r_things.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index d873b806b..56b645bf9 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1743,6 +1743,18 @@ static void R_ProjectSprite(mobj_t *thing) return; } + // Adjust sort scale + tr_x = tr_y = 0; + + if (splat) + { + tz = (patch->height - patch->topoffset) * FRACUNIT; + ang = (viewangle >> ANGLETOFINESHIFT); + + tr_x = FixedMul(FixedMul(FixedMul(spritexscale, this_scale), tz), FINECOSINE(ang)); + tr_y = FixedMul(FixedMul(FixedMul(spriteyscale, this_scale), tz), FINESINE(ang)); + } + if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY) { fixed_t linkscale; @@ -1752,8 +1764,8 @@ static void R_ProjectSprite(mobj_t *thing) if (! R_ThingVisible(thing)) return; - tr_x = thing->x - viewx; - tr_y = thing->y - viewy; + tr_x = (thing->x + tr_x) - viewx; + tr_y = (thing->y + tr_y) - viewy; tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); linkscale = FixedDiv(projectiony, tz); @@ -1766,6 +1778,13 @@ static void R_ProjectSprite(mobj_t *thing) sortscale = linkscale; // now make sure it's linked cut |= SC_LINKDRAW; } + else if (splat) + { + tr_x = (thing->x + tr_x) - viewx; + tr_y = (thing->y + tr_y) - viewy; + tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); + sortscale = FixedDiv(projectiony, tz); + } // PORTAL SPRITE CLIPPING if (portalrender && portalclipline) @@ -2634,7 +2653,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps || (r2->sprite->sortscale == rover->sortscale && r2->sprite->dispoffset > rover->dispoffset)); if (rover->cut & SC_SPLAT - && r2->sprite->cut & SC_SPLAT) + || r2->sprite->cut & SC_SPLAT) { fixed_t z1 = 0, z2 = 0; @@ -2652,8 +2671,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps z1 -= viewz; z2 -= viewz; - if (z1 >= z2) - infront = true; + infront = (z1 >= z2); } else { From e8dd79e5e2a191c616675347f73b4e557e6b648e Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 13 Oct 2020 02:24:18 -0300 Subject: [PATCH 20/81] Improve sorting between sprites and floor sprites --- src/r_things.c | 67 ++++++++++++++++++++++++++++++-------------------- src/r_things.h | 4 ++- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 56b645bf9..e23c08eb1 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1413,7 +1413,9 @@ static void R_ProjectSprite(mobj_t *thing) mobj_t *oldthing = thing; fixed_t tr_x, tr_y; fixed_t tx, tz; - fixed_t xscale, yscale, sortscale; //added : 02-02-98 : aaargll..if I were a math-guy!!! + fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!! + fixed_t sortscale, sortsplat = 0; + fixed_t sort_x = 0, sort_y = 0; INT32 x1, x2; @@ -1743,16 +1745,13 @@ static void R_ProjectSprite(mobj_t *thing) return; } - // Adjust sort scale - tr_x = tr_y = 0; - + // Adjust the sort scale if needed if (splat) { tz = (patch->height - patch->topoffset) * FRACUNIT; ang = (viewangle >> ANGLETOFINESHIFT); - - tr_x = FixedMul(FixedMul(FixedMul(spritexscale, this_scale), tz), FINECOSINE(ang)); - tr_y = FixedMul(FixedMul(FixedMul(spriteyscale, this_scale), tz), FINESINE(ang)); + sort_x = FixedMul(FixedMul(FixedMul(spritexscale, this_scale), tz), FINECOSINE(ang)); + sort_y = FixedMul(FixedMul(FixedMul(spriteyscale, this_scale), tz), FINESINE(ang)); } if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY) @@ -1764,8 +1763,8 @@ static void R_ProjectSprite(mobj_t *thing) if (! R_ThingVisible(thing)) return; - tr_x = (thing->x + tr_x) - viewx; - tr_y = (thing->y + tr_y) - viewy; + tr_x = (thing->x + sort_x) - viewx; + tr_y = (thing->y + sort_y) - viewy; tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); linkscale = FixedDiv(projectiony, tz); @@ -1780,12 +1779,21 @@ static void R_ProjectSprite(mobj_t *thing) } else if (splat) { - tr_x = (thing->x + tr_x) - viewx; - tr_y = (thing->y + tr_y) - viewy; + tr_x = (thing->x + sort_x) - viewx; + tr_y = (thing->y + sort_y) - viewy; tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); sortscale = FixedDiv(projectiony, tz); } + // Calculate the splat's sortscale + if (splat) + { + tr_x = (thing->x - sort_x) - viewx; + tr_y = (thing->y - sort_y) - viewy; + tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); + sortsplat = FixedDiv(projectiony, tz); + } + // PORTAL SPRITE CLIPPING if (portalrender && portalclipline) { @@ -1936,6 +1944,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->heightsec = heightsec; //SoM: 3/17/2000 vis->mobjflags = thing->flags; vis->sortscale = sortscale; + vis->sortsplat = sortsplat; vis->dispoffset = dispoffset; // Monster Iestyn: 23/11/15 vis->gx = thing->x; vis->gy = thing->y; @@ -2652,26 +2661,32 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps boolean infront = (r2->sprite->sortscale > rover->sortscale || (r2->sprite->sortscale == rover->sortscale && r2->sprite->dispoffset > rover->dispoffset)); - if (rover->cut & SC_SPLAT - || r2->sprite->cut & SC_SPLAT) + if (rover->cut & SC_SPLAT || r2->sprite->cut & SC_SPLAT) { - fixed_t z1 = 0, z2 = 0; + fixed_t scale1 = (rover->cut & SC_SPLAT ? rover->sortsplat : rover->sortscale); + fixed_t scale2 = (r2->sprite->cut & SC_SPLAT ? r2->sprite->sortsplat : r2->sprite->sortscale); + boolean behind = (scale2 > scale1 || (scale2 == scale1 && r2->sprite->dispoffset > rover->dispoffset)); - if (rover->mobj->z - viewz > 0) + if (!behind) { - z1 = rover->pz; - z2 = r2->sprite->pz; - } - else - { - z1 = r2->sprite->pz; - z2 = rover->pz; - } + fixed_t z1 = 0, z2 = 0; - z1 -= viewz; - z2 -= viewz; + if (rover->mobj->z - viewz > 0) + { + z1 = rover->pz; + z2 = r2->sprite->pz; + } + else + { + z1 = r2->sprite->pz; + z2 = rover->pz; + } - infront = (z1 >= z2); + z1 -= viewz; + z2 -= viewz; + + infront = (z1 >= z2); + } } else { diff --git a/src/r_things.h b/src/r_things.h index 16cf5088f..643b2ca9e 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -155,7 +155,9 @@ typedef struct vissprite_s fixed_t pz, pzt; // physical bottom/top for sorting with 3D floors fixed_t startfrac; // horizontal position of x1 - fixed_t scale, sortscale; // sortscale only differs from scale for paper sprites and MF2_LINKDRAW + fixed_t scale; + fixed_t sortscale; // sortscale only differs from scale for paper sprites, floor sprites, and MF2_LINKDRAW + fixed_t sortsplat; // the sortscale from behind the floor sprite fixed_t scalestep; // only for paper sprites, 0 otherwise fixed_t paperoffset, paperdistance; // for paper sprites, offset/dist relative to the angle fixed_t xiscale; // negative if flipped From a6f2e8b9c65b6bcc43729a58f12f937f6493e93c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 13 Oct 2020 12:57:36 -0300 Subject: [PATCH 21/81] Implement relative and absolute sprite offsets for objects (mobjs) Added RF_ABSOLUTEOFFSETS and RF_FLIPOFFSETS --- src/d_clisrv.c | 16 ++++++++++---- src/d_clisrv.h | 8 +++++-- src/dehacked.c | 4 +++- src/hardware/hw_glob.h | 4 +++- src/hardware/hw_main.c | 22 +++++++++++++++++-- src/lua_mobjlib.c | 48 ++++++++++++++++++++++++++++-------------- src/p_mobj.c | 5 ++++- src/p_mobj.h | 10 +++++++-- src/p_saveg.c | 18 ++++++++++++++-- src/r_defs.h | 10 +++++---- src/r_things.c | 25 +++++++++++++++++++--- src/r_things.h | 2 ++ 12 files changed, 134 insertions(+), 38 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3db5a6207..636e2bfa8 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -643,6 +643,12 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->frame = LONG(players[i].mo->frame); rsp->sprite2 = players[i].mo->sprite2; rsp->anim_duration = SHORT(players[i].mo->anim_duration); + + rsp->spritexscale = LONG(players[i].mo->spritexscale); + rsp->spriteyscale = LONG(players[i].mo->spriteyscale); + rsp->spritexoffset = LONG(players[i].mo->spritexoffset); + rsp->spriteyoffset = LONG(players[i].mo->spriteyoffset); + rsp->tics = LONG(players[i].mo->tics); rsp->statenum = (statenum_t)LONG(players[i].mo->state-states); // :( rsp->eflags = (UINT16)SHORT(players[i].mo->eflags); @@ -655,8 +661,6 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->scale = LONG(players[i].mo->scale); rsp->destscale = LONG(players[i].mo->destscale); rsp->scalespeed = LONG(players[i].mo->scalespeed); - rsp->spritexscale = LONG(players[i].mo->spritexscale); - rsp->spriteyscale = LONG(players[i].mo->spriteyscale); } static void resynch_read_player(resynch_pak *rsp) @@ -805,6 +809,12 @@ static void resynch_read_player(resynch_pak *rsp) players[i].mo->frame = LONG(rsp->frame); players[i].mo->sprite2 = rsp->sprite2; players[i].mo->anim_duration = SHORT(rsp->anim_duration); + + players[i].mo->spritexscale = LONG(rsp->spritexscale); + players[i].mo->spriteyscale = LONG(rsp->spriteyscale); + players[i].mo->spritexoffset = LONG(rsp->spritexoffset); + players[i].mo->spriteyoffset = LONG(rsp->spriteyoffset); + players[i].mo->tics = LONG(rsp->tics); players[i].mo->state = &states[LONG(rsp->statenum)]; @@ -817,8 +827,6 @@ static void resynch_read_player(resynch_pak *rsp) players[i].mo->scale = LONG(rsp->scale); players[i].mo->destscale = LONG(rsp->destscale); players[i].mo->scalespeed = LONG(rsp->scalespeed); - players[i].mo->spritexscale = LONG(rsp->spritexscale); - players[i].mo->spriteyscale = LONG(rsp->spriteyscale); // And finally, SET THE MOBJ SKIN damn it. if ((players[i].powers[pw_carry] == CR_NIGHTSMODE) && (skins[players[i].skin].sprites[SPR2_NFLY].numframes == 0)) diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 0ed0b10f5..94cec3ff7 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -288,6 +288,12 @@ typedef struct UINT32 frame; UINT8 sprite2; UINT16 anim_duration; + + fixed_t spritexscale; + fixed_t spriteyscale; + fixed_t spritexoffset; + fixed_t spriteyoffset; + INT32 tics; statenum_t statenum; UINT32 flags; @@ -300,8 +306,6 @@ typedef struct fixed_t scale; fixed_t destscale; fixed_t scalespeed; - fixed_t spritexscale; - fixed_t spriteyscale; } ATTRPACK resynch_pak; typedef struct diff --git a/src/dehacked.c b/src/dehacked.c index aa4a04be4..0662074ba 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9583,10 +9583,12 @@ struct { // Render flags {"RF_HORIZONTALFLIP",RF_HORIZONTALFLIP}, {"RF_VERTICALFLIP",RF_VERTICALFLIP}, - {"RF_ONESIDED",RF_ONESIDED}, + {"RF_ABSOLUTEOFFSETS",RF_ABSOLUTEOFFSETS}, + {"RF_FLIPOFFSETS",RF_FLIPOFFSETS}, {"RF_SLOPESPLAT",RF_SLOPESPLAT}, {"RF_NOSPLATBILLBOARD",RF_NOSPLATBILLBOARD}, {"RF_NOSPLATROLLANGLE",RF_NOSPLATROLLANGLE}, + {"RF_BLENDMASK",RF_BLENDMASK}, {"RF_FULLBRIGHT",RF_FULLBRIGHT}, {"RF_FULLDARK",RF_FULLDARK}, {"RF_SPRITETYPEMASK",RF_SPRITETYPEMASK}, diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index cb517b611..6a9bb257c 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -69,9 +69,11 @@ typedef struct gl_vissprite_s float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting float scale; - float spritexscale, spriteyscale; float shadowheight, shadowscale; + float spritexscale, spriteyscale; + float spritexoffset, spriteyoffset; + UINT32 renderflags; UINT8 rotateflags; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 5c450e9d2..315737108 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3966,8 +3966,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) angle = -angle; angle += ANGLE_90; - topoffset = (float)gpatch->topoffset; - leftoffset = (float)gpatch->leftoffset; + topoffset = spr->spriteyoffset; + leftoffset = spr->spritexoffset; if (spr->flip) leftoffset = ((float)gpatch->width - leftoffset); @@ -4979,6 +4979,22 @@ static void HWR_ProjectSprite(mobj_t *thing) } #endif + if (thing->renderflags & RF_ABSOLUTEOFFSETS) + { + spr_offset = thing->spritexoffset; + spr_topoffset = thing->spriteyoffset; + } + else + { + SINT8 flipoffset = 1; + + if ((thing->renderflags & RF_FLIPOFFSETS) && flip) + flipoffset = -1; + + spr_offset += thing->spritexoffset * flipoffset; + spr_topoffset += thing->spriteyoffset * flipoffset; + } + if (papersprite) { rightsin = FIXED_TO_FLOAT(FINESINE((mobjangle)>>ANGLETOFINESHIFT)); @@ -5123,6 +5139,8 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->scale = this_scale; vis->spritexscale = spritexscale; vis->spriteyscale = spriteyscale; + vis->spritexoffset = FIXED_TO_FLOAT(spr_offset); + vis->spriteyoffset = FIXED_TO_FLOAT(spr_topoffset); vis->rotated = false; diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index c390eb064..a544f151c 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -39,6 +39,10 @@ enum mobj_e { mobj_frame, mobj_sprite2, mobj_anim_duration, + mobj_spritexscale, + mobj_spriteyscale, + mobj_spritexoffset, + mobj_spriteyoffset, mobj_touching_sectorlist, mobj_subsector, mobj_floorz, @@ -84,8 +88,6 @@ enum mobj_e { mobj_scale, mobj_destscale, mobj_scalespeed, - mobj_spritexscale, - mobj_spriteyscale, mobj_extravalue1, mobj_extravalue2, mobj_cusval, @@ -111,6 +113,10 @@ static const char *const mobj_opt[] = { "frame", "sprite2", "anim_duration", + "spritexscale", + "spriteyscale", + "spritexoffset", + "spriteyoffset", "touching_sectorlist", "subsector", "floorz", @@ -156,8 +162,6 @@ static const char *const mobj_opt[] = { "scale", "destscale", "scalespeed", - "spritexscale", - "spriteyscale", "extravalue1", "extravalue2", "cusval", @@ -233,6 +237,18 @@ static int mobj_get(lua_State *L) case mobj_anim_duration: lua_pushinteger(L, mo->anim_duration); break; + case mobj_spritexscale: + lua_pushfixed(L, mo->spritexscale); + break; + case mobj_spriteyscale: + lua_pushfixed(L, mo->spriteyscale); + break; + case mobj_spritexoffset: + lua_pushfixed(L, mo->spritexoffset); + break; + case mobj_spriteyoffset: + lua_pushfixed(L, mo->spriteyoffset); + break; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: @@ -390,12 +406,6 @@ static int mobj_get(lua_State *L) case mobj_scalespeed: lua_pushfixed(L, mo->scalespeed); break; - case mobj_spritexscale: - lua_pushfixed(L, mo->spritexscale); - break; - case mobj_spriteyscale: - lua_pushfixed(L, mo->spriteyscale); - break; case mobj_extravalue1: lua_pushinteger(L, mo->extravalue1); break; @@ -507,6 +517,18 @@ static int mobj_set(lua_State *L) case mobj_anim_duration: mo->anim_duration = (UINT16)luaL_checkinteger(L, 3); break; + case mobj_spritexscale: + mo->spritexscale = luaL_checkfixed(L, 3); + break; + case mobj_spriteyscale: + mo->spriteyscale = luaL_checkfixed(L, 3); + break; + case mobj_spritexoffset: + mo->spritexoffset = luaL_checkfixed(L, 3); + break; + case mobj_spriteyoffset: + mo->spriteyoffset = luaL_checkfixed(L, 3); + break; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: @@ -739,12 +761,6 @@ static int mobj_set(lua_State *L) case mobj_scalespeed: mo->scalespeed = luaL_checkfixed(L, 3); break; - case mobj_spritexscale: - mo->spritexscale = luaL_checkfixed(L, 3); - break; - case mobj_spriteyscale: - mo->spriteyscale = luaL_checkfixed(L, 3); - break; case mobj_extravalue1: mo->extravalue1 = luaL_checkinteger(L, 3); break; diff --git a/src/p_mobj.c b/src/p_mobj.c index 827650ce6..2260ace51 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10465,12 +10465,15 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->scale = FRACUNIT; mobj->destscale = mobj->scale; mobj->scalespeed = FRACUNIT/12; - mobj->spritexscale = mobj->spriteyscale = mobj->scale; // TODO: Make this a special map header if ((maptol & TOL_ERZ3) && !(mobj->type == MT_BLACKEGGMAN)) mobj->destscale = FRACUNIT/2; + // Sprite rendering + mobj->spritexscale = mobj->spriteyscale = mobj->scale; + mobj->spritexoffset = mobj->spriteyoffset = 0; + // set subsector and/or block links P_SetThingPosition(mobj); I_Assert(mobj->subsector != NULL); diff --git a/src/p_mobj.h b/src/p_mobj.h index eb8a9ccc2..0b688a9ad 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -286,6 +286,10 @@ typedef struct mobj_s UINT8 sprite2; // player sprites UINT16 anim_duration; // for FF_ANIMATE states + UINT32 renderflags; // render flags + fixed_t spritexscale, spriteyscale; + fixed_t spritexoffset, spriteyoffset; + struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears struct subsector_s *subsector; // Subsector the mobj resides in. @@ -309,7 +313,6 @@ typedef struct mobj_s UINT32 flags; // flags from mobjinfo tables UINT32 flags2; // MF2_ flags UINT16 eflags; // extra flags - UINT32 renderflags; // render flags void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin) // Player and mobj sprites in multiplayer modes are modified @@ -362,7 +365,6 @@ typedef struct mobj_s fixed_t scale; fixed_t destscale; fixed_t scalespeed; - fixed_t spritexscale, spriteyscale; // Extra values are for internal use for whatever you want INT32 extravalue1; @@ -409,6 +411,10 @@ typedef struct precipmobj_s UINT8 sprite2; // player sprites UINT16 anim_duration; // for FF_ANIMATE states + UINT32 renderflags; // render flags + fixed_t spritexscale, spriteyscale; + fixed_t spritexoffset, spriteyoffset; + struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears struct subsector_s *subsector; // Subsector the mobj resides in. diff --git a/src/p_saveg.c b/src/p_saveg.c index d613efd70..3a9663326 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1395,8 +1395,10 @@ typedef enum MD2_ROLLANGLE = 1<<14, MD2_SPRITEXSCALE = 1<<15, MD2_SPRITEYSCALE = 1<<16, - MD2_SHADOWSCALE = 1<<17, - MD2_RENDERFLAGS = 1<<18, + MD2_SPRITEXOFFSET = 1<<17, + MD2_SPRITEYOFFSET = 1<<18, + MD2_SHADOWSCALE = 1<<19, + MD2_RENDERFLAGS = 1<<20, } mobj_diff2_t; typedef enum @@ -1611,6 +1613,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_SPRITEXSCALE; if (mobj->spriteyscale != FRACUNIT) diff2 |= MD2_SPRITEYSCALE; + if (mobj->spritexoffset) + diff2 |= MD2_SPRITEXOFFSET; + if (mobj->spriteyoffset) + diff2 |= MD2_SPRITEYOFFSET; if (mobj->shadowscale) diff2 |= MD2_SHADOWSCALE; if (mobj->renderflags) @@ -1759,6 +1765,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->spritexscale); if (diff2 & MD2_SPRITEYSCALE) WRITEFIXED(save_p, mobj->spriteyscale); + if (diff2 & MD2_SPRITEXOFFSET) + WRITEFIXED(save_p, mobj->spritexoffset); + if (diff2 & MD2_SPRITEYOFFSET) + WRITEFIXED(save_p, mobj->spriteyoffset); if (diff2 & MD2_SHADOWSCALE) WRITEFIXED(save_p, mobj->shadowscale); if (diff2 & MD2_RENDERFLAGS) @@ -2774,6 +2784,10 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->spritexscale = READFIXED(save_p); if (diff2 & MD2_SPRITEYSCALE) mobj->spriteyscale = READFIXED(save_p); + if (diff2 & MD2_SPRITEXOFFSET) + mobj->spritexoffset = READFIXED(save_p); + if (diff2 & MD2_SPRITEYOFFSET) + mobj->spriteyoffset = READFIXED(save_p); if (diff2 & MD2_SHADOWSCALE) mobj->shadowscale = READFIXED(save_p); if (diff2 & MD2_RENDERFLAGS) diff --git a/src/r_defs.h b/src/r_defs.h index 749638db3..7b7c5d7f0 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -717,10 +717,12 @@ typedef enum { RF_HORIZONTALFLIP = 0x0001, // Flip sprite horizontally RF_VERTICALFLIP = 0x0002, // Flip sprite vertically - RF_ONESIDED = 0x0004, // Wall/floor sprite is visible from front only - RF_SLOPESPLAT = 0x0008, // Rotate floor sprites by the object's standing slope - RF_NOSPLATBILLBOARD = 0x0010, // Don't billboard floor sprites (faces forward from the view angle) - RF_NOSPLATROLLANGLE = 0x0020, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead) + RF_ABSOLUTEOFFSETS = 0x0004, // Sprite uses the object's offsets absolutely, instead of relatively + RF_FLIPOFFSETS = 0x0008, // Relative object offsets are flipped with the sprite + + RF_SLOPESPLAT = 0x0010, // Rotate floor sprites by the object's standing slope + RF_NOSPLATBILLBOARD = 0x0020, // Don't billboard floor sprites (faces forward from the view angle) + RF_NOSPLATROLLANGLE = 0x0040, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead) RF_BLENDMASK = 0x0F00, // --Blending modes RF_FULLBRIGHT = 0x0100, // Sprite is drawn at full brightness diff --git a/src/r_things.c b/src/r_things.c index e23c08eb1..d60228e36 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1632,6 +1632,22 @@ static void R_ProjectSprite(mobj_t *thing) if (spritexscale < 1 || spriteyscale < 1) return; + if (thing->renderflags & RF_ABSOLUTEOFFSETS) + { + spr_offset = thing->spritexoffset; + spr_topoffset = thing->spriteyoffset; + } + else + { + SINT8 flipoffset = 1; + + if ((thing->renderflags & RF_FLIPOFFSETS) && flip) + flipoffset = -1; + + spr_offset += thing->spritexoffset * flipoffset; + spr_topoffset += thing->spriteyoffset * flipoffset; + } + if (flip) offset = spr_offset - spr_width; else @@ -1981,7 +1997,8 @@ static void R_ProjectSprite(mobj_t *thing) vis->spritexscale = spritexscale; vis->spriteyscale = spriteyscale; - vis->shadowscale = shadowscale; + vis->spritexoffset = spr_offset; + vis->spriteyoffset = spr_topoffset; if (shadowdraw || shadoweffects) { @@ -1992,6 +2009,8 @@ static void R_ProjectSprite(mobj_t *thing) else iscale = FixedDiv(FRACUNIT, vis->xscale); + vis->shadowscale = shadowscale; + if (flip) { vis->startfrac = spr_width-1; @@ -2818,8 +2837,8 @@ static void R_DrawVisSplat(vissprite_t *spr) splat.angle = -splatangle; splat.angle += ANGLE_90; - topoffset = (spr->patch->topoffset * FRACUNIT); - leftoffset = (spr->patch->leftoffset * FRACUNIT); + topoffset = spr->spriteyoffset; + leftoffset = spr->spritexoffset; if (hflip) leftoffset = ((splat.width * FRACUNIT) - leftoffset); diff --git a/src/r_things.h b/src/r_things.h index 643b2ca9e..f960089a1 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -195,6 +195,8 @@ typedef struct vissprite_s UINT8 rotateflags; fixed_t spritexscale, spriteyscale; + fixed_t spritexoffset, spriteyoffset; + fixed_t shadowscale; INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; From 394150fca49085c24440e77c8692ab24981b1794 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 13 Oct 2020 17:03:50 -0300 Subject: [PATCH 22/81] Fix infinitely long splat spans --- src/r_splats.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/r_splats.c b/src/r_splats.c index cddbbf85f..fa4d9eef8 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -268,6 +268,9 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis) x2 = swap; } + if (x1 == INT16_MIN || x2 == INT16_MAX) + continue; + if (x1 < 0) x1 = 0; if (x2 >= vid.width) From 53a5e758558a38c2c57beef8cc5042bf0111d68d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 13 Oct 2020 19:16:25 -0300 Subject: [PATCH 23/81] Correctly return the output patch's size in Picture_PatchConvert --- src/r_picformats.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/r_picformats.c b/src/r_picformats.c index 8ec78663e..ffef4c2f2 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -352,20 +352,26 @@ void *Picture_PatchConvert( img = Z_Malloc(size, PU_STATIC, NULL); memcpy(img, imgbuf, size); - if (outsize != NULL) - *outsize = size; - if (Picture_IsInternalPatchFormat(outformat)) { patch_t *converted = Patch_Create((softwarepatch_t *)img, size, NULL); + #ifdef HWRENDER Patch_CreateGL(converted); #endif + Z_Free(img); + + if (outsize != NULL) + *outsize = sizeof(patch_t); return converted; } else + { + if (outsize != NULL) + *outsize = size; return img; + } } /** Converts a picture to a flat. From bf9a8d9f3b47dff0ec62ab6839e3d1e289344ac0 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 13 Oct 2020 19:18:01 -0300 Subject: [PATCH 24/81] Fix the wrong freeing function call being used in Patch_FreeData --- src/r_patch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_patch.c b/src/r_patch.c index 9b1e7d1b8..c78ffdd67 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -77,7 +77,7 @@ static void Patch_FreeData(patch_t *patch) for (i = 0; i < 2; i++) { if (patch->flats[i]) - Patch_Free(patch->flats[i]); + Z_Free(patch->flats[i]); } #ifdef ROTSPRITE From f93e0505696eb84bcef8468ff978c707d723d13a Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 13 Oct 2020 22:42:07 -0300 Subject: [PATCH 25/81] Implement sloped floor sprites --- src/r_draw.h | 39 ++++-- src/r_draw8.c | 235 +++++++++++++++++++++++++++++++-- src/r_draw8_npo2.c | 317 +++++++++++++++++++++++++++++++++++++++++++-- src/r_plane.c | 90 +++++++------ src/r_plane.h | 8 +- src/r_splats.c | 155 +++++++++++----------- src/r_splats.h | 8 +- src/r_things.c | 73 +++++++++-- src/screen.c | 4 + src/screen.h | 2 + 10 files changed, 757 insertions(+), 174 deletions(-) diff --git a/src/r_draw.h b/src/r_draw.h index d77bbedd3..5011d29d9 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -150,42 +150,53 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void); void R_DrawFogColumn_8(void); void R_DrawColumnShadowed_8(void); +#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan)) + void R_DrawSpan_8(void); -void R_DrawSplat_8(void); -void R_DrawFloorSprite_8(void); void R_DrawTranslucentSpan_8(void); -void R_DrawTranslucentSplat_8(void); -void R_DrawTranslucentFloorSprite_8(void); void R_DrawTiltedSpan_8(void); void R_DrawTiltedTranslucentSpan_8(void); -#ifndef NOWATER -void R_DrawTiltedTranslucentWaterSpan_8(void); -#endif + +void R_DrawSplat_8(void); +void R_DrawTranslucentSplat_8(void); void R_DrawTiltedSplat_8(void); + +void R_DrawFloorSprite_8(void); +void R_DrawTranslucentFloorSprite_8(void); +void R_DrawTiltedFloorSprite_8(void); +void R_DrawTiltedTranslucentFloorSprite_8(void); + void R_CalcTiltedLighting(fixed_t start, fixed_t end); extern INT32 tiltlighting[MAXVIDWIDTH]; + #ifndef NOWATER void R_DrawTranslucentWaterSpan_8(void); +void R_DrawTiltedTranslucentWaterSpan_8(void); + extern INT32 ds_bgofs; extern INT32 ds_waterofs; #endif + void R_DrawFogSpan_8(void); // Lactozilla: Non-powers-of-two void R_DrawSpan_NPO2_8(void); void R_DrawTranslucentSpan_NPO2_8(void); -void R_DrawFloorSprite_NPO2_8(void); -void R_DrawSplat_NPO2_8(void); -void R_DrawTranslucentSplat_NPO2_8(void); -void R_DrawTranslucentFloorSprite_NPO2_8(void); void R_DrawTiltedSpan_NPO2_8(void); void R_DrawTiltedTranslucentSpan_NPO2_8(void); -#ifndef NOWATER -void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void); -#endif + +void R_DrawSplat_NPO2_8(void); +void R_DrawTranslucentSplat_NPO2_8(void); void R_DrawTiltedSplat_NPO2_8(void); + +void R_DrawFloorSprite_NPO2_8(void); +void R_DrawTranslucentFloorSprite_NPO2_8(void); +void R_DrawTiltedFloorSprite_NPO2_8(void); +void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void); + #ifndef NOWATER void R_DrawTranslucentWaterSpan_NPO2_8(void); +void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void); #endif #ifdef USEASM diff --git a/src/r_draw8.c b/src/r_draw8.c index bc39e91a5..c28a25cbc 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -536,6 +536,9 @@ void R_DrawTranslatedColumn_8(void) // SPANS // ========================================================================== +#define SPANSIZE 16 +#define INVSPAN 0.0625f + /** \brief The R_DrawSpan_8 function Draws the actual span. */ @@ -643,8 +646,6 @@ void R_CalcTiltedLighting(fixed_t start, fixed_t end) } } -#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan)) - /** \brief The R_DrawTiltedSpan_8 function Draw slopes! Holy sheit! */ @@ -704,9 +705,6 @@ void R_DrawTiltedSpan_8(void) vz += ds_svp->x; } while (--width >= 0); #else -#define SPANSIZE 16 -#define INVSPAN 0.0625f - startz = 1.f/iz; startu = uz*startz; startv = vz*startz; @@ -839,9 +837,6 @@ void R_DrawTiltedTranslucentSpan_8(void) vz += ds_svp->x; } while (--width >= 0); #else -#define SPANSIZE 16 -#define INVSPAN 0.0625f - startz = 1.f/iz; startu = uz*startz; startv = vz*startz; @@ -977,9 +972,6 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) vz += ds_svp->x; } while (--width >= 0); #else -#define SPANSIZE 16 -#define INVSPAN 0.0625f - startz = 1.f/iz; startu = uz*startz; startv = vz*startz; @@ -1116,9 +1108,6 @@ void R_DrawTiltedSplat_8(void) vz += ds_svp->x; } while (--width >= 0); #else -#define SPANSIZE 16 -#define INVSPAN 0.0625f - startz = 1.f/iz; startu = uz*startz; startv = vz*startz; @@ -1643,6 +1632,224 @@ void R_DrawTranslucentFloorSprite_8 (void) } } +/** \brief The R_DrawTiltedFloorSprite_8 function + Draws a tilted floor sprite. +*/ +void R_DrawTiltedFloorSprite_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT16 *source; + UINT8 *colormap; + UINT8 *translation; + UINT8 *dest; + UINT16 val; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + source = (UINT16 *)ds_source; + colormap = ds_colormap; + translation = ds_translation; + + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (i = SPANSIZE-1; i >= 0; i--) + { + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val & 0xFF00) + *dest = colormap[translation[val & 0xFF]]; + dest++; + + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val & 0xFF00) + *dest = colormap[translation[val & 0xFF]]; + } + else + { + double left = width; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (; width != 0; width--) + { + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val & 0xFF00) + *dest = colormap[translation[val & 0xFF]]; + dest++; + + u += stepu; + v += stepv; + } + } + } +} + +/** \brief The R_DrawTiltedTranslucentFloorSprite_8 function + Draws a tilted, translucent, floor sprite. +*/ +void R_DrawTiltedTranslucentFloorSprite_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT16 *source; + UINT8 *colormap; + UINT8 *translation; + UINT8 *dest; + UINT16 val; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + source = (UINT16 *)ds_source; + colormap = ds_colormap; + translation = ds_translation; + + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (i = SPANSIZE-1; i >= 0; i--) + { + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val & 0xFF00) + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + dest++; + + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val & 0xFF00) + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + } + else + { + double left = width; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (; width != 0; width--) + { + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val & 0xFF00) + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + dest++; + + u += stepu; + v += stepv; + } + } + } +} + /** \brief The R_DrawTranslucentSpan_8 function Draws the actual span with translucency. */ diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 087a8d30c..895869e2d 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -15,6 +15,9 @@ // SPANS // ========================================================================== +#define SPANSIZE 16 +#define INVSPAN 0.0625f + /** \brief The R_DrawSpan_NPO2_8 function Draws the actual span. */ @@ -61,8 +64,6 @@ void R_DrawSpan_NPO2_8 (void) } } -#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan)) - /** \brief The R_DrawTiltedSpan_NPO2_8 function Draw slopes! Holy sheit! */ @@ -137,9 +138,6 @@ void R_DrawTiltedSpan_NPO2_8(void) vz += ds_svp->x; } while (--width >= 0); #else -#define SPANSIZE 16 -#define INVSPAN 0.0625f - startz = 1.f/iz; startu = uz*startz; startv = vz*startz; @@ -332,9 +330,6 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) vz += ds_svp->x; } while (--width >= 0); #else -#define SPANSIZE 16 -#define INVSPAN 0.0625f - startz = 1.f/iz; startu = uz*startz; startv = vz*startz; @@ -531,9 +526,6 @@ void R_DrawTiltedSplat_NPO2_8(void) vz += ds_svp->x; } while (--width >= 0); #else -#define SPANSIZE 16 -#define INVSPAN 0.0625f - startz = 1.f/iz; startu = uz*startz; startv = vz*startz; @@ -852,6 +844,306 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void) } } +/** \brief The R_DrawTiltedFloorSprite_NPO2_8 function + Draws a tilted floor sprite. +*/ +void R_DrawTiltedFloorSprite_NPO2_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT16 *source; + UINT8 *colormap; + UINT8 *translation; + UINT8 *dest; + UINT16 val; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + source = (UINT16 *)ds_source; + colormap = ds_colormap; + translation = ds_translation; + + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (i = SPANSIZE-1; i >= 0; i--) + { + // Lactozilla: Non-powers-of-two + 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)]; + if (val & 0xFF00) + *dest = colormap[translation[val & 0xFF]]; + dest++; + + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + // Lactozilla: Non-powers-of-two + { + 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)]; + if (val & 0xFF00) + *dest = colormap[translation[val & 0xFF]]; + } + } + else + { + double left = width; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (; width != 0; width--) + { + // Lactozilla: Non-powers-of-two + 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)]; + if (val & 0xFF00) + *dest = colormap[translation[val & 0xFF]]; + dest++; + + u += stepu; + v += stepv; + } + } + } +} + +/** \brief The R_DrawTiltedTranslucentFloorSprite_NPO2_8 function + Draws a tilted, translucent, floor sprite. +*/ +void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT16 *source; + UINT8 *colormap; + UINT8 *translation; + UINT8 *dest; + UINT16 val; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + source = (UINT16 *)ds_source; + colormap = ds_colormap; + translation = ds_translation; + + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (i = SPANSIZE-1; i >= 0; i--) + { + // Lactozilla: Non-powers-of-two + 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)]; + if (val & 0xFF00) + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + dest++; + + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + // Lactozilla: Non-powers-of-two + { + 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)]; + if (val & 0xFF00) + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + } + } + else + { + double left = width; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (; width != 0; width--) + { + // Lactozilla: Non-powers-of-two + 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)]; + if (val & 0xFF00) + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + dest++; + + u += stepu; + v += stepv; + } + } + } +} + /** \brief The R_DrawTranslucentSpan_NPO2_8 function Draws the actual span with translucency. */ @@ -1016,9 +1308,6 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) vz += ds_svp->x; } while (--width >= 0); #else -#define SPANSIZE 16 -#define INVSPAN 0.0625f - startz = 1.f/iz; startu = uz*startz; startv = vz*startz; diff --git a/src/r_plane.c b/src/r_plane.c index 797919a9f..096d1dbd6 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -645,46 +645,48 @@ static void R_DrawSkyPlane(visplane_t *pl) } } -static void R_SlopeVectors(visplane_t *pl, INT32 i, float fudge) +// Potentially override other stuff for now cus we're mean. :< But draw a slope plane! +// I copied ZDoom's code and adapted it to SRB2... -Red +void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge) { - // Potentially override other stuff for now cus we're mean. :< But draw a slope plane! - // I copied ZDoom's code and adapted it to SRB2... -Red floatv3_t p, m, n; float ang; float vx, vy, vz; + float xscale = FIXED_TO_FLOAT(planexscale); + float yscale = FIXED_TO_FLOAT(planeyscale); // compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly // use this as a temp var to store P_GetSlopeZAt's return value each time fixed_t temp; - vx = FIXED_TO_FLOAT(pl->viewx+xoffs); - vy = FIXED_TO_FLOAT(pl->viewy-yoffs); - vz = FIXED_TO_FLOAT(pl->viewz); + vx = FIXED_TO_FLOAT(planeviewx+planexoffset); + vy = FIXED_TO_FLOAT(planeviewy-planeyoffset); + vz = FIXED_TO_FLOAT(planeviewz); - temp = P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy); + temp = P_GetSlopeZAt(slope, planeviewx, planeviewy); zeroheight = FIXED_TO_FLOAT(temp); // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in // errors if the flat is rotated. - ang = ANG2RAD(ANGLE_270 - pl->viewangle); + ang = ANG2RAD(ANGLE_270 - planeviewangle); p.x = vx * cos(ang) - vy * sin(ang); p.z = vx * sin(ang) + vy * cos(ang); - temp = P_GetSlopeZAt(pl->slope, -xoffs, yoffs); + temp = P_GetSlopeZAt(slope, -planexoffset, planeyoffset); p.y = FIXED_TO_FLOAT(temp) - vz; // m is the v direction vector in view space - ang = ANG2RAD(ANGLE_180 - (pl->viewangle + pl->plangle)); - m.x = cos(ang); - m.z = sin(ang); + ang = ANG2RAD(ANGLE_180 - (planeviewangle + planeangle)); + m.x = yscale * cos(ang); + m.z = yscale * sin(ang); // n is the u direction vector in view space - n.x = sin(ang); - n.z = -cos(ang); + n.x = xscale * sin(ang); + n.z = -xscale * cos(ang); - ang = ANG2RAD(pl->plangle); - temp = P_GetSlopeZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(sin(ang)), pl->viewy + FLOAT_TO_FIXED(cos(ang))); + ang = ANG2RAD(planeangle); + temp = P_GetSlopeZAt(slope, planeviewx + yscale * FLOAT_TO_FIXED(sin(ang)), planeviewy + yscale * FLOAT_TO_FIXED(cos(ang))); m.y = FIXED_TO_FLOAT(temp) - zeroheight; - temp = P_GetSlopeZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang))); + temp = P_GetSlopeZAt(slope, planeviewx + xscale * FLOAT_TO_FIXED(cos(ang)), planeviewy - xscale * FLOAT_TO_FIXED(sin(ang))); n.y = FIXED_TO_FLOAT(temp) - zeroheight; if (ds_powersoftwo) @@ -700,42 +702,50 @@ static void R_SlopeVectors(visplane_t *pl, INT32 i, float 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) \ -d.x = (v1.y * v2.z) - (v1.z * v2.y);\ -d.y = (v1.z * v2.x) - (v1.x * v2.z);\ -d.z = (v1.x * v2.y) - (v1.y * v2.x) - CROSS(ds_su[i], p, m); - CROSS(ds_sv[i], p, n); - CROSS(ds_sz[i], m, n); +d->x = (v1.y * v2.z) - (v1.z * v2.y);\ +d->y = (v1.z * v2.x) - (v1.x * v2.z);\ +d->z = (v1.x * v2.y) - (v1.y * v2.x) + CROSS(ds_sup, p, m); + CROSS(ds_svp, p, n); + CROSS(ds_szp, m, n); #undef CROSS - ds_su[i].z *= focallengthf; - ds_sv[i].z *= focallengthf; - ds_sz[i].z *= focallengthf; + ds_sup->z *= focallengthf; + ds_svp->z *= focallengthf; + ds_szp->z *= focallengthf; // Premultiply the texture vectors with the scale factors #define SFMULT 65536.f if (ds_powersoftwo) { - ds_su[i].x *= (SFMULT * (1<x *= (SFMULT * (1<y *= (SFMULT * (1<z *= (SFMULT * (1<x *= (SFMULT * (1<y *= (SFMULT * (1<z *= (SFMULT * (1<x *= SFMULT; + ds_sup->y *= SFMULT; + ds_sup->z *= SFMULT; + ds_svp->x *= SFMULT; + ds_svp->y *= SFMULT; + ds_svp->z *= SFMULT; } #undef SFMULT } +static void R_SlopePlaneVectors(visplane_t *pl, INT32 i, float fudge) +{ + ds_sup = &ds_su[i]; + ds_svp = &ds_sv[i]; + ds_szp = &ds_sz[i]; + R_CalculateSlopeVectors(pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoffs, yoffs, pl->viewangle, pl->plangle, fudge); +} + void R_DrawSinglePlane(visplane_t *pl) { levelflat_t *levelflat; @@ -992,7 +1002,7 @@ void R_DrawSinglePlane(visplane_t *pl) R_PlaneRipple(pl, i, plheight); xoffs = rxoffs + ripple_xfrac; yoffs = ryoffs + ripple_yfrac; - R_SlopeVectors(pl, i, fudgecanyon); + R_SlopePlaneVectors(pl, i, fudgecanyon); } xoffs = rxoffs; @@ -1000,7 +1010,7 @@ void R_DrawSinglePlane(visplane_t *pl) } else #endif - R_SlopeVectors(pl, 0, fudgecanyon); + R_SlopePlaneVectors(pl, 0, fudgecanyon); #ifndef NOWATER if (itswater && (spanfunctype == SPANDRAWFUNC_WATER)) diff --git a/src/r_plane.h b/src/r_plane.h index 15f7f07f3..e6dffb4da 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -84,11 +84,15 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop); void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop); 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); +// Draws a single visplane. +void R_DrawSinglePlane(visplane_t *pl); + +// Calculates the slope vectors needed for tilted span drawing. +void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge); + typedef struct planemgr_s { visplane_t *plane; diff --git a/src/r_splats.c b/src/r_splats.c index fa4d9eef8..541221841 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -14,6 +14,7 @@ #include "r_main.h" #include "r_splats.h" #include "r_bsp.h" +#include "p_slopes.h" #include "w_wad.h" #include "z_zone.h" @@ -143,10 +144,10 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 // fill the polygon with linear interpolation, call span drawer for each // scan line // -------------------------------------------------------------------------- -void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis) +void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis) { // rasterizing - INT32 miny = viewheight + 1, maxy = 0, y, x1, ry1, x2, y2, i; + INT32 miny = viewheight + 1, maxy = 0, y, x1, ry1, x2, y2, i, xclip; fixed_t offsetx = 0, offsety = 0; fixed_t step; @@ -217,19 +218,47 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis) // do segment d -> left side of texture RASTERPARAMS(0,3,pSplat->width-1,0,0,1); - ds_source = pSplat->pic; + ds_source = (UINT8 *)pSplat->pic; ds_flatwidth = pSplat->width; ds_flatheight = pSplat->height; if (R_CheckPowersOfTwo()) R_CheckFlatLength(ds_flatwidth * ds_flatheight); + // Lactozilla: I don't know what I'm doing + if (pSplat->tilted) + { + R_CalculateSlopeVectors(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, viewangle, pSplat->angle, 1.0f); + spanfunctype = SPANDRAWFUNC_TILTEDSPRITE; + } + else + { + if (pSplat->angle) + { + // Add the view offset, rotated by the plane angle. + fixed_t a = -pSplat->verts[0].x + viewx; + fixed_t b = -pSplat->verts[0].y + viewy; + angle = (pSplat->angle >> ANGLETOFINESHIFT); + offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b,FINESINE(angle)); + offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b,FINECOSINE(angle)); + } + else + { + offsetx = viewx - pSplat->verts[0].x; + offsety = pSplat->verts[0].y - viewy; + } + } + ds_transmap = NULL; if (vis->transmap) { ds_transmap = vis->transmap; - spanfunctype = SPANDRAWFUNC_TRANSSPRITE; + + if (pSplat->tilted) + spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE; + else + spanfunctype = SPANDRAWFUNC_TRANSSPRITE; } if (ds_powersoftwo) @@ -237,7 +266,7 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis) else spanfunc = spanfuncs_npo2[spanfunctype]; - if (pSplat->angle) + if (pSplat->angle && !pSplat->tilted) { memset(cachedheight, 0, sizeof(cachedheight)); angle = (viewangle + pSplat->angle - ANGLE_90) >> ANGLETOFINESHIFT; @@ -252,7 +281,6 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis) } planeheight = abs(pSplat->z - viewz); - if (maxy >= vid.height) maxy = vid.height-1; @@ -276,33 +304,6 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis) if (x2 >= vid.width) x2 = vid.width - 1; - angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT; - planecos = FINECOSINE(angle); - planesin = FINESINE(angle); - - if (planeheight != cachedheight[y]) - { - cachedheight[y] = planeheight; - distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); - xstep = cachedxstep[y] = FixedMul(distance, basexscale); - ystep = cachedystep[y] = FixedMul(distance, baseyscale); - // don't divide by zero - if ((span = abs(centery-y))) - { - xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span; - ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span; - } - } - else - { - distance = cacheddistance[y]; - xstep = cachedxstep[y]; - ystep = cachedystep[y]; - } - - ds_xstep = FixedDiv(xstep, pSplat->xscale); - ds_ystep = FixedDiv(ystep, pSplat->yscale); - ds_colormap = vis->colormap; ds_translation = R_GetSpriteTranslation(vis); if (ds_translation == NULL) @@ -316,53 +317,61 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis) ds_colormap = &vis->extra_colormap->colormap[ds_colormap - colormaps]; } - if (pSplat->angle) + R_ClipVisSprite(vis, x1-1, x2+1, drawsegs, NULL); + memset(ds_splatclip, 0, sizeof(ds_splatclip)); + + if (x2 >= x1 && x1 < viewwidth && x1 >= 0) { - // Add the view offset, rotated by the plane angle. - fixed_t a = -pSplat->verts[0].x + viewx; - fixed_t b = -pSplat->verts[0].y + viewy; - angle = (pSplat->angle >> ANGLETOFINESHIFT); - offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b,FINESINE(angle)); - offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b,FINECOSINE(angle)); - } - else - { - offsetx = viewx - pSplat->verts[0].x; - offsety = pSplat->verts[0].y - viewy; - } - - if (vis != NULL) - { - INT32 xclip; - - mfloorclip = vis->clipbot; - mceilingclip = vis->cliptop; - - R_ClipVisSprite(vis, x1-1, x2+1, drawsegs, NULL); - memset(ds_splatclip, 0, sizeof(ds_splatclip)); - - if (x2 >= x1 && x1 < viewwidth && x1 >= 0) + for (xclip = x1; xclip <= x2; xclip++) { - for (xclip = x1; xclip <= x2; xclip++) + if (y >= mfloorclip[xclip]) + ds_splatclip[xclip] = 1; + } + } + + while (ds_splatclip[x1]) + x1++; + i = x2; + while (i > x1) + { + if (ds_splatclip[i]) + x2 = i-1; + i--; + } + + if (!pSplat->tilted) + { + angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT; + planecos = FINECOSINE(angle); + planesin = FINESINE(angle); + + if (planeheight != cachedheight[y]) + { + cachedheight[y] = planeheight; + distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); + xstep = cachedxstep[y] = FixedMul(distance, basexscale); + ystep = cachedystep[y] = FixedMul(distance, baseyscale); + + // don't divide by zero + if ((span = abs(centery-y))) { - if (y >= mfloorclip[xclip]) - ds_splatclip[xclip] = 1; + xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span; + ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span; } } - - while (ds_splatclip[x1]) - x1++; - i = x2; - while (i > x1) + else { - if (ds_splatclip[i]) - x2 = i-1; - i--; + distance = cacheddistance[y]; + xstep = cachedxstep[y]; + ystep = cachedystep[y]; } - } - ds_xfrac = FixedDiv(offsetx + FixedMul(planecos, distance) + (x1 - centerx) * xstep, pSplat->xscale); - ds_yfrac = FixedDiv(offsety - FixedMul(planesin, distance) + (x1 - centerx) * ystep, pSplat->yscale); + ds_xstep = FixedDiv(xstep, pSplat->xscale); + ds_ystep = FixedDiv(ystep, pSplat->yscale); + + ds_xfrac = FixedDiv(offsetx + FixedMul(planecos, distance) + (x1 - centerx) * xstep, pSplat->xscale); + ds_yfrac = FixedDiv(offsety - FixedMul(planesin, distance) + (x1 - centerx) * ystep, pSplat->yscale); + } if (x2 >= x1) { @@ -376,7 +385,7 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis) rastertab[y].maxx = INT32_MIN; } - if (pSplat->angle) + if (pSplat->angle && !pSplat->tilted) { memset(cachedheight, 0, sizeof(cachedheight)); angle = (viewangle - ANGLE_90) >> ANGLETOFINESHIFT; diff --git a/src/r_splats.h b/src/r_splats.h index 9c01084cf..b0707e95b 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -31,17 +31,19 @@ extern struct rastery_s *prastertab; // for ASM code #ifdef FLOORSPLATS typedef struct floorsplat_s { - UINT8 *pic; + UINT16 *pic; INT32 width, height; fixed_t scale, xscale, yscale; angle_t angle; + boolean tilted; // Uses the tilted drawer + pslope_t slope; - vertex_t verts[4]; // (x,y) as viewed from above on map + vector3_t verts[4]; // (x,y,z) as viewed from above on map fixed_t x, y, z; // position mobj_t *mobj; // Mobj it is tied to } floorsplat_t; -void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis); +void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis); extern UINT8 ds_splatclip[MAXVIDWIDTH]; #endif diff --git a/src/r_things.c b/src/r_things.c index d60228e36..99fa2c7c5 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1415,7 +1415,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t tx, tz; fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!! fixed_t sortscale, sortsplat = 0; - fixed_t sort_x = 0, sort_y = 0; + fixed_t sort_x = 0, sort_y = 0, sort_z; INT32 x1, x2; @@ -1764,10 +1764,10 @@ static void R_ProjectSprite(mobj_t *thing) // Adjust the sort scale if needed if (splat) { - tz = (patch->height - patch->topoffset) * FRACUNIT; + sort_z = (patch->height - patch->topoffset) * FRACUNIT; ang = (viewangle >> ANGLETOFINESHIFT); - sort_x = FixedMul(FixedMul(FixedMul(spritexscale, this_scale), tz), FINECOSINE(ang)); - sort_y = FixedMul(FixedMul(FixedMul(spriteyscale, this_scale), tz), FINESINE(ang)); + sort_x = FixedMul(FixedMul(FixedMul(spritexscale, this_scale), sort_z), FINECOSINE(ang)); + sort_y = FixedMul(FixedMul(FixedMul(spriteyscale, this_scale), sort_z), FINESINE(ang)); } if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY) @@ -1797,8 +1797,8 @@ static void R_ProjectSprite(mobj_t *thing) { tr_x = (thing->x + sort_x) - viewx; tr_y = (thing->y + sort_y) - viewy; - tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); - sortscale = FixedDiv(projectiony, tz); + sort_z = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); + sortscale = FixedDiv(projectiony, sort_z); } // Calculate the splat's sortscale @@ -1806,8 +1806,8 @@ static void R_ProjectSprite(mobj_t *thing) { tr_x = (thing->x - sort_x) - viewx; tr_y = (thing->y - sort_y) - viewy; - tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); - sortsplat = FixedDiv(projectiony, tz); + sort_z = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); + sortsplat = FixedDiv(projectiony, sort_z); } // PORTAL SPRITE CLIPPING @@ -2796,8 +2796,8 @@ static void R_DrawVisSplat(vissprite_t *spr) #ifdef FLOORSPLATS floorsplat_t splat; fixed_t tr_x, tr_y, rot_x, rot_y, rot_z; - vertex_t *v3d; - vertex_t v2d[4]; + vector3_t *v3d; + vector2_t v2d[4]; fixed_t x, y; fixed_t w, h; angle_t splatangle, angle; @@ -2809,6 +2809,7 @@ static void R_DrawVisSplat(vissprite_t *spr) boolean vflip = (spr->cut & SC_VFLIP); UINT8 flipflags = 0; vector2_t rotated[4]; + pslope_t *slope = NULL; INT32 i; if (hflip) @@ -2826,6 +2827,9 @@ static void R_DrawVisSplat(vissprite_t *spr) splat.height = spr->patch->height; splat.scale = spr->mobj->scale; + if (spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES) + splat.scale = FixedMul(splat.scale, ((skin_t *)spr->mobj->skin)->highresscale); + if (spr->rotateflags & SRF_3D || spr->renderflags & RF_NOSPLATBILLBOARD) splatangle = spr->mobj->angle; else @@ -2859,6 +2863,7 @@ static void R_DrawVisSplat(vissprite_t *spr) splat.x = x; splat.y = y; splat.z = spr->mobj->z; + splat.tilted = false; // Set positions @@ -2889,14 +2894,53 @@ static void R_DrawVisSplat(vissprite_t *spr) rotated[i].y = FixedMul(splat.verts[i].x, sa) + FixedMul(splat.verts[i].y, ca); } + if (spr->renderflags & RF_SLOPESPLAT) + { + slope = spr->mobj->standingslope; + splat.tilted = (slope != NULL); + } + + if (splat.tilted) + { + // Lactozilla: Just copy the entire slope LMFAOOOO + pslope_t *s = &splat.slope; + + s->o.x = slope->o.x; + s->o.y = slope->o.y; + s->o.z = slope->o.z; + + s->d.x = slope->d.x; + s->d.y = slope->d.y; + + s->normal.x = slope->normal.x; + s->normal.y = slope->normal.y; + s->normal.z = slope->normal.z; + + s->zdelta = slope->zdelta; + s->zangle = slope->zangle; + s->xydirection = slope->xydirection; + + s->next = NULL; + s->flags = 0; + } + // Translate for (i = 0; i < 4; i++) { - splat.verts[i].x = rotated[i].x + x; - splat.verts[i].y = rotated[i].y + y; - } + tr_x = rotated[i].x + x; + tr_y = rotated[i].y + y; - rot_z = splat.z - viewz; + if (slope) + { + rot_z = P_GetSlopeZAt(slope, tr_x, tr_y); + splat.verts[i].z = rot_z; + } + else + splat.verts[i].z = splat.z; + + splat.verts[i].x = tr_x; + splat.verts[i].y = tr_y; + } for (i = 0; i < 4; i++) { @@ -2909,6 +2953,7 @@ static void R_DrawVisSplat(vissprite_t *spr) // rotation around vertical y axis rot_x = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); rot_y = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); + rot_z = v3d->z - viewz; if (!rot_y || rot_y < FixedDiv(4*FRACUNIT, splat.scale)) return; diff --git a/src/screen.c b/src/screen.c index f5d182f34..8b6c05b6a 100644 --- a/src/screen.c +++ b/src/screen.c @@ -126,6 +126,8 @@ void SCR_SetDrawFuncs(void) spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8; spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8; spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8; + spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8; + spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_8; spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8; #ifndef NOWATER spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8; @@ -144,6 +146,8 @@ void SCR_SetDrawFuncs(void) spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed #ifndef NOWATER spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8; diff --git a/src/screen.h b/src/screen.h index 021c644ba..b139bd3b4 100644 --- a/src/screen.h +++ b/src/screen.h @@ -144,6 +144,8 @@ enum SPANDRAWFUNC_TRANSSPLAT, SPANDRAWFUNC_SPRITE, SPANDRAWFUNC_TRANSSPRITE, + SPANDRAWFUNC_TILTEDSPRITE, + SPANDRAWFUNC_TILTEDTRANSSPRITE, SPANDRAWFUNC_FOG, #ifndef NOWATER SPANDRAWFUNC_WATER, From 3a76f04ac2d1075410fca9da717292b7c880a7b1 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 13 Oct 2020 23:12:44 -0300 Subject: [PATCH 26/81] [Software] Use the light at the bottom of the object for splats --- src/r_things.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 99fa2c7c5..a0b6239a7 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1914,12 +1914,13 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->subsector->sector->numlights) { INT32 lightnum; + fixed_t top = (splat) ? gz : gzt; light = thing->subsector->sector->numlights - 1; // R_GetPlaneLight won't work on sloped lights! for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) { fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], thing->x, thing->y); - if (h <= gzt) { + if (h <= top) { light = lightnum - 1; break; } From 96fa912baec5a4f9fa297cc91b59f1c79bfefc7c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 14 Oct 2020 00:57:13 -0300 Subject: [PATCH 27/81] Implement object-defined floor sprite slopes. --- src/dehacked.c | 2 + src/hardware/hw_main.c | 24 +++++++++--- src/lua_mobjlib.c | 7 ++++ src/p_mobj.c | 6 +++ src/p_mobj.h | 1 + src/p_saveg.c | 88 ++++++++++++++++++++++++++++++++---------- src/r_defs.h | 8 ++-- src/r_things.c | 28 ++++++++++---- 8 files changed, 129 insertions(+), 35 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 0662074ba..df692391c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9585,7 +9585,9 @@ struct { {"RF_VERTICALFLIP",RF_VERTICALFLIP}, {"RF_ABSOLUTEOFFSETS",RF_ABSOLUTEOFFSETS}, {"RF_FLIPOFFSETS",RF_FLIPOFFSETS}, + {"RF_SPLATMASK",RF_SLOPESPLAT}, {"RF_SLOPESPLAT",RF_SLOPESPLAT}, + {"RF_OBJECTSLOPESPLAT",RF_OBJECTSLOPESPLAT}, {"RF_NOSPLATBILLBOARD",RF_NOSPLATBILLBOARD}, {"RF_NOSPLATROLLANGLE",RF_NOSPLATROLLANGLE}, {"RF_BLENDMASK",RF_BLENDMASK}, diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 315737108..948045df3 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3942,6 +3942,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) { F2DCoord verts[4]; F2DCoord rotated[4]; + angle_t angle; float ca, sa; float w, h; @@ -3950,12 +3951,14 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) float leftoffset, topoffset; float scale = spr->scale; float zoffset = (P_MobjFlip(spr->mobj) * 0.05f); + pslope_t *splatslope = NULL; INT32 i; - if (spr->renderflags & RF_SHADOWEFFECTS) + renderflags_t renderflags = spr->renderflags; + if (renderflags & RF_SHADOWEFFECTS) scale *= spr->shadowscale; - if (spr->rotateflags & SRF_3D || spr->renderflags & RF_NOSPLATBILLBOARD) + if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) angle = spr->mobj->angle; else angle = viewangle; @@ -4015,13 +4018,24 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) wallVerts[i].z = rotated[i].y + FIXED_TO_FLOAT(spr->mobj->y); } - if (spr->renderflags & RF_SLOPESPLAT && spr->mobj->standingslope) + if (renderflags & (RF_SLOPESPLAT | RF_OBJECTSLOPESPLAT)) { - pslope_t *slope = spr->mobj->standingslope; + pslope_t *standingslope = spr->mobj->standingslope; // The slope that the object is standing on. + // The slope that was defined for the sprite. + if (renderflags & RF_SLOPESPLAT) + splatslope = spr->mobj->floorspriteslope; + + if (standingslope && (renderflags & RF_OBJECTSLOPESPLAT)) + splatslope = standingslope; + } + + // Set vertical position + if (splatslope) + { for (i = 0; i < 4; i++) { - fixed_t slopez = P_GetSlopeZAt(slope, FLOAT_TO_FIXED(wallVerts[i].x), FLOAT_TO_FIXED(wallVerts[i].z)); + fixed_t slopez = P_GetSlopeZAt(splatslope, FLOAT_TO_FIXED(wallVerts[i].x), FLOAT_TO_FIXED(wallVerts[i].z)); wallVerts[i].y = FIXED_TO_FLOAT(slopez) + zoffset; } } diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index a544f151c..75b0c2f89 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -43,6 +43,7 @@ enum mobj_e { mobj_spriteyscale, mobj_spritexoffset, mobj_spriteyoffset, + mobj_floorspriteslope, mobj_touching_sectorlist, mobj_subsector, mobj_floorz, @@ -117,6 +118,7 @@ static const char *const mobj_opt[] = { "spriteyscale", "spritexoffset", "spriteyoffset", + "floorspriteslope", "touching_sectorlist", "subsector", "floorz", @@ -249,6 +251,9 @@ static int mobj_get(lua_State *L) case mobj_spriteyoffset: lua_pushfixed(L, mo->spriteyoffset); break; + case mobj_floorspriteslope: + LUA_PushUserdata(L, mo->floorspriteslope, META_SLOPE); + break; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: @@ -529,6 +534,8 @@ static int mobj_set(lua_State *L) case mobj_spriteyoffset: mo->spriteyoffset = luaL_checkfixed(L, 3); break; + case mobj_floorspriteslope: + return NOSET; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: diff --git a/src/p_mobj.c b/src/p_mobj.c index 2260ace51..6d36ee303 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10473,6 +10473,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // Sprite rendering mobj->spritexscale = mobj->spriteyscale = mobj->scale; mobj->spritexoffset = mobj->spriteyoffset = 0; + mobj->floorspriteslope = Z_Calloc(sizeof(pslope_t), PU_LEVEL, NULL); + mobj->floorspriteslope->normal.z = FRACUNIT; // set subsector and/or block links P_SetThingPosition(mobj); @@ -10935,6 +10937,10 @@ void P_RemoveMobj(mobj_t *mobj) mobj->state = NULL; mobj->player = NULL; + if (mobj->floorspriteslope) + Z_Free(mobj->floorspriteslope); + mobj->floorspriteslope = NULL; + // stop any playing sound S_StopSound(mobj); diff --git a/src/p_mobj.h b/src/p_mobj.h index 0b688a9ad..d26a38897 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -289,6 +289,7 @@ typedef struct mobj_s UINT32 renderflags; // render flags fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; + struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears diff --git a/src/p_saveg.c b/src/p_saveg.c index 3a9663326..ae8181693 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1393,12 +1393,13 @@ typedef enum MD2_COLORIZED = 1<<12, MD2_MIRRORED = 1<<13, MD2_ROLLANGLE = 1<<14, - MD2_SPRITEXSCALE = 1<<15, - MD2_SPRITEYSCALE = 1<<16, - MD2_SPRITEXOFFSET = 1<<17, - MD2_SPRITEYOFFSET = 1<<18, - MD2_SHADOWSCALE = 1<<19, - MD2_RENDERFLAGS = 1<<20, + MD2_SHADOWSCALE = 1<<15, + MD2_RENDERFLAGS = 1<<16, + MD2_SPRITEXSCALE = 1<<17, + MD2_SPRITEYSCALE = 1<<18, + MD2_SPRITEXOFFSET = 1<<19, + MD2_SPRITEYOFFSET = 1<<20, + MD2_FLOORSPRITESLOPE = 1<<21, } mobj_diff2_t; typedef enum @@ -1609,18 +1610,27 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_MIRRORED; if (mobj->rollangle) diff2 |= MD2_ROLLANGLE; + if (mobj->shadowscale) + diff2 |= MD2_SHADOWSCALE; + if (mobj->renderflags) + diff2 |= MD2_RENDERFLAGS; if (mobj->spritexscale != FRACUNIT) diff2 |= MD2_SPRITEXSCALE; if (mobj->spriteyscale != FRACUNIT) diff2 |= MD2_SPRITEYSCALE; if (mobj->spritexoffset) diff2 |= MD2_SPRITEXOFFSET; - if (mobj->spriteyoffset) - diff2 |= MD2_SPRITEYOFFSET; - if (mobj->shadowscale) - diff2 |= MD2_SHADOWSCALE; - if (mobj->renderflags) - diff2 |= MD2_RENDERFLAGS; + + { + pslope_t *slope = mobj->floorspriteslope; + if (slope->zangle || slope->zdelta || slope->xydirection + || slope->o.x || slope->o.y || slope->o.z + || slope->d.x || slope->d.y + || slope->normal.x || slope->normal.y + || (slope->normal.z != FRACUNIT)) + diff2 |= MD2_FLOORSPRITESLOPE; + } + if (diff2 != 0) diff |= MD_MORE; @@ -1761,6 +1771,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, mobj->mirrored); if (diff2 & MD2_ROLLANGLE) WRITEANGLE(save_p, mobj->rollangle); + if (diff2 & MD2_SHADOWSCALE) + WRITEFIXED(save_p, mobj->shadowscale); + if (diff2 & MD2_RENDERFLAGS) + WRITEUINT32(save_p, mobj->renderflags); if (diff2 & MD2_SPRITEXSCALE) WRITEFIXED(save_p, mobj->spritexscale); if (diff2 & MD2_SPRITEYSCALE) @@ -1769,10 +1783,25 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->spritexoffset); if (diff2 & MD2_SPRITEYOFFSET) WRITEFIXED(save_p, mobj->spriteyoffset); - if (diff2 & MD2_SHADOWSCALE) - WRITEFIXED(save_p, mobj->shadowscale); - if (diff2 & MD2_RENDERFLAGS) - WRITEUINT32(save_p, mobj->renderflags); + if (diff2 & MD2_FLOORSPRITESLOPE) + { + pslope_t *slope = mobj->floorspriteslope; + + WRITEFIXED(save_p, slope->zdelta); + WRITEANGLE(save_p, slope->zangle); + WRITEANGLE(save_p, slope->xydirection); + + WRITEFIXED(save_p, slope->o.x); + WRITEFIXED(save_p, slope->o.y); + WRITEFIXED(save_p, slope->o.z); + + WRITEFIXED(save_p, slope->d.x); + WRITEFIXED(save_p, slope->d.y); + + WRITEFIXED(save_p, slope->normal.x); + WRITEFIXED(save_p, slope->normal.y); + WRITEFIXED(save_p, slope->normal.z); + } WRITEUINT32(save_p, mobj->mobjnum); } @@ -2780,6 +2809,10 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->mirrored = READUINT8(save_p); if (diff2 & MD2_ROLLANGLE) mobj->rollangle = READANGLE(save_p); + if (diff2 & MD2_SHADOWSCALE) + mobj->shadowscale = READFIXED(save_p); + if (diff2 & MD2_RENDERFLAGS) + mobj->renderflags = READUINT32(save_p); if (diff2 & MD2_SPRITEXSCALE) mobj->spritexscale = READFIXED(save_p); if (diff2 & MD2_SPRITEYSCALE) @@ -2788,10 +2821,25 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->spritexoffset = READFIXED(save_p); if (diff2 & MD2_SPRITEYOFFSET) mobj->spriteyoffset = READFIXED(save_p); - if (diff2 & MD2_SHADOWSCALE) - mobj->shadowscale = READFIXED(save_p); - if (diff2 & MD2_RENDERFLAGS) - mobj->renderflags = READUINT32(save_p); + if (diff2 & MD2_FLOORSPRITESLOPE) + { + pslope_t *slope = mobj->floorspriteslope; + + slope->zdelta = READFIXED(save_p); + slope->zangle = READANGLE(save_p); + slope->xydirection = READANGLE(save_p); + + slope->o.x = READFIXED(save_p); + slope->o.y = READFIXED(save_p); + slope->o.z = READFIXED(save_p); + + slope->d.x = READFIXED(save_p); + slope->d.y = READFIXED(save_p); + + slope->normal.x = READFIXED(save_p); + slope->normal.y = READFIXED(save_p); + slope->normal.z = READFIXED(save_p); + } if (diff & MD_REDFLAG) { diff --git a/src/r_defs.h b/src/r_defs.h index 7b7c5d7f0..4423a4266 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -720,9 +720,11 @@ typedef enum RF_ABSOLUTEOFFSETS = 0x0004, // Sprite uses the object's offsets absolutely, instead of relatively RF_FLIPOFFSETS = 0x0008, // Relative object offsets are flipped with the sprite - RF_SLOPESPLAT = 0x0010, // Rotate floor sprites by the object's standing slope - RF_NOSPLATBILLBOARD = 0x0020, // Don't billboard floor sprites (faces forward from the view angle) - RF_NOSPLATROLLANGLE = 0x0040, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead) + RF_SPLATMASK = 0x00F0, // --Floor sprite flags + RF_SLOPESPLAT = 0x0010, // Rotate floor sprites by a slope + RF_OBJECTSLOPESPLAT = 0x0020, // Rotate floor sprites by the object's standing slope + RF_NOSPLATBILLBOARD = 0x0040, // Don't billboard floor sprites (faces forward from the view angle) + RF_NOSPLATROLLANGLE = 0x0080, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead) RF_BLENDMASK = 0x0F00, // --Blending modes RF_FULLBRIGHT = 0x0100, // Sprite is drawn at full brightness diff --git a/src/r_things.c b/src/r_things.c index a0b6239a7..e8c00b86b 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2797,21 +2797,26 @@ static void R_DrawVisSplat(vissprite_t *spr) #ifdef FLOORSPLATS floorsplat_t splat; fixed_t tr_x, tr_y, rot_x, rot_y, rot_z; + vector3_t *v3d; vector2_t v2d[4]; + vector2_t rotated[4]; + fixed_t x, y; fixed_t w, h; - angle_t splatangle, angle; + angle_t angle, splatangle; fixed_t ca, sa; fixed_t xscale, yscale; fixed_t xoffset, yoffset; fixed_t leftoffset, topoffset; + pslope_t *slope = NULL; + INT32 i; + boolean hflip = (spr->xiscale < 0); boolean vflip = (spr->cut & SC_VFLIP); UINT8 flipflags = 0; - vector2_t rotated[4]; - pslope_t *slope = NULL; - INT32 i; + + renderflags_t renderflags = spr->renderflags; if (hflip) flipflags |= PICFLAGS_XFLIP; @@ -2831,7 +2836,7 @@ static void R_DrawVisSplat(vissprite_t *spr) if (spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES) splat.scale = FixedMul(splat.scale, ((skin_t *)spr->mobj->skin)->highresscale); - if (spr->rotateflags & SRF_3D || spr->renderflags & RF_NOSPLATBILLBOARD) + if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) splatangle = spr->mobj->angle; else splatangle = viewangle; @@ -2895,9 +2900,18 @@ static void R_DrawVisSplat(vissprite_t *spr) rotated[i].y = FixedMul(splat.verts[i].x, sa) + FixedMul(splat.verts[i].y, ca); } - if (spr->renderflags & RF_SLOPESPLAT) + if (renderflags & (RF_SLOPESPLAT | RF_OBJECTSLOPESPLAT)) { - slope = spr->mobj->standingslope; + pslope_t *standingslope = spr->mobj->standingslope; // The slope that the object is standing on. + + // The slope that was defined for the sprite. + if (renderflags & RF_SLOPESPLAT) + slope = spr->mobj->floorspriteslope; + + if (standingslope && (renderflags & RF_OBJECTSLOPESPLAT)) + slope = standingslope; + + // Set splat as tilted splat.tilted = (slope != NULL); } From d348ff079b0d3628e1c356a40c5f0b8248eb4e2f Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 14 Oct 2020 13:07:02 -0300 Subject: [PATCH 28/81] Only create floor sprite slopes when needed, instead of always allocating them. Has to be done manually in Lua. Use P_CreateFloorSpriteSlope, and P_DeleteFloorSpriteSlope when done with it. --- src/lua_baselib.c | 24 ++++++++++++++++++++++++ src/p_mobj.c | 19 +++++++++++++++++-- src/p_mobj.h | 2 ++ src/p_saveg.c | 4 ++-- 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index d74af4214..f320cfdce 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -910,6 +910,28 @@ static int lib_pMaceRotate(lua_State *L) return 0; } +static int lib_pCreateFloorSpriteSlope(lua_State *L) +{ + mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + INLEVEL + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + LUA_PushUserdata(L, (pslope_t *)P_CreateFloorSpriteSlope(mobj), META_SLOPE); + return 1; +} + +static int lib_pDeleteFloorSpriteSlope(lua_State *L) +{ + mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + INLEVEL + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + P_DeleteFloorSpriteSlope(mobj); + return 1; +} + static int lib_pRailThinker(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -3536,6 +3558,8 @@ static luaL_Reg lib[] = { {"P_CheckSolidLava",lib_pCheckSolidLava}, {"P_CanRunOnWater",lib_pCanRunOnWater}, {"P_MaceRotate",lib_pMaceRotate}, + {"P_CreateFloorSpriteSlope",lib_pCreateFloorSpriteSlope}, + {"P_DeleteFloorSpriteSlope",lib_pDeleteFloorSpriteSlope}, {"P_RailThinker",lib_pRailThinker}, {"P_XYMovement",lib_pXYMovement}, {"P_RingXYMovement",lib_pRingXYMovement}, diff --git a/src/p_mobj.c b/src/p_mobj.c index 6d36ee303..389dddecd 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10473,8 +10473,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // Sprite rendering mobj->spritexscale = mobj->spriteyscale = mobj->scale; mobj->spritexoffset = mobj->spriteyoffset = 0; - mobj->floorspriteslope = Z_Calloc(sizeof(pslope_t), PU_LEVEL, NULL); - mobj->floorspriteslope->normal.z = FRACUNIT; + mobj->floorspriteslope = NULL; // set subsector and/or block links P_SetThingPosition(mobj); @@ -10876,6 +10875,22 @@ static inline precipmobj_t *P_SpawnSnowMobj(fixed_t x, fixed_t y, fixed_t z, mob return mo; } +void *P_CreateFloorSpriteSlope(mobj_t *mobj) +{ + if (mobj->floorspriteslope) + Z_Free(mobj->floorspriteslope); + mobj->floorspriteslope = Z_Calloc(sizeof(pslope_t), PU_LEVEL, NULL); + mobj->floorspriteslope->normal.z = FRACUNIT; + return (void *)mobj->floorspriteslope; +} + +void P_DeleteFloorSpriteSlope(mobj_t *mobj) +{ + if (mobj->floorspriteslope) + Z_Free(mobj->floorspriteslope); + mobj->floorspriteslope = NULL; +} + // // P_RemoveMobj // diff --git a/src/p_mobj.h b/src/p_mobj.h index d26a38897..7eb47112c 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -472,6 +472,8 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime); void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle); void P_SpawnPrecipitation(void); void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, statenum_t nstate, angle_t rotangle, boolean spawncenter); +void *P_CreateFloorSpriteSlope(mobj_t *mobj); +void P_DeleteFloorSpriteSlope(mobj_t *mobj); boolean P_BossTargetPlayer(mobj_t *actor, boolean closest); boolean P_SupermanLook4Players(mobj_t *actor); void P_DestroyRobots(void); diff --git a/src/p_saveg.c b/src/p_saveg.c index ae8181693..6bd24214d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1620,7 +1620,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_SPRITEYSCALE; if (mobj->spritexoffset) diff2 |= MD2_SPRITEXOFFSET; - + if (mobj->floorspriteslope) { pslope_t *slope = mobj->floorspriteslope; if (slope->zangle || slope->zdelta || slope->xydirection @@ -2823,7 +2823,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->spriteyoffset = READFIXED(save_p); if (diff2 & MD2_FLOORSPRITESLOPE) { - pslope_t *slope = mobj->floorspriteslope; + pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj); slope->zdelta = READFIXED(save_p); slope->zangle = READANGLE(save_p); From 04829fc613b5127d4f764d1ba95b7432f9dcf193 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 14 Oct 2020 14:08:25 -0300 Subject: [PATCH 29/81] Fix a crash in R_CalculateSlopeVectors called from R_RenderFloorSplat --- src/r_splats.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/r_splats.c b/src/r_splats.c index 541221841..ce45446d0 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -228,6 +228,9 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis // Lactozilla: I don't know what I'm doing if (pSplat->tilted) { + ds_sup = &ds_su[0]; + ds_svp = &ds_sv[0]; + ds_szp = &ds_sz[0]; R_CalculateSlopeVectors(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, viewangle, pSplat->angle, 1.0f); spanfunctype = SPANDRAWFUNC_TILTEDSPRITE; } From 578600156d9daa7f54ce1759dfdd0db35dd349c2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 14 Oct 2020 21:20:37 -0300 Subject: [PATCH 30/81] Simplify the floor splat clipping code a bit --- src/r_splats.c | 59 +++++++++++++++++++++++++++----------------------- src/r_splats.h | 1 - src/r_things.c | 4 +++- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/src/r_splats.c b/src/r_splats.c index ce45446d0..efcd6ea98 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -24,8 +24,6 @@ struct rastery_s *prastertab; // for ASM code static struct rastery_s rastertab[MAXVIDHEIGHT]; static void prepare_rastertab(void); -UINT8 ds_splatclip[MAXVIDWIDTH]; - // ========================================================================== // FLOOR SPLATS // ========================================================================== @@ -147,7 +145,8 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis) { // rasterizing - INT32 miny = viewheight + 1, maxy = 0, y, x1, ry1, x2, y2, i, xclip; + INT32 miny = viewheight + 1, maxy = 0; + INT32 y, x1, ry1, x2, y2, i; fixed_t offsetx = 0, offsety = 0; fixed_t step; @@ -289,6 +288,8 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis for (y = miny; y <= maxy; y++) { + boolean cliptab[MAXVIDWIDTH+1]; + x1 = rastertab[y].minx>>FRACBITS; x2 = rastertab[y].maxx>>FRACBITS; @@ -304,8 +305,34 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis if (x1 < 0) x1 = 0; - if (x2 >= vid.width) - x2 = vid.width - 1; + if (x2 >= viewwidth) + x2 = viewwidth - 1; + + if (x1 >= viewwidth || x2 < 0) + continue; + + for (i = x1; i <= x2; i++) + cliptab[i] = (y >= mfloorclip[i]); + + // clip left + while (cliptab[x1]) + { + x1++; + if (x1 >= viewwidth) + break; + } + + // clip right + i = x2; + + while (i > x1) + { + if (cliptab[i]) + x2 = i-1; + i--; + if (i < 0) + break; + } ds_colormap = vis->colormap; ds_translation = R_GetSpriteTranslation(vis); @@ -320,28 +347,6 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis ds_colormap = &vis->extra_colormap->colormap[ds_colormap - colormaps]; } - R_ClipVisSprite(vis, x1-1, x2+1, drawsegs, NULL); - memset(ds_splatclip, 0, sizeof(ds_splatclip)); - - if (x2 >= x1 && x1 < viewwidth && x1 >= 0) - { - for (xclip = x1; xclip <= x2; xclip++) - { - if (y >= mfloorclip[xclip]) - ds_splatclip[xclip] = 1; - } - } - - while (ds_splatclip[x1]) - x1++; - i = x2; - while (i > x1) - { - if (ds_splatclip[i]) - x2 = i-1; - i--; - } - if (!pSplat->tilted) { angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT; diff --git a/src/r_splats.h b/src/r_splats.h index b0707e95b..ba5052fc9 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -44,7 +44,6 @@ typedef struct floorsplat_s } floorsplat_t; void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis); -extern UINT8 ds_splatclip[MAXVIDWIDTH]; #endif #endif /*__R_SPLATS_H__*/ diff --git a/src/r_things.c b/src/r_things.c index e8c00b86b..6c1d8a879 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -3213,7 +3213,9 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) for (; clippedvissprites < visspritecount; clippedvissprites++) { vissprite_t *spr = R_GetVisSprite(clippedvissprites); - R_ClipVisSprite(spr, spr->x1, spr->x2, dsstart, portal); + INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1; + INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth : spr->x2; + R_ClipVisSprite(spr, x1, x2, dsstart, portal); } } From 5c2f487fbe8dc88b5fa226e4d7cf3187be04ea48 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 14 Oct 2020 21:26:23 -0300 Subject: [PATCH 31/81] Don't project if rot_y is less than a single fracunit --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 6c1d8a879..5fd4e27ad 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2970,7 +2970,7 @@ static void R_DrawVisSplat(vissprite_t *spr) rot_y = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); rot_z = v3d->z - viewz; - if (!rot_y || rot_y < FixedDiv(4*FRACUNIT, splat.scale)) + if (rot_y < FRACUNIT) return; // note: y from view above of map, is distance far away From 9365c88dc21750223f72e79d8f5132bff5e19024 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 15 Oct 2020 00:03:32 -0300 Subject: [PATCH 32/81] Fix precipitation --- src/p_mobj.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_mobj.h b/src/p_mobj.h index 7eb47112c..3f03e6ada 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -415,6 +415,7 @@ typedef struct precipmobj_s UINT32 renderflags; // render flags fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; + struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears From 1aa324add0a811f15355987f7f221a29bfd6097a Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 15 Oct 2020 11:32:21 -0300 Subject: [PATCH 33/81] Remove unnecessarily duplicated code in R_GetSpriteTranslation --- src/r_things.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 5fd4e27ad..266fc28ef 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -761,28 +761,6 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis) else return R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); } - else if (vis->mobj->color && vis->transmap) // Color mapping - { - if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) - return R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - else if (!(vis->cut & SC_PRECIP) - && vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD - && (vis->mobj->player->charflags & SF_DASHMODE) - && ((leveltime/2) & 1)) - { - if (vis->mobj->player->charflags & SF_MACHINE) - return R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); - else - return R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - } - else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> - { - size_t skinnum = (skin_t*)vis->mobj->skin-skins; - return R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); - } - else // Use the defaults - return R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); - } else if (vis->mobj->color) { // New colormap stuff for skins Tails 06-07-2002 From f2e09eb2f60d65401bb33b5ea820bb410ac50326 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 15 Oct 2020 14:05:18 -0300 Subject: [PATCH 34/81] Change vis->transmap statement --- src/r_things.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 266fc28ef..444b671d2 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2007,24 +2007,19 @@ static void R_ProjectSprite(mobj_t *thing) vis->scale += FixedMul(scalestep, spriteyscale) * (vis->x1 - x1); } - vis->patch = patch; - -// -// determine the colormap (lightlevel & special effects) -// - vis->transmap = NULL; - - // specific translucency - if (!cv_translucency.value) - ; // no translucency - else if (trans) + if (cv_translucency.value && trans) vis->transmap = transtables + ((trans-1)<transmap = NULL; if (R_ThingIsFullBright(oldthing) || oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) vis->cut |= SC_FULLBRIGHT; else if (R_ThingIsFullDark(oldthing)) vis->cut |= SC_FULLDARK; + // + // determine the colormap (lightlevel & special effects) + // if (vis->cut & SC_FULLBRIGHT && (!vis->extra_colormap || !(vis->extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES))) { @@ -2049,6 +2044,8 @@ static void R_ProjectSprite(mobj_t *thing) if (splat) vis->cut |= SC_SPLAT; // I like ya cut g + vis->patch = patch; + if (thing->subsector->sector->numlights && !(shadowdraw || splat)) R_SplitSprite(vis); From 6cf1441e3395cef3987f410e21cc72caa2c607d3 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 15 Oct 2020 14:12:19 -0300 Subject: [PATCH 35/81] [Software floor sprites] Set the colormap and translation outside of the loop --- src/r_splats.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/r_splats.c b/src/r_splats.c index efcd6ea98..10cf1127c 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -251,7 +251,18 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis } } - ds_transmap = NULL; + ds_colormap = vis->colormap; + ds_translation = R_GetSpriteTranslation(vis); + if (ds_translation == NULL) + ds_translation = colormaps; + + if (vis->extra_colormap) + { + if (!ds_colormap) + ds_colormap = vis->extra_colormap->colormap; + else + ds_colormap = &vis->extra_colormap->colormap[ds_colormap - colormaps]; + } if (vis->transmap) { @@ -262,6 +273,8 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis else spanfunctype = SPANDRAWFUNC_TRANSSPRITE; } + else + ds_transmap = NULL; if (ds_powersoftwo) spanfunc = spanfuncs[spanfunctype]; @@ -334,19 +347,6 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis break; } - ds_colormap = vis->colormap; - ds_translation = R_GetSpriteTranslation(vis); - if (ds_translation == NULL) - ds_translation = colormaps; - - if (vis->extra_colormap) - { - if (!ds_colormap) - ds_colormap = vis->extra_colormap->colormap; - else - ds_colormap = &vis->extra_colormap->colormap[ds_colormap - colormaps]; - } - if (!pSplat->tilted) { angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT; From b9c9660629a8efc2c2b6651b48ea6bd82c002ed7 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 15 Oct 2020 14:31:16 -0300 Subject: [PATCH 36/81] Don't free PU_HWRCACHE and PU_HWRCACHE_UNLOCKED memory tags in HWR_ClearAllTextures. Probably fixes a random annoying crash around that function. (I was also suspecting renderer switching was doing other slightly weird stuff.) --- src/hardware/hw_cache.c | 5 ----- src/hardware/hw_glob.h | 2 -- src/hardware/hw_main.c | 50 ++++++++++++++++++++++++++++++----------- src/hardware/hw_main.h | 4 ++++ src/p_setup.c | 29 ++---------------------- 5 files changed, 43 insertions(+), 47 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 39c06fa0c..85dabbcec 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -674,11 +674,6 @@ void HWR_ClearAllTextures(void) // free references to the textures HWD.pfnClearMipMapCache(); - // free all hardware-converted graphics cached in the heap - // our gool is only the textures since user of the texture is the texture cache - Z_FreeTag(PU_HWRCACHE); - Z_FreeTag(PU_HWRCACHE_UNLOCKED); - // Alam: free the Z_Blocks before freeing it's users HWR_FreePatchCache(true); } diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 6a9bb257c..112b241ef 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -108,8 +108,6 @@ void HWR_InitMapTextures(void); void HWR_LoadMapTextures(size_t pnumtextures); void HWR_FreeMapTextures(void); -extern boolean gl_maptexturesloaded; - patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump); patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 948045df3..89610a8d7 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -163,9 +163,11 @@ int rs_hw_numcolors = 0; int rs_hw_batchsorttime = 0; int rs_hw_batchdrawtime = 0; +boolean gl_init = false; +boolean gl_maploaded = false; +boolean gl_sessioncommandsadded = false; boolean gl_shadersavailable = true; - // ========================================================================== // Lighting // ========================================================================== @@ -6113,6 +6115,33 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE); } +void HWR_LoadLevel(void) +{ + // Lactozilla (December 8, 2019) + // Level setup used to free EVERY mipmap from memory. + // Even mipmaps that aren't related to level textures. + // Presumably, the hardware render code used to store textures as level data. + // Meaning, they had memory allocated and marked with the PU_LEVEL tag. + // Level textures are only reloaded after R_LoadTextures, which is + // when the texture list is loaded. + + // Sal: Unfortunately, NOT freeing them causes the dreaded Color Bug. + HWR_FreeColormapCache(); + +#ifdef ALAM_LIGHTING + // BP: reset light between levels (we draw preview frame lights on current frame) + HWR_ResetLights(); +#endif + + HWR_CreatePlanePolygons((INT32)numnodes - 1); + + // Build the sky dome + HWR_ClearSkyDome(); + HWR_BuildSkyDome(); + + gl_maploaded = true; +} + // ========================================================================== // 3D ENGINE COMMANDS // ========================================================================== @@ -6206,13 +6235,10 @@ void HWR_AddCommands(void) void HWR_AddSessionCommands(void) { - static boolean alreadycalled = false; - if (alreadycalled) + if (gl_sessioncommandsadded) return; - CV_RegisterVar(&cv_glanisotropicmode); - - alreadycalled = true; + gl_sessioncommandsadded = true; } // -------------------------------------------------------------------------- @@ -6220,10 +6246,7 @@ void HWR_AddSessionCommands(void) // -------------------------------------------------------------------------- void HWR_Startup(void) { - static boolean startupdone = false; - - // do this once - if (!startupdone) + if (!gl_init) { INT32 i; CONS_Printf("HWR_Startup()...\n"); @@ -6246,7 +6269,7 @@ void HWR_Startup(void) if (rendermode == render_opengl) textureformat = patchformat = GL_TEXFMT_RGBA; - startupdone = true; + gl_init = true; } // -------------------------------------------------------------------------- @@ -6255,7 +6278,8 @@ void HWR_Startup(void) void HWR_Switch(void) { // Add session commands - HWR_AddSessionCommands(); + if (!gl_sessioncommandsadded) + HWR_AddSessionCommands(); // Set special states from CVARs HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value); @@ -6266,7 +6290,7 @@ void HWR_Switch(void) HWR_LoadMapTextures(numtextures); // Create plane polygons - if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)) + if (!gl_maploaded && (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) HWR_LoadLevel(); } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index e3c795b22..381d7b0d7 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -123,6 +123,10 @@ extern int rs_hw_numcolors; extern int rs_hw_batchsorttime; extern int rs_hw_batchdrawtime; +extern boolean gl_init; +extern boolean gl_maploaded; +extern boolean gl_maptexturesloaded; +extern boolean gl_sessioncommandsadded; extern boolean gl_shadersavailable; #endif diff --git a/src/p_setup.c b/src/p_setup.c index 349b0582d..e96177dd9 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4144,6 +4144,8 @@ boolean P_LoadLevel(boolean fromnetsave) P_SpawnPrecipitation(); #ifdef HWRENDER // not win32 only 19990829 by Kin + gl_maploaded = false; + // Lactozilla: Free extrasubsectors regardless of renderer. HWR_FreeExtraSubsectors(); @@ -4231,33 +4233,6 @@ boolean P_LoadLevel(boolean fromnetsave) return true; } -#ifdef HWRENDER -void HWR_LoadLevel(void) -{ - // Lactozilla (December 8, 2019) - // Level setup used to free EVERY mipmap from memory. - // Even mipmaps that aren't related to level textures. - // Presumably, the hardware render code used to store textures as level data. - // Meaning, they had memory allocated and marked with the PU_LEVEL tag. - // Level textures are only reloaded after R_LoadTextures, which is - // when the texture list is loaded. - - // Sal: Unfortunately, NOT freeing them causes the dreaded Color Bug. - HWR_FreeColormapCache(); - -#ifdef ALAM_LIGHTING - // BP: reset light between levels (we draw preview frame lights on current frame) - HWR_ResetLights(); -#endif - - HWR_CreatePlanePolygons((INT32)numnodes - 1); - - // Build the sky dome - HWR_ClearSkyDome(); - HWR_BuildSkyDome(); -} -#endif - // // P_RunSOC // From e2adf00fc608ef2953571f48e5921e9dac25155f Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 17 Oct 2020 22:40:49 -0300 Subject: [PATCH 37/81] Don't render sprites with negative xscale or yscale in OpenGL --- src/hardware/hw_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 89610a8d7..bd4bcf66d 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4849,6 +4849,9 @@ static void HWR_ProjectSprite(mobj_t *thing) if (!thing) return; + if (thing->spritexscale < 1 || thing->spriteyscale < 1) + return; + dispoffset = thing->info->dispoffset; this_scale = FIXED_TO_FLOAT(thing->scale); From b84a7ebd5352b62836d2ad6e11ea653441bf229d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 19 Oct 2020 17:33:16 -0300 Subject: [PATCH 38/81] Remove FLOORSPLATS define --- src/doomdef.h | 3 --- src/r_splats.c | 3 --- src/r_splats.h | 2 -- src/r_things.c | 4 ---- 4 files changed, 12 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 98a22e5ab..d0b7ea0c2 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -641,9 +641,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Render flats on walls #define WALLFLATS -/// Floor splats -#define FLOORSPLATS - /// Maintain compatibility with older 2.2 demos #define OLD22DEMOCOMPAT diff --git a/src/r_splats.c b/src/r_splats.c index 10cf1127c..c4074f3d1 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -20,7 +20,6 @@ struct rastery_s *prastertab; // for ASM code -#ifdef FLOORSPLATS static struct rastery_s rastertab[MAXVIDHEIGHT]; static void prepare_rastertab(void); @@ -412,5 +411,3 @@ static void prepare_rastertab(void) rastertab[i].maxx = INT32_MIN; } } - -#endif // FLOORSPLATS diff --git a/src/r_splats.h b/src/r_splats.h index ba5052fc9..6ee8d5c6f 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -28,7 +28,6 @@ struct rastery_s }; extern struct rastery_s *prastertab; // for ASM code -#ifdef FLOORSPLATS typedef struct floorsplat_s { UINT16 *pic; @@ -44,6 +43,5 @@ typedef struct floorsplat_s } floorsplat_t; void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis); -#endif #endif /*__R_SPLATS_H__*/ diff --git a/src/r_things.c b/src/r_things.c index 444b671d2..1a2061cec 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2769,7 +2769,6 @@ void R_InitDrawNodes(void) static void R_DrawVisSplat(vissprite_t *spr) { -#ifdef FLOORSPLATS floorsplat_t splat; fixed_t tr_x, tr_y, rot_x, rot_y, rot_z; @@ -2958,9 +2957,6 @@ static void R_DrawVisSplat(vissprite_t *spr) } R_RenderFloorSplat(&splat, v2d, spr); -#else - (void)spr; -#endif } // From 018b826e1b1869bd35c07f26331a11fa58ba5746 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 19 Oct 2020 17:35:49 -0300 Subject: [PATCH 39/81] Rename R_DrawVisSplat to R_DrawSplatSprite, move into r_splats.c --- src/r_splats.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++++ src/r_splats.h | 1 + src/r_things.c | 194 +----------------------------------------------- 3 files changed, 198 insertions(+), 193 deletions(-) diff --git a/src/r_splats.c b/src/r_splats.c index c4074f3d1..ddc73e090 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -136,6 +136,202 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 } } +void R_DrawSplatSprite(vissprite_t *spr) +{ + floorsplat_t splat; + mobj_t *mobj = spr->mobj; + fixed_t tr_x, tr_y, rot_x, rot_y, rot_z; + + vector3_t *v3d; + vector2_t v2d[4]; + vector2_t rotated[4]; + + fixed_t x, y; + fixed_t w, h; + angle_t angle, splatangle; + fixed_t ca, sa; + fixed_t xscale, yscale; + fixed_t xoffset, yoffset; + fixed_t leftoffset, topoffset; + pslope_t *slope = NULL; + INT32 i; + + boolean hflip = (spr->xiscale < 0); + boolean vflip = (spr->cut & SC_VFLIP); + UINT8 flipflags = 0; + + renderflags_t renderflags = spr->renderflags; + + if (hflip) + flipflags |= PICFLAGS_XFLIP; + if (vflip) + flipflags |= PICFLAGS_YFLIP; + + if (!mobj || P_MobjWasRemoved(mobj)) + return; + + Patch_GenerateFlat(spr->patch, flipflags); + splat.pic = spr->patch->flats[flipflags]; + if (splat.pic == NULL) + return; + + splat.mobj = mobj; + splat.width = spr->patch->width; + splat.height = spr->patch->height; + splat.scale = mobj->scale; + + if (mobj->skin && ((skin_t *)mobj->skin)->flags & SF_HIRES) + splat.scale = FixedMul(splat.scale, ((skin_t *)mobj->skin)->highresscale); + + if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) + splatangle = mobj->angle; + else + splatangle = viewangle; + + if (!(spr->cut & SC_ISROTATED)) + splatangle += mobj->rollangle; + + splat.angle = -splatangle; + splat.angle += ANGLE_90; + + topoffset = spr->spriteyoffset; + leftoffset = spr->spritexoffset; + if (hflip) + leftoffset = ((splat.width * FRACUNIT) - leftoffset); + + xscale = spr->spritexscale; + yscale = spr->spriteyscale; + + splat.xscale = FixedMul(splat.scale, xscale); + splat.yscale = FixedMul(splat.scale, yscale); + + xoffset = FixedMul(leftoffset, splat.xscale); + yoffset = FixedMul(topoffset, splat.yscale); + + x = mobj->x; + y = mobj->y; + w = (splat.width * splat.xscale); + h = (splat.height * splat.yscale); + + splat.x = x; + splat.y = y; + splat.z = mobj->z; + splat.tilted = false; + + // Set positions + + // 3--2 + // | | + // 0--1 + + splat.verts[0].x = w - xoffset; + splat.verts[0].y = yoffset; + + splat.verts[1].x = -xoffset; + splat.verts[1].y = yoffset; + + splat.verts[2].x = -xoffset; + splat.verts[2].y = -h + yoffset; + + splat.verts[3].x = w - xoffset; + splat.verts[3].y = -h + yoffset; + + angle = -splat.angle; + ca = FINECOSINE(angle>>ANGLETOFINESHIFT); + sa = FINESINE(angle>>ANGLETOFINESHIFT); + + // Rotate + for (i = 0; i < 4; i++) + { + rotated[i].x = FixedMul(splat.verts[i].x, ca) - FixedMul(splat.verts[i].y, sa); + rotated[i].y = FixedMul(splat.verts[i].x, sa) + FixedMul(splat.verts[i].y, ca); + } + + if (renderflags & (RF_SLOPESPLAT | RF_OBJECTSLOPESPLAT)) + { + pslope_t *standingslope = mobj->standingslope; // The slope that the object is standing on. + + // The slope that was defined for the sprite. + if (renderflags & RF_SLOPESPLAT) + slope = mobj->floorspriteslope; + + if (standingslope && (renderflags & RF_OBJECTSLOPESPLAT)) + slope = standingslope; + + // Set splat as tilted + splat.tilted = (slope != NULL); + } + + if (splat.tilted) + { + // Lactozilla: Just copy the entire slope LMFAOOOO + pslope_t *s = &splat.slope; + + s->o.x = slope->o.x; + s->o.y = slope->o.y; + s->o.z = slope->o.z; + + s->d.x = slope->d.x; + s->d.y = slope->d.y; + + s->normal.x = slope->normal.x; + s->normal.y = slope->normal.y; + s->normal.z = slope->normal.z; + + s->zdelta = slope->zdelta; + s->zangle = slope->zangle; + s->xydirection = slope->xydirection; + + s->next = NULL; + s->flags = 0; + } + + // Translate + for (i = 0; i < 4; i++) + { + tr_x = rotated[i].x + x; + tr_y = rotated[i].y + y; + + if (slope) + { + rot_z = P_GetSlopeZAt(slope, tr_x, tr_y); + splat.verts[i].z = rot_z; + } + else + splat.verts[i].z = splat.z; + + splat.verts[i].x = tr_x; + splat.verts[i].y = tr_y; + } + + for (i = 0; i < 4; i++) + { + v3d = &splat.verts[i]; + + // transform the origin point + tr_x = v3d->x - viewx; + tr_y = v3d->y - viewy; + + // rotation around vertical y axis + rot_x = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); + rot_y = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); + rot_z = v3d->z - viewz; + + if (rot_y < FRACUNIT) + return; + + // note: y from view above of map, is distance far away + xscale = FixedDiv(projection, rot_y); + yscale = -FixedDiv(projectiony, rot_y); + + // projection + v2d[i].x = (centerxfrac + FixedMul(rot_x, xscale))>>FRACBITS; + v2d[i].y = (centeryfrac + FixedMul(rot_z, yscale))>>FRACBITS; + } + + R_RenderFloorSplat(&splat, v2d, spr); +} + // -------------------------------------------------------------------------- // Rasterize the four edges of a floor splat polygon, // fill the polygon with linear interpolation, call span drawer for each diff --git a/src/r_splats.h b/src/r_splats.h index 6ee8d5c6f..737a2c703 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -42,6 +42,7 @@ typedef struct floorsplat_s mobj_t *mobj; // Mobj it is tied to } floorsplat_t; +void R_DrawSplatSprite(vissprite_t *spr); void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis); #endif /*__R_SPLATS_H__*/ diff --git a/src/r_things.c b/src/r_things.c index 1a2061cec..6562a3ca8 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2767,198 +2767,6 @@ void R_InitDrawNodes(void) nodebankhead.next = nodebankhead.prev = &nodebankhead; } -static void R_DrawVisSplat(vissprite_t *spr) -{ - floorsplat_t splat; - fixed_t tr_x, tr_y, rot_x, rot_y, rot_z; - - vector3_t *v3d; - vector2_t v2d[4]; - vector2_t rotated[4]; - - fixed_t x, y; - fixed_t w, h; - angle_t angle, splatangle; - fixed_t ca, sa; - fixed_t xscale, yscale; - fixed_t xoffset, yoffset; - fixed_t leftoffset, topoffset; - pslope_t *slope = NULL; - INT32 i; - - boolean hflip = (spr->xiscale < 0); - boolean vflip = (spr->cut & SC_VFLIP); - UINT8 flipflags = 0; - - renderflags_t renderflags = spr->renderflags; - - if (hflip) - flipflags |= PICFLAGS_XFLIP; - if (vflip) - flipflags |= PICFLAGS_YFLIP; - - Patch_GenerateFlat(spr->patch, flipflags); - splat.pic = spr->patch->flats[flipflags]; - if (splat.pic == NULL) - return; - - splat.mobj = spr->mobj; - splat.width = spr->patch->width; - splat.height = spr->patch->height; - splat.scale = spr->mobj->scale; - - if (spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES) - splat.scale = FixedMul(splat.scale, ((skin_t *)spr->mobj->skin)->highresscale); - - if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) - splatangle = spr->mobj->angle; - else - splatangle = viewangle; - - if (!(spr->cut & SC_ISROTATED)) - splatangle += spr->mobj->rollangle; - - splat.angle = -splatangle; - splat.angle += ANGLE_90; - - topoffset = spr->spriteyoffset; - leftoffset = spr->spritexoffset; - if (hflip) - leftoffset = ((splat.width * FRACUNIT) - leftoffset); - - xscale = spr->spritexscale; - yscale = spr->spriteyscale; - - splat.xscale = FixedMul(splat.scale, xscale); - splat.yscale = FixedMul(splat.scale, yscale); - - xoffset = FixedMul(leftoffset, splat.xscale); - yoffset = FixedMul(topoffset, splat.yscale); - - x = spr->mobj->x; - y = spr->mobj->y; - w = (splat.width * splat.xscale); - h = (splat.height * splat.yscale); - - splat.x = x; - splat.y = y; - splat.z = spr->mobj->z; - splat.tilted = false; - - // Set positions - - // 3--2 - // | | - // 0--1 - - splat.verts[0].x = w - xoffset; - splat.verts[0].y = yoffset; - - splat.verts[1].x = -xoffset; - splat.verts[1].y = yoffset; - - splat.verts[2].x = -xoffset; - splat.verts[2].y = -h + yoffset; - - splat.verts[3].x = w - xoffset; - splat.verts[3].y = -h + yoffset; - - angle = -splat.angle; - ca = FINECOSINE(angle>>ANGLETOFINESHIFT); - sa = FINESINE(angle>>ANGLETOFINESHIFT); - - // Rotate - for (i = 0; i < 4; i++) - { - rotated[i].x = FixedMul(splat.verts[i].x, ca) - FixedMul(splat.verts[i].y, sa); - rotated[i].y = FixedMul(splat.verts[i].x, sa) + FixedMul(splat.verts[i].y, ca); - } - - if (renderflags & (RF_SLOPESPLAT | RF_OBJECTSLOPESPLAT)) - { - pslope_t *standingslope = spr->mobj->standingslope; // The slope that the object is standing on. - - // The slope that was defined for the sprite. - if (renderflags & RF_SLOPESPLAT) - slope = spr->mobj->floorspriteslope; - - if (standingslope && (renderflags & RF_OBJECTSLOPESPLAT)) - slope = standingslope; - - // Set splat as tilted - splat.tilted = (slope != NULL); - } - - if (splat.tilted) - { - // Lactozilla: Just copy the entire slope LMFAOOOO - pslope_t *s = &splat.slope; - - s->o.x = slope->o.x; - s->o.y = slope->o.y; - s->o.z = slope->o.z; - - s->d.x = slope->d.x; - s->d.y = slope->d.y; - - s->normal.x = slope->normal.x; - s->normal.y = slope->normal.y; - s->normal.z = slope->normal.z; - - s->zdelta = slope->zdelta; - s->zangle = slope->zangle; - s->xydirection = slope->xydirection; - - s->next = NULL; - s->flags = 0; - } - - // Translate - for (i = 0; i < 4; i++) - { - tr_x = rotated[i].x + x; - tr_y = rotated[i].y + y; - - if (slope) - { - rot_z = P_GetSlopeZAt(slope, tr_x, tr_y); - splat.verts[i].z = rot_z; - } - else - splat.verts[i].z = splat.z; - - splat.verts[i].x = tr_x; - splat.verts[i].y = tr_y; - } - - for (i = 0; i < 4; i++) - { - v3d = &splat.verts[i]; - - // transform the origin point - tr_x = v3d->x - viewx; - tr_y = v3d->y - viewy; - - // rotation around vertical y axis - rot_x = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); - rot_y = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); - rot_z = v3d->z - viewz; - - if (rot_y < FRACUNIT) - return; - - // note: y from view above of map, is distance far away - xscale = FixedDiv(projection, rot_y); - yscale = -FixedDiv(projectiony, rot_y); - - // projection - v2d[i].x = (centerxfrac + FixedMul(rot_x, xscale))>>FRACBITS; - v2d[i].y = (centeryfrac + FixedMul(rot_z, yscale))>>FRACBITS; - } - - R_RenderFloorSplat(&splat, v2d, spr); -} - // // R_DrawSprite // @@ -2971,7 +2779,7 @@ static void R_DrawSprite(vissprite_t *spr) mceilingclip = spr->cliptop; if (spr->cut & SC_SPLAT) - R_DrawVisSplat(spr); + R_DrawSplatSprite(spr); else R_DrawVisSprite(spr); } From adf89b0b36c706bd7300940b8ac1577a456ac193 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 19 Oct 2020 17:38:02 -0300 Subject: [PATCH 40/81] Include p_local.h --- src/r_splats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/r_splats.c b/src/r_splats.c index ddc73e090..6de0a7917 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -14,6 +14,7 @@ #include "r_main.h" #include "r_splats.h" #include "r_bsp.h" +#include "p_local.h" #include "p_slopes.h" #include "w_wad.h" #include "z_zone.h" From cdc4a6d86ef1c3374ca7a3623cf0420826b86ad1 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 27 Oct 2020 00:03:41 -0300 Subject: [PATCH 41/81] Implement blend modes --- src/d_clisrv.c | 4 +- src/d_clisrv.h | 1 + src/dehacked.c | 9 ++ src/f_wipe.c | 2 +- src/hardware/hw_defs.h | 47 +++++---- src/hardware/hw_draw.c | 2 +- src/hardware/hw_light.c | 7 +- src/hardware/hw_main.c | 107 ++++++++++++++------ src/hardware/hw_main.h | 8 +- src/hardware/hw_md2.c | 8 +- src/hardware/r_opengl/r_opengl.c | 164 ++++++++++++++++++++----------- src/lua_mobjlib.c | 8 ++ src/p_mobj.c | 2 +- src/p_mobj.h | 5 +- src/p_saveg.c | 17 +++- src/r_data.c | 4 +- src/r_draw.c | 108 +++++++++++++++++--- src/r_draw.h | 24 ++++- src/r_main.c | 4 +- src/r_plane.c | 22 ++--- src/r_segs.c | 22 ++--- src/r_things.c | 6 +- src/v_video.c | 14 +-- 23 files changed, 415 insertions(+), 180 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 636e2bfa8..dba783f4c 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -655,6 +655,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->flags = LONG(players[i].mo->flags); rsp->flags2 = LONG(players[i].mo->flags2); rsp->renderflags = LONG(players[i].mo->renderflags); + rsp->blendmode = LONG(players[i].mo->blendmode); rsp->radius = LONG(players[i].mo->radius); rsp->height = LONG(players[i].mo->height); @@ -794,7 +795,6 @@ static void resynch_read_player(resynch_pak *rsp) players[i].mo->eflags = (UINT16)SHORT(rsp->eflags); players[i].mo->flags = LONG(rsp->flags); players[i].mo->flags2 = LONG(rsp->flags2); - players[i].mo->renderflags = LONG(rsp->renderflags); players[i].mo->friction = LONG(rsp->friction); players[i].mo->health = LONG(rsp->health); players[i].mo->momx = LONG(rsp->momx); @@ -809,6 +809,8 @@ static void resynch_read_player(resynch_pak *rsp) players[i].mo->frame = LONG(rsp->frame); players[i].mo->sprite2 = rsp->sprite2; players[i].mo->anim_duration = SHORT(rsp->anim_duration); + players[i].mo->renderflags = LONG(rsp->renderflags); + players[i].mo->blendmode = LONG(rsp->blendmode); players[i].mo->spritexscale = LONG(rsp->spritexscale); players[i].mo->spriteyscale = LONG(rsp->spriteyscale); diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 94cec3ff7..747cf6842 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -300,6 +300,7 @@ typedef struct UINT32 flags2; UINT16 eflags; UINT32 renderflags; + INT32 blendmode; fixed_t radius; fixed_t height; diff --git a/src/dehacked.c b/src/dehacked.c index df692391c..3562a2aec 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9580,6 +9580,15 @@ struct { {"tr_trans90",tr_trans90}, {"NUMTRANSMAPS",NUMTRANSMAPS}, + // Alpha styles (blend modes) + {"AST_COPY",AST_COPY}, + {"AST_TRANSLUCENT",AST_TRANSLUCENT}, + {"AST_ADD",AST_ADD}, + {"AST_SUBTRACT",AST_SUBTRACT}, + {"AST_REVERSESUBTRACT",AST_REVERSESUBTRACT}, + {"AST_MODULATE",AST_MODULATE}, + {"AST_OVERLAY",AST_OVERLAY}, + // Render flags {"RF_HORIZONTALFLIP",RF_HORIZONTALFLIP}, {"RF_VERTICALFLIP",RF_VERTICALFLIP}, diff --git a/src/f_wipe.c b/src/f_wipe.c index f5b9bd722..6afb8a6a7 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -293,7 +293,7 @@ static void F_DoWipe(fademask_t *fademask) else { // pointer to transtable that this mask would use - transtbl = transtables + ((9 - *mask)< PolyColor - PF_NoTexture = 0x00002000, // Use the small white texture - PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona - PF_Ripple = 0x00008000, // Water shader effect - PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y - PF_ForceWrapX = 0x00020000, // Force repeat texture on X - PF_ForceWrapY = 0x00040000, // Force repeat texture on Y - PF_Clip = 0x40000000, // clip to frustum and nearz plane (glide only, automatic in opengl) - PF_NoZClip = 0x20000000, // in conjonction with PF_Clip - PF_Debug = 0x80000000 // print debug message in driver :) + PF_NoTexture = 0x00002000, // Disables texturing + PF_Corona = 0x00004000, // Tells the renderer we are drawing a corona + PF_Ripple = 0x00008000, // Water effect shader + PF_RemoveYWrap = 0x00010000, // Forces clamp texture on Y + PF_ForceWrapX = 0x00020000, // Forces repeat texture on X + PF_ForceWrapY = 0x00040000 // Forces repeat texture on Y }; diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index a4e1df496..faf7a9f8c 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -571,7 +571,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) // But then, the question is: why not 0 instead of PF_Masked ? // or maybe PF_Environment ??? (like what I said above) // BP: PF_Environment don't change anything ! and 0 is undifined - HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest | PF_Clip | PF_NoZClip); + HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest); } // ========================================================================== diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 32c2d550d..987d70c69 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -35,8 +35,7 @@ #define DL_HIGH_QUALITY //#define STATICLIGHT //Hurdler: TODO! -//#define LIGHTMAPFLAGS (PF_Masked|PF_Clip|PF_NoAlphaTest) // debug see overdraw -#define LIGHTMAPFLAGS (PF_Modulated|PF_Additive|PF_Clip) +#define LIGHTMAPFLAGS (PF_Modulated|PF_AdditiveSource) #ifdef ALAM_LIGHTING static dynlights_t view_dynlights[2]; // 2 players in splitscreen mode @@ -1056,7 +1055,7 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gl_vissprite_t *spr) HWR_GetPic(coronalumpnum); /// \todo use different coronas - HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_Corona | PF_NoDepthTest); + HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_Corona | PF_NoDepthTest); } } #endif @@ -1144,7 +1143,7 @@ void HWR_DrawCoronas(void) light[3].y = cy+size*1.33f; light[3].s = 0.0f; light[3].t = 1.0f; - HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona); + HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_NoDepthTest | PF_Corona); } } #endif diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index bd4bcf66d..fb8318e09 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -695,28 +695,71 @@ static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight) v3d->z = pv->y; } - HWD.pfnDrawPolygon(NULL, planeVerts, nrPlaneVerts, - PF_Clip|PF_Invisible|PF_NoTexture|PF_Occlude); + HWD.pfnDrawPolygon(NULL, planeVerts, nrPlaneVerts, PF_Invisible|PF_NoTexture|PF_Occlude); } #endif //polysky #endif //doplanes -FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) +FBITFIELD HWR_GetBlendModeFlag(INT32 ast) +{ + switch (ast) + { + case AST_ADD: + return PF_Additive; + case AST_SUBTRACT: + return PF_Subtractive; + case AST_REVERSESUBTRACT: + return PF_ReverseSubtract; + case AST_MODULATE: + return PF_Multiplicative; + default: + return PF_Translucent; + } + + return 0; +} + +UINT8 HWR_GetTranstableAlpha(INT32 transtablenum) { switch (transtablenum) { - case 0 : pSurf->PolyColor.s.alpha = 0x00;return PF_Masked; - case tr_trans10 : pSurf->PolyColor.s.alpha = 0xe6;return PF_Translucent; - case tr_trans20 : pSurf->PolyColor.s.alpha = 0xcc;return PF_Translucent; - case tr_trans30 : pSurf->PolyColor.s.alpha = 0xb3;return PF_Translucent; - case tr_trans40 : pSurf->PolyColor.s.alpha = 0x99;return PF_Translucent; - case tr_trans50 : pSurf->PolyColor.s.alpha = 0x80;return PF_Translucent; - case tr_trans60 : pSurf->PolyColor.s.alpha = 0x66;return PF_Translucent; - case tr_trans70 : pSurf->PolyColor.s.alpha = 0x4c;return PF_Translucent; - case tr_trans80 : pSurf->PolyColor.s.alpha = 0x33;return PF_Translucent; - case tr_trans90 : pSurf->PolyColor.s.alpha = 0x19;return PF_Translucent; + case 0 : return 0xff; + case tr_trans10 : return 0xe6; + case tr_trans20 : return 0xcc; + case tr_trans30 : return 0xb3; + case tr_trans40 : return 0x99; + case tr_trans50 : return 0x80; + case tr_trans60 : return 0x66; + case tr_trans70 : return 0x4c; + case tr_trans80 : return 0x33; + case tr_trans90 : return 0x19; } + + return 0xff; +} + +FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf) +{ + if (!transtablenum) + { + pSurf->PolyColor.s.alpha = 0xff; + return PF_Masked; + } + + pSurf->PolyColor.s.alpha = HWR_GetTranstableAlpha(transtablenum); + return HWR_GetBlendModeFlag(style); +} + +FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) +{ + if (!transtablenum) + { + pSurf->PolyColor.s.alpha = 0x00; + return PF_Masked; + } + + pSurf->PolyColor.s.alpha = HWR_GetTranstableAlpha(transtablenum); return PF_Translucent; } @@ -2770,10 +2813,10 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, if (blendmode & PF_Translucent) { Surf.PolyColor.s.alpha = (UINT8)alpha; - blendmode |= PF_Modulated|PF_Occlude|PF_Clip; + blendmode |= PF_Modulated|PF_Occlude; } else - blendmode |= PF_Masked|PF_Modulated|PF_Clip; + blendmode |= PF_Masked|PF_Modulated; HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, 1, false); // floor shader } @@ -3443,7 +3486,7 @@ static void HWR_LinkDrawHackFinish(void) { // draw sprite shape, only to z-buffer HWR_GetPatch(linkdrawlist[i].spr->gpatch); - HWR_ProcessPolygon(&surf, linkdrawlist[i].verts, 4, PF_Translucent|PF_Occlude|PF_Invisible|PF_Clip, 0, false); + HWR_ProcessPolygon(&surf, linkdrawlist[i].verts, 4, PF_Translucent|PF_Occlude|PF_Invisible, 0, false); } // reset list linkdrawcount = 0; @@ -3587,7 +3630,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) HWR_Lighting(&sSurf, 0, colormap); sSurf.PolyColor.s.alpha = alpha; - HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, 3, false); // sprite shader + HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated, 3, false); // sprite shader } // This is expecting a pointer to an array containing 4 wallVerts for a sprite @@ -3741,10 +3784,10 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) else if (spr->mobj->flags2 & MF2_SHADOW) { Surf.PolyColor.s.alpha = 0x40; - blend = PF_Translucent; + blend = HWR_GetBlendModeFlag(spr->mobj->blendmode); } else if (spr->mobj->frame & FF_TRANSMASK) - blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); + blend = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); else { // BP: i agree that is little better in environement but it don't @@ -3752,7 +3795,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) // Hurdler: PF_Environement would be cool, but we need to fix // the issue with the fog before Surf.PolyColor.s.alpha = 0xFF; - blend = PF_Translucent|occlusion; + blend = HWR_GetBlendModeFlag(spr->mobj->blendmode)|occlusion; if (!occlusion) use_linkdraw_hack = true; } @@ -3860,7 +3903,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) Surf.PolyColor.s.alpha = alpha; - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader if (use_linkdraw_hack) HWR_LinkDrawHackAdd(wallVerts, spr); @@ -3889,7 +3932,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) Surf.PolyColor.s.alpha = alpha; - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader if (use_linkdraw_hack) HWR_LinkDrawHackAdd(wallVerts, spr); @@ -4156,10 +4199,10 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) else if (spr->mobj->flags2 & MF2_SHADOW) { Surf.PolyColor.s.alpha = 0x40; - blend = PF_Translucent; + blend = HWR_GetBlendModeFlag(spr->mobj->blendmode); } else if (spr->mobj->frame & FF_TRANSMASK) - blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); + blend = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); else { // BP: i agree that is little better in environement but it don't @@ -4167,7 +4210,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) // Hurdler: PF_Environement would be cool, but we need to fix // the issue with the fog before Surf.PolyColor.s.alpha = 0xFF; - blend = PF_Translucent|occlusion; + blend = HWR_GetBlendModeFlag(spr->mobj->blendmode)|occlusion; if (!occlusion) use_linkdraw_hack = true; } @@ -4183,7 +4226,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) if (!occlusion) use_linkdraw_hack = true; } - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader if (use_linkdraw_hack) HWR_LinkDrawHackAdd(wallVerts, spr); @@ -4271,10 +4314,10 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) if (spr->mobj->flags2 & MF2_SHADOW) { Surf.PolyColor.s.alpha = 0x40; - blend = PF_Translucent; + blend = HWR_GetBlendModeFlag(spr->mobj->blendmode); } else if (spr->mobj->frame & FF_TRANSMASK) - blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); + blend = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); else { // BP: i agree that is little better in environement but it don't @@ -4282,10 +4325,10 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) // Hurdler: PF_Environement would be cool, but we need to fix // the issue with the fog before Surf.PolyColor.s.alpha = 0xFF; - blend = PF_Translucent|PF_Occlude; + blend = HWR_GetBlendModeFlag(spr->mobj->blendmode)|PF_Occlude; } - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader } #endif @@ -4749,7 +4792,7 @@ static void HWR_DrawSprites(void) // (Other states probably don't matter. Here I left them same as in LinkDrawHackFinish) // Without this workaround the rest of the draw calls in this frame (including UI, screen texture) // can get drawn using an incorrect glBlendFunc, resulting in a occasional black screen. - HWD.pfnSetBlend(PF_Translucent|PF_Occlude|PF_Clip|PF_Masked); + HWD.pfnSetBlend(PF_Translucent|PF_Occlude|PF_Masked); } // -------------------------------------------------------------------------- @@ -6422,7 +6465,7 @@ void HWR_DoPostProcessor(player_t *player) Surf.PolyColor.s.alpha = 0xc0; // match software mode - HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest|PF_Clip|PF_NoZClip); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_AdditiveSource|PF_NoTexture|PF_NoDepthTest); } // Capture the screen for intermission and screen waving diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 381d7b0d7..bd4151826 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -54,7 +54,6 @@ boolean HWR_Screenshot(const char *pathname); void HWR_AddCommands(void); void HWR_AddSessionCommands(void); void transform(float *cx, float *cy, float *cz); -FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf); INT32 HWR_GetTextureUsed(void); void HWR_DoPostProcessor(player_t *player); void HWR_StartScreenWipe(void); @@ -65,10 +64,15 @@ void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum); void HWR_MakeScreenFinalTexture(void); void HWR_DrawScreenFinalTexture(int width, int height); -// This stuff is put here so MD2's can use them +// This stuff is put here so models can use them void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap); UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work +UINT8 HWR_GetTranstableAlpha(INT32 transtablenum); +FBITFIELD HWR_GetBlendModeFlag(INT32 ast); +FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf); +FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf); + void HWR_ReadShaders(UINT16 wadnum, boolean PK3); boolean HWR_LoadShaders(void); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index d5c9cedaf..4358c5024 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1317,11 +1317,17 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) //durs = tics; if (spr->mobj->flags2 & MF2_SHADOW) + { Surf.PolyColor.s.alpha = 0x40; + Surf.PolyFlags = HWR_GetBlendModeFlag(spr->mobj->blendmode); + } else if (spr->mobj->frame & FF_TRANSMASK) - HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); + Surf.PolyFlags = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); else + { Surf.PolyColor.s.alpha = 0xFF; + Surf.PolyFlags = 0; + } // dont forget to enabled the depth test because we can't do this like // before: polygons models are not sorted diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 8b0e746b2..e3f7e714b 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -425,6 +425,10 @@ static PFNglBufferData pglBufferData; typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers); static PFNglDeleteBuffers pglDeleteBuffers; +/* 2.0 functions */ +typedef void (APIENTRY * PFNglBlendEquation) (GLenum mode); +static PFNglBlendEquation pglBlendEquation; + /* 1.2 Parms */ /* GL_CLAMP_TO_EDGE_EXT */ @@ -892,6 +896,9 @@ void SetupGLFunc4(void) pglBufferData = GetGLFunc("glBufferData"); pglDeleteBuffers = GetGLFunc("glDeleteBuffers"); + /* 2.0 funcs */ + pglBlendEquation = GetGLFunc("glBlendEquation"); + #ifdef GL_SHADERS pglCreateShader = GetGLFunc("glCreateShader"); pglShaderSource = GetGLFunc("glShaderSource"); @@ -1286,6 +1293,7 @@ void SetStates(void) pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + pglEnable(GL_ALPHA_TEST); pglAlphaFunc(GL_NOTEQUAL, 0.0f); //pglBlendFunc(GL_ONE, GL_ZERO); // copy pixel to frame buffer (opaque) @@ -1554,64 +1562,110 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, pglEnable(GL_TEXTURE_2D); } -static void Clamp2D(GLenum pname) -{ - pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP); // fallback clamp - pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP_TO_EDGE); -} - // -----------------+ // SetBlend : Set render mode // -----------------+ // PF_Masked - we could use an ALPHA_TEST of GL_EQUAL, and alpha ref of 0, // is it faster when pixels are discarded ? + +static void Clamp2D(GLenum pname) +{ + pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP); // fallback clamp + pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP_TO_EDGE); +} + +static void SetBlendEquation(GLenum mode) +{ + if (pglBlendEquation) + pglBlendEquation(mode); +} + +static void SetBlendMode(FBITFIELD flags) +{ + // Set blending function + switch (flags) + { + case PF_Translucent & PF_Blending: + pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency + break; + case PF_Masked & PF_Blending: + // Hurdler: does that mean lighting is only made by alpha src? + // it sounds ok, but not for polygonsmooth + pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture + break; + case PF_Additive & PF_Blending: + case PF_Subtractive & PF_Blending: + case PF_ReverseSubtract & PF_Blending: + case PF_Environment & PF_Blending: + pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + break; + case PF_AdditiveSource & PF_Blending: + pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest + break; + case PF_Multiplicative & PF_Blending: + pglBlendFunc(GL_DST_COLOR, GL_ZERO); + break; + case PF_Fog & PF_Fog: + // Sryder: Fog + // multiplies input colour by input alpha, and destination colour by input colour, then adds them + pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); + break; + default: // must be 0, otherwise it's an error + // No blending + pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending + break; + } + + // Set blending equation + switch (flags) + { + case PF_Subtractive & PF_Blending: + SetBlendEquation(GL_FUNC_SUBTRACT); + break; + case PF_ReverseSubtract & PF_Blending: + // good for shadow + // not really but what else ? + SetBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + break; + default: + SetBlendEquation(GL_FUNC_ADD); + break; + } + + // Alpha test + switch (flags) + { + case PF_Masked & PF_Blending: + pglAlphaFunc(GL_GREATER, 0.5f); + break; + case PF_Translucent & PF_Blending: + case PF_Additive & PF_Blending: + case PF_AdditiveSource & PF_Blending: + case PF_Subtractive & PF_Blending: + case PF_ReverseSubtract & PF_Blending: + case PF_Environment & PF_Blending: + case PF_Multiplicative & PF_Blending: + pglAlphaFunc(GL_NOTEQUAL, 0.0f); + break; + case PF_Fog & PF_Fog: + pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments + break; + default: + pglAlphaFunc(GL_GREATER, 0.5f); + break; + } +} + EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) { FBITFIELD Xor; Xor = CurrentPolyFlags^PolyFlags; - if (Xor & (PF_Blending|PF_RemoveYWrap|PF_ForceWrapX|PF_ForceWrapY|PF_Occlude|PF_NoTexture|PF_Modulated|PF_NoDepthTest|PF_Decal|PF_Invisible|PF_NoAlphaTest)) + if (Xor & (PF_Blending|PF_RemoveYWrap|PF_ForceWrapX|PF_ForceWrapY|PF_Occlude|PF_NoTexture|PF_Modulated|PF_NoDepthTest|PF_Decal|PF_Invisible)) { - if (Xor&(PF_Blending)) // if blending mode must be changed - { - switch (PolyFlags & PF_Blending) { - case PF_Translucent & PF_Blending: - pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency - pglAlphaFunc(GL_NOTEQUAL, 0.0f); - break; - case PF_Masked & PF_Blending: - // Hurdler: does that mean lighting is only made by alpha src? - // it sounds ok, but not for polygonsmooth - pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture - pglAlphaFunc(GL_GREATER, 0.5f); - break; - case PF_Additive & PF_Blending: - pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest - pglAlphaFunc(GL_NOTEQUAL, 0.0f); - break; - case PF_Environment & PF_Blending: - pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - pglAlphaFunc(GL_NOTEQUAL, 0.0f); - break; - case PF_Substractive & PF_Blending: - // good for shadow - // not really but what else ? - pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); - pglAlphaFunc(GL_NOTEQUAL, 0.0f); - break; - case PF_Fog & PF_Fog: - // Sryder: Fog - // multiplies input colour by input alpha, and destination colour by input colour, then adds them - pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); - pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments - break; - default : // must be 0, otherwise it's an error - // No blending - pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending - pglAlphaFunc(GL_GREATER, 0.5f); - break; - } - } + if (Xor & PF_Blending) // if blending mode must be changed + SetBlendMode(PolyFlags & PF_Blending); + if (Xor & PF_NoAlphaTest) { if (PolyFlags & PF_NoAlphaTest) @@ -1628,7 +1682,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) pglDisable(GL_POLYGON_OFFSET_FILL); } - if (Xor&PF_NoDepthTest) + if (Xor & PF_NoDepthTest) { if (PolyFlags & PF_NoDepthTest) pglDepthFunc(GL_ALWAYS); //pglDisable(GL_DEPTH_TEST); @@ -1636,25 +1690,25 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) pglDepthFunc(GL_LEQUAL); //pglEnable(GL_DEPTH_TEST); } - if (Xor&PF_RemoveYWrap) + if (Xor & PF_RemoveYWrap) { if (PolyFlags & PF_RemoveYWrap) Clamp2D(GL_TEXTURE_WRAP_T); } - if (Xor&PF_ForceWrapX) + if (Xor & PF_ForceWrapX) { if (PolyFlags & PF_ForceWrapX) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); } - if (Xor&PF_ForceWrapY) + if (Xor & PF_ForceWrapY) { if (PolyFlags & PF_ForceWrapY) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } - if (Xor&PF_Modulated) + if (Xor & PF_Modulated) { #if defined (__unix__) || defined (UNIXCOMMON) if (oglflags & GLF_NOTEXENV) @@ -2613,7 +2667,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 else pglColor4ubv((GLubyte*)&Surface->PolyColor.s); - SetBlend((poly.alpha < 1 ? PF_Translucent : (PF_Masked|PF_Occlude))|PF_Modulated); + SetBlend((poly.alpha < 1 ? Surface->PolyFlags : (PF_Masked|PF_Occlude))|PF_Modulated); tint.red = byte2float[Surface->TintColor.s.red]; tint.green = byte2float[Surface->TintColor.s.green]; @@ -3194,7 +3248,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void) pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - SetBlend(PF_Modulated|PF_NoDepthTest|PF_Clip|PF_NoZClip); + SetBlend(PF_Modulated|PF_NoDepthTest); pglEnable(GL_TEXTURE_2D); // Draw the original screen @@ -3204,7 +3258,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void) pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest|PF_Clip|PF_NoZClip); + SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest); // Draw the end screen that fades in pglActiveTexture(GL_TEXTURE0); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 75b0c2f89..75e8dba99 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -64,6 +64,7 @@ enum mobj_e { mobj_renderflags, mobj_skin, mobj_color, + mobj_blendmode, mobj_bnext, mobj_bprev, mobj_hnext, @@ -139,6 +140,7 @@ static const char *const mobj_opt[] = { "renderflags", "skin", "color", + "blendmode", "bnext", "bprev", "hnext", @@ -315,6 +317,9 @@ static int mobj_get(lua_State *L) case mobj_color: lua_pushinteger(L, mo->color); break; + case mobj_blendmode: + lua_pushinteger(L, mo->blendmode); + break; case mobj_bnext: LUA_PushUserdata(L, mo->bnext, META_MOBJ); break; @@ -650,6 +655,9 @@ static int mobj_set(lua_State *L) mo->color = newcolor; break; } + case mobj_blendmode: + mo->blendmode = (INT32)luaL_checkinteger(L, 3); + break; case mobj_bnext: return NOSETPOS; case mobj_bprev: diff --git a/src/p_mobj.c b/src/p_mobj.c index 389dddecd..7529b196a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10454,7 +10454,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits.. - mobj->renderflags = 0; P_SetupStateAnimation(mobj, st); mobj->friction = ORIG_FRICTION; @@ -10471,6 +10470,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->destscale = FRACUNIT/2; // Sprite rendering + mobj->blendmode = AST_TRANSLUCENT; mobj->spritexscale = mobj->spriteyscale = mobj->scale; mobj->spritexoffset = mobj->spriteyoffset = 0; mobj->floorspriteslope = NULL; diff --git a/src/p_mobj.h b/src/p_mobj.h index 3f03e6ada..a60da67d3 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -265,6 +265,7 @@ typedef enum { // Ran the thinker this tic. PCF_THUNK = 32, } precipflag_t; + // Map Object definition. typedef struct mobj_s { @@ -287,6 +288,7 @@ typedef struct mobj_s UINT16 anim_duration; // for FF_ANIMATE states UINT32 renderflags; // render flags + INT32 blendmode; // blend mode fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by @@ -405,7 +407,7 @@ typedef struct precipmobj_s struct precipmobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr // More drawing info: to determine current sprite. - angle_t angle, pitch, roll; // orientation + angle_t angle, pitch, roll; // orientation angle_t rollangle; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h @@ -413,6 +415,7 @@ typedef struct precipmobj_s UINT16 anim_duration; // for FF_ANIMATE states UINT32 renderflags; // render flags + INT32 blendmode; // blend mode fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by diff --git a/src/p_saveg.c b/src/p_saveg.c index 6bd24214d..8dc019b95 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1395,11 +1395,12 @@ typedef enum MD2_ROLLANGLE = 1<<14, MD2_SHADOWSCALE = 1<<15, MD2_RENDERFLAGS = 1<<16, - MD2_SPRITEXSCALE = 1<<17, - MD2_SPRITEYSCALE = 1<<18, - MD2_SPRITEXOFFSET = 1<<19, - MD2_SPRITEYOFFSET = 1<<20, - MD2_FLOORSPRITESLOPE = 1<<21, + MD2_BLENDMODE = 1<<17, + MD2_SPRITEXSCALE = 1<<18, + MD2_SPRITEYSCALE = 1<<19, + MD2_SPRITEXOFFSET = 1<<20, + MD2_SPRITEYOFFSET = 1<<21, + MD2_FLOORSPRITESLOPE = 1<<22, } mobj_diff2_t; typedef enum @@ -1614,6 +1615,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_SHADOWSCALE; if (mobj->renderflags) diff2 |= MD2_RENDERFLAGS; + if (mobj->renderflags) + diff2 |= MD2_BLENDMODE; if (mobj->spritexscale != FRACUNIT) diff2 |= MD2_SPRITEXSCALE; if (mobj->spriteyscale != FRACUNIT) @@ -1775,6 +1778,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->shadowscale); if (diff2 & MD2_RENDERFLAGS) WRITEUINT32(save_p, mobj->renderflags); + if (diff2 & MD2_BLENDMODE) + WRITEINT32(save_p, mobj->blendmode); if (diff2 & MD2_SPRITEXSCALE) WRITEFIXED(save_p, mobj->spritexscale); if (diff2 & MD2_SPRITEYSCALE) @@ -2813,6 +2818,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->shadowscale = READFIXED(save_p); if (diff2 & MD2_RENDERFLAGS) mobj->renderflags = READUINT32(save_p); + if (diff2 & MD2_BLENDMODE) + mobj->blendmode = READINT32(save_p); if (diff2 & MD2_SPRITEXSCALE) mobj->spritexscale = READFIXED(save_p); if (diff2 & MD2_SPRITEYSCALE) diff --git a/src/r_data.c b/src/r_data.c index 3c7d76d21..af672f6dc 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -175,13 +175,15 @@ UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT if (alpha <= ASTTextureBlendingThreshold[1]) { UINT8 *mytransmap; + INT32 trans; // Is the patch way too translucent? Don't blend then. if (alpha < ASTTextureBlendingThreshold[0]) 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); + trans = (8*(alpha) + 255/8)/(255 - 255/11); + mytransmap = R_GetTranslucencyTable(trans + 1); if (background != 0xFF) return *(mytransmap + (background<<8) + foreground); } diff --git a/src/r_draw.c b/src/r_draw.c index e10d6e399..ac9b7a2cd 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -75,6 +75,7 @@ UINT8 *dc_source; #define NUMTRANSTABLES 9 // how many translucency tables are used UINT8 *transtables; // translucency tables +UINT8 *blendtables[NUMBLENDMAPS]; /** \brief R_DrawTransColumn uses this */ @@ -116,10 +117,6 @@ float focallengthf, zeroheight; UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; -// ========================================================================== -// OLD DOOM FUZZY EFFECT -// ========================================================================== - // ========================================================================= // TRANSLATION COLORMAP CODE // ========================================================================= @@ -139,11 +136,11 @@ UINT8 skincolor_modified[MAXSKINCOLORS]; CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; -/** \brief The R_InitTranslationTables +#define TRANSTAB_AMTMUL10 (256.0f / 10.0f) - load in color translation tables +/** \brief Initializes the translucency tables used by the Software renderer. */ -void R_InitTranslationTables(void) +void R_InitTranslucencyTables(void) { // Load here the transparency lookup tables 'TINTTAB' // NOTE: the TINTTAB resource MUST BE aligned on 64k for the asm @@ -160,17 +157,94 @@ void R_InitTranslationTables(void) W_ReadLump(W_GetNumForName("TRANS70"), transtables+0x60000); W_ReadLump(W_GetNumForName("TRANS80"), transtables+0x70000); W_ReadLump(W_GetNumForName("TRANS90"), transtables+0x80000); + + R_GenerateBlendTables(); } +void R_GenerateBlendTables(void) +{ + INT32 i; -/** \brief Generates a translation colormap. + for (i = 0; i < NUMBLENDMAPS; i++) + { + if (i == blendtab_modulate) + continue; + blendtables[i] = Z_MallocAlign((NUMTRANSTABLES + 1) * 0x10000, PU_STATIC, NULL, 16); + } - \param dest_colormap colormap to populate - \param skinnum number of skin, TC_DEFAULT or TC_BOSS - \param color translation color + for (i = 0; i <= 9; i++) + { + const size_t offs = (0x10000 * i); + const UINT8 alpha = TRANSTAB_AMTMUL10 * i; - \return void -*/ + R_GenerateTranslucencyTable(blendtables[blendtab_add] + offs, AST_ADD, alpha); + R_GenerateTranslucencyTable(blendtables[blendtab_subtract] + offs, AST_SUBTRACT, alpha); + R_GenerateTranslucencyTable(blendtables[blendtab_reversesubtract] + offs, AST_REVERSESUBTRACT, alpha); + } + + // Modulation blending only requires a single table + blendtables[blendtab_modulate] = Z_MallocAlign(0x10000, PU_STATIC, NULL, 16); + R_GenerateTranslucencyTable(blendtables[blendtab_modulate], AST_MODULATE, 0); +} + +static colorlookup_t transtab_lut; + +void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt) +{ + INT16 bg, fg; + + if (table == NULL) + I_Error("R_GenerateTranslucencyTable: input table was NULL!"); + + InitColorLUT(&transtab_lut, pMasterPalette, false); + + for (bg = 0; bg < 0xFF; bg++) + { + for (fg = 0; fg < 0xFF; fg++) + { + RGBA_t backrgba = V_GetMasterColor(bg); + RGBA_t frontrgba = V_GetMasterColor(fg); + RGBA_t result; + + result.rgba = ASTBlendPixel(backrgba, frontrgba, style, blendamt); + table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue); + } + } +} + +#define ClipTransLevel(trans) max(min((trans), NUMTRANSMAPS-2), 0) + +UINT8 *R_GetTranslucencyTable(INT32 alphalevel) +{ + return transtables + (ClipTransLevel(alphalevel-1) << FF_TRANSSHIFT); +} + +UINT8 *R_GetBlendTable(int style, INT32 alphalevel) +{ + size_t offs = (ClipTransLevel(alphalevel) << FF_TRANSSHIFT); + + // Lactozilla: Returns the equivalent to AST_TRANSLUCENT + // if no alpha style matches any of the blend tables. + switch (style) + { + case AST_ADD: + return blendtables[blendtab_add] + offs; + case AST_SUBTRACT: + return blendtables[blendtab_subtract] + offs; + case AST_REVERSESUBTRACT: + return blendtables[blendtab_reversesubtract] + offs; + case AST_MODULATE: + return blendtables[blendtab_modulate]; + default: + break; + } + + // Return a normal translucency table + if (--alphalevel >= 0) + return transtables + (ClipTransLevel(alphalevel) << FF_TRANSSHIFT); + else + return NULL; +} // Define for getting accurate color brightness readings according to how the human eye sees them. // https://en.wikipedia.org/wiki/Relative_luminance @@ -228,6 +302,14 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT16 skincolor) #undef SETBRIGHTNESS +/** \brief Generates a translation colormap. + + \param dest_colormap colormap to populate + \param skinnum number of skin, TC_DEFAULT or TC_BOSS + \param color translation color + + \return void +*/ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT16 color) { INT32 i, starttranscolor, skinramplength; diff --git a/src/r_draw.h b/src/r_draw.h index 5011d29d9..8ee028892 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -37,7 +37,6 @@ extern UINT8 dc_hires; extern UINT8 *dc_source; // first pixel in a column // translucency stuff here -extern UINT8 *transtables; // translucency tables, should be (*transtables)[5][256][256] extern UINT8 *dc_transmap; // translation stuff here @@ -111,17 +110,36 @@ extern lumpnum_t viewborderlump[8]; #define TC_BLINK -6 // For item blinking, according to kart #define TC_DASHMODE -7 // For Metal Sonic's dashmode +// Custom player skin translation // Initialize color translation tables, for player rendering etc. -void R_InitTranslationTables(void); UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags); void R_FlushTranslationColormapCache(void); UINT16 R_GetColorByName(const char *name); UINT16 R_GetSuperColorByName(const char *name); +extern UINT8 *transtables; // translucency tables, should be (*transtables)[5][256][256] + +enum +{ + blendtab_add, + blendtab_subtract, + blendtab_reversesubtract, + blendtab_modulate, + NUMBLENDMAPS +}; + +extern UINT8 *blendtables[NUMBLENDMAPS]; + +void R_InitTranslucencyTables(void); +void R_GenerateBlendTables(void); +void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt); + +UINT8 *R_GetTranslucencyTable(INT32 alphalevel); +UINT8 *R_GetBlendTable(int style, INT32 alphalevel); + // Color ramp modification should force a recache extern UINT8 skincolor_modified[]; -// Custom player skin translation void R_InitViewBuffer(INT32 width, INT32 height); void R_InitViewBorder(void); void R_VideoErase(size_t ofs, INT32 count); diff --git a/src/r_main.c b/src/r_main.c index 03f9c6818..2706522f5 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1010,8 +1010,8 @@ void R_Init(void) //I_OutputMsg("\nR_InitLightTables"); R_InitLightTables(); - //I_OutputMsg("\nR_InitTranslationTables\n"); - R_InitTranslationTables(); + //I_OutputMsg("\nR_InitTranslucencyTables\n"); + R_InitTranslucencyTables(); R_InitDrawNodes(); diff --git a/src/r_plane.c b/src/r_plane.c index 096d1dbd6..5cd6a8c1f 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -780,7 +780,7 @@ void R_DrawSinglePlane(visplane_t *pl) else if (pl->polyobj->translucency > 0) { spanfunctype = (pl->polyobj->flags & POF_SPLAT) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS; - ds_transmap = transtables + ((pl->polyobj->translucency-1)<polyobj->translucency); } else if (pl->polyobj->flags & POF_SPLAT) // Opaque, but allow transparent flat pixels spanfunctype = SPANDRAWFUNC_SPLAT; @@ -819,23 +819,23 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->ffloor->alpha < 12) return; // Don't even draw it else if (pl->ffloor->alpha < 38) - ds_transmap = transtables + ((tr_trans90-1)<ffloor->alpha < 64) - ds_transmap = transtables + ((tr_trans80-1)<ffloor->alpha < 89) - ds_transmap = transtables + ((tr_trans70-1)<ffloor->alpha < 115) - ds_transmap = transtables + ((tr_trans60-1)<ffloor->alpha < 140) - ds_transmap = transtables + ((tr_trans50-1)<ffloor->alpha < 166) - ds_transmap = transtables + ((tr_trans40-1)<ffloor->alpha < 192) - ds_transmap = transtables + ((tr_trans30-1)<ffloor->alpha < 217) - ds_transmap = transtables + ((tr_trans20-1)<ffloor->alpha < 243) - ds_transmap = transtables + ((tr_trans10-1)<alpha > 0 && ldef->alpha < FRACUNIT) { - dc_transmap = transtables + ((R_GetLinedefTransTable(ldef->alpha) - 1) << FF_TRANSSHIFT); + dc_transmap = R_GetTranslucencyTable(R_GetLinedefTransTable(ldef->alpha)); colfunc = colfuncs[COLDRAWFUNC_FUZZY]; } @@ -165,7 +165,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (curline->polyseg->translucency >= NUMTRANSMAPS) return; - dc_transmap = transtables + ((curline->polyseg->translucency-1)<polyseg->translucency); colfunc = colfuncs[COLDRAWFUNC_FUZZY]; } @@ -580,23 +580,23 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (pfloor->alpha < 12) return; // Don't even draw it else if (pfloor->alpha < 38) - dc_transmap = transtables + ((tr_trans90-1)<alpha < 64) - dc_transmap = transtables + ((tr_trans80-1)<alpha < 89) - dc_transmap = transtables + ((tr_trans70-1)<alpha < 115) - dc_transmap = transtables + ((tr_trans60-1)<alpha < 140) - dc_transmap = transtables + ((tr_trans50-1)<alpha < 166) - dc_transmap = transtables + ((tr_trans40-1)<alpha < 192) - dc_transmap = transtables + ((tr_trans30-1)<alpha < 217) - dc_transmap = transtables + ((tr_trans20-1)<alpha < 243) - dc_transmap = transtables + ((tr_trans10-1)<extra_colormap = thing->subsector->sector->extra_colormap; - shadow->transmap = transtables + (trans<transmap = R_GetTranslucencyTable(trans + 1); shadow->colormap = scalelight[0][0]; // full dark! objectsdrawn++; @@ -2007,8 +2007,8 @@ static void R_ProjectSprite(mobj_t *thing) vis->scale += FixedMul(scalestep, spriteyscale) * (vis->x1 - x1); } - if (cv_translucency.value && trans) - vis->transmap = transtables + ((trans-1)<blendmode != AST_COPY) && cv_translucency.value) + vis->transmap = R_GetBlendTable(thing->blendmode, trans); else vis->transmap = NULL; diff --git a/src/v_video.c b/src/v_video.c index 9aeded617..522883475 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -551,7 +551,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca if (alphalevel) { - v_translevel = transtables + ((alphalevel-1)<= 0) && dest < deststop; dest += vid.width) { u = 0; @@ -1683,7 +1683,7 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U fadetable = ((color & 0xFF00) // Color is not palette index? ? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade. - : ((UINT8 *)transtables + ((9-strength)<= 0) && dest < deststop; dest += vid.width) { u = 0; @@ -1829,7 +1829,7 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength) ? ((UINT8 *)(((color & 0x0F00) == 0x0A00) ? fadecolormap // Do fadecolormap fade. : (((color & 0x0F00) == 0x0B00) ? fadecolormap + (256 * FADECOLORMAPROWS) // Do white fadecolormap fade. : colormaps)) + strength*256) // Do COLORMAP fade. - : ((UINT8 *)transtables + ((9-strength)< Date: Tue, 27 Oct 2020 17:02:35 -0300 Subject: [PATCH 42/81] Bug fixes --- src/hardware/hw_main.c | 23 ++++++++++++++++++++--- src/hardware/hw_md2.c | 15 +++++---------- src/hardware/r_opengl/r_opengl.c | 10 ++++++++-- src/r_things.c | 10 +++++++--- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index fb8318e09..8a4274d68 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -722,6 +722,8 @@ FBITFIELD HWR_GetBlendModeFlag(INT32 ast) UINT8 HWR_GetTranstableAlpha(INT32 transtablenum) { + transtablenum = max(min(transtablenum, tr_trans90), 0); + switch (transtablenum) { case 0 : return 0xff; @@ -3787,7 +3789,12 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) blend = HWR_GetBlendModeFlag(spr->mobj->blendmode); } else if (spr->mobj->frame & FF_TRANSMASK) - blend = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); + { + INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; + if (spr->mobj->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) + return; + blend = HWR_SurfaceBlend(spr->mobj->blendmode, trans, &Surf); + } else { // BP: i agree that is little better in environement but it don't @@ -4202,7 +4209,12 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) blend = HWR_GetBlendModeFlag(spr->mobj->blendmode); } else if (spr->mobj->frame & FF_TRANSMASK) - blend = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); + { + INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; + if (spr->mobj->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) + return; + blend = HWR_SurfaceBlend(spr->mobj->blendmode, trans, &Surf); + } else { // BP: i agree that is little better in environement but it don't @@ -4317,7 +4329,12 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) blend = HWR_GetBlendModeFlag(spr->mobj->blendmode); } else if (spr->mobj->frame & FF_TRANSMASK) - blend = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); + { + INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; + if (spr->mobj->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) + return; + blend = HWR_SurfaceBlend(spr->mobj->blendmode, trans, &Surf); + } else { // BP: i agree that is little better in environement but it don't diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 4358c5024..8ca38296a 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1316,21 +1316,16 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) //if (tics > durs) //durs = tics; - if (spr->mobj->flags2 & MF2_SHADOW) - { - Surf.PolyColor.s.alpha = 0x40; - Surf.PolyFlags = HWR_GetBlendModeFlag(spr->mobj->blendmode); - } - else if (spr->mobj->frame & FF_TRANSMASK) + if (spr->mobj->frame & FF_TRANSMASK) Surf.PolyFlags = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); else { - Surf.PolyColor.s.alpha = 0xFF; - Surf.PolyFlags = 0; + Surf.PolyColor.s.alpha = (spr->mobj->flags2 & MF2_SHADOW) ? 0x40 : 0xff; + Surf.PolyFlags = HWR_GetBlendModeFlag(spr->mobj->blendmode); } - // dont forget to enabled the depth test because we can't do this like - // before: polygons models are not sorted + // don't forget to enable the depth test because we can't do this + // like before: model polygons are not sorted // 1. load model+texture if not already loaded // 2. draw model with correct position, rotation,... diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index e3f7e714b..728c59f64 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2600,6 +2600,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 boolean useVBO = true; + FBITFIELD flags; int i; // Because otherwise, scaling the screen negatively vertically breaks the lighting @@ -2667,8 +2668,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 else pglColor4ubv((GLubyte*)&Surface->PolyColor.s); - SetBlend((poly.alpha < 1 ? Surface->PolyFlags : (PF_Masked|PF_Occlude))|PF_Modulated); - tint.red = byte2float[Surface->TintColor.s.red]; tint.green = byte2float[Surface->TintColor.s.green]; tint.blue = byte2float[Surface->TintColor.s.blue]; @@ -2679,6 +2678,13 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 fade.blue = byte2float[Surface->FadeColor.s.blue]; fade.alpha = byte2float[Surface->FadeColor.s.alpha]; + flags = (Surface->PolyFlags | PF_Modulated); + if (Surface->PolyFlags & (PF_Additive|PF_AdditiveSource|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative)) + flags |= PF_Occlude; + else if (Surface->PolyColor.s.alpha == 0xFF) + flags |= (PF_Occlude | PF_Masked); + + SetBlend(flags); Shader_Load(Surface, &poly, &tint, &fade); pglEnable(GL_CULL_FACE); diff --git a/src/r_things.c b/src/r_things.c index b85e4dfdc..916d2e891 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1802,7 +1802,11 @@ static void R_ProjectSprite(mobj_t *thing) if (oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) trans = tr_trans80; // because now the translucency is set through FF_TRANSMASK else if (oldthing->frame & FF_TRANSMASK) + { trans = (oldthing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; + if (oldthing->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) + return; + } else trans = 0; @@ -1834,7 +1838,7 @@ static void R_ProjectSprite(mobj_t *thing) else trans += 3; - if (trans >= 9) + if (trans >= NUMTRANSMAPS) return; trans--; @@ -2007,8 +2011,8 @@ static void R_ProjectSprite(mobj_t *thing) vis->scale += FixedMul(scalestep, spriteyscale) * (vis->x1 - x1); } - if ((thing->blendmode != AST_COPY) && cv_translucency.value) - vis->transmap = R_GetBlendTable(thing->blendmode, trans); + if ((oldthing->blendmode != AST_COPY) && cv_translucency.value) + vis->transmap = R_GetBlendTable(oldthing->blendmode, trans); else vis->transmap = NULL; From d2c000b2525f783e558fff2fa1b19939a0841a20 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 27 Oct 2020 19:54:10 -0300 Subject: [PATCH 43/81] Implement an "ignore colormaps" sprite rendering flag --- src/dehacked.c | 1 + src/hardware/hw_main.c | 41 ++++++++++++++++++++++++----------------- src/r_defs.h | 1 + src/r_things.c | 36 ++++++++++++++++++++---------------- 4 files changed, 46 insertions(+), 33 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 3562a2aec..67e83e4d5 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9602,6 +9602,7 @@ struct { {"RF_BLENDMASK",RF_BLENDMASK}, {"RF_FULLBRIGHT",RF_FULLBRIGHT}, {"RF_FULLDARK",RF_FULLDARK}, + {"RF_NOCOLORMAPS",RF_NOCOLORMAPS}, {"RF_SPRITETYPEMASK",RF_SPRITETYPEMASK}, {"RF_PAPERSPRITE",RF_PAPERSPRITE}, {"RF_FLOORSPRITE",RF_FLOORSPRITE}, diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 8a4274d68..590fac520 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3616,16 +3616,17 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) shadowVerts[3].t = shadowVerts[2].t = 0; shadowVerts[0].t = shadowVerts[1].t = ((GLPatch_t *)gpatch->hardware)->max_t; - if (thing->subsector->sector->numlights) + if (!(thing->renderflags & RF_NOCOLORMAPS)) { - light = R_GetPlaneLight(thing->subsector->sector, groundz, false); // Always use the light at the top instead of whatever I was doing before + if (thing->subsector->sector->numlights) + { + // Always use the light at the top instead of whatever I was doing before + light = R_GetPlaneLight(thing->subsector->sector, groundz, false); - if (*thing->subsector->sector->lightlist[light].extra_colormap) - colormap = *thing->subsector->sector->lightlist[light].extra_colormap; - } - else - { - if (thing->subsector->sector->extra_colormap) + if (*thing->subsector->sector->lightlist[light].extra_colormap) + colormap = *thing->subsector->sector->lightlist[light].extra_colormap; + } + else if (thing->subsector->sector->extra_colormap) colormap = thing->subsector->sector->extra_colormap; } @@ -3675,7 +3676,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) FOutVector baseWallVerts[4]; // This is what the verts should end up as patch_t *gpatch; FSurfaceInfo Surf; - extracolormap_t *colormap; + extracolormap_t *colormap = NULL; FUINT lightlevel; boolean lightset = true; FBITFIELD blend = 0; @@ -3810,7 +3811,9 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) // Start with the lightlevel and colormap from the top of the sprite lightlevel = *list[sector->numlights - 1].lightlevel; - colormap = *list[sector->numlights - 1].extra_colormap; + if (!(spr->mobj->renderflags & RF_NOCOLORMAPS)) + colormap = *list[sector->numlights - 1].extra_colormap; + i = 0; temp = FLOAT_TO_FIXED(realtop); @@ -3828,7 +3831,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) { if (!lightset) lightlevel = *list[i-1].lightlevel > 255 ? 255 : *list[i-1].lightlevel; - colormap = *list[i-1].extra_colormap; + if (!(spr->mobj->renderflags & RF_NOCOLORMAPS)) + colormap = *list[i-1].extra_colormap; break; } } @@ -3843,7 +3847,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) { if (!lightset) lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel; - colormap = *list[i].extra_colormap; + if (!(spr->mobj->renderflags & RF_NOCOLORMAPS)) + colormap = *list[i].extra_colormap; } if (i + 1 < sector->numlights) @@ -4160,7 +4165,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) sector_t *sector = spr->mobj->subsector->sector; UINT8 lightlevel = 0; boolean lightset = true; - extracolormap_t *colormap = sector->extra_colormap; + extracolormap_t *colormap = NULL; if (R_ThingIsFullBright(spr->mobj)) lightlevel = 255; @@ -4169,6 +4174,9 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) else lightset = false; + if (!(spr->mobj->renderflags & RF_NOCOLORMAPS)) + colormap = sector->extra_colormap; + if (splat && sector->numlights) { INT32 light = R_GetPlaneLight(sector, spr->mobj->z, false); @@ -4176,7 +4184,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) if (!lightset) lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel; - if (*sector->lightlist[light].extra_colormap) + if (*sector->lightlist[light].extra_colormap && !(spr->mobj->renderflags & RF_NOCOLORMAPS)) colormap = *sector->lightlist[light].extra_colormap; } else if (!lightset) @@ -4301,9 +4309,8 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) if (sector->numlights) { - INT32 light; - - light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before + // Always use the light at the top instead of whatever I was doing before + INT32 light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); if (!(spr->mobj->frame & FF_FULLBRIGHT)) lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel; diff --git a/src/r_defs.h b/src/r_defs.h index 4423a4266..9d0f4247c 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -729,6 +729,7 @@ typedef enum RF_BLENDMASK = 0x0F00, // --Blending modes RF_FULLBRIGHT = 0x0100, // Sprite is drawn at full brightness RF_FULLDARK = 0x0200, // Sprite is drawn completely dark + RF_NOCOLORMAPS = 0x0400, // Sprite is not drawn with colormaps RF_SPRITETYPEMASK = 0x7000, // ---Different sprite types, not all implemented RF_PAPERSPRITE = 0x1000, // Paper sprite diff --git a/src/r_things.c b/src/r_things.c index 916d2e891..5db78b346 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -842,7 +842,7 @@ static void R_DrawVisSprite(vissprite_t *vis) else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome. colfunc = colfuncs[COLDRAWFUNC_TRANS]; - if (vis->extra_colormap) + if (vis->extra_colormap && !(vis->renderflags & RF_NOCOLORMAPS)) { if (!dc_colormap) dc_colormap = vis->extra_colormap->colormap; @@ -1354,26 +1354,30 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, x1 += (x2-x1)/2; shadow->shear.offset = shadow->x1-x1; - if (thing->subsector->sector->numlights) + if (thing->renderflags & RF_NOCOLORMAPS) + shadow->extra_colormap = NULL; + else { - INT32 lightnum; - light = thing->subsector->sector->numlights - 1; + if (thing->subsector->sector->numlights) + { + INT32 lightnum; + light = thing->subsector->sector->numlights - 1; - // R_GetPlaneLight won't work on sloped lights! - for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) { - fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], thing->x, thing->y); - if (h <= shadow->gzt) { - light = lightnum - 1; - break; + // R_GetPlaneLight won't work on sloped lights! + for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) { + fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], thing->x, thing->y); + if (h <= shadow->gzt) { + light = lightnum - 1; + break; + } } } - //light = R_GetPlaneLight(thing->subsector->sector, shadow->gzt, false); - } - if (thing->subsector->sector->numlights) - shadow->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap; - else - shadow->extra_colormap = thing->subsector->sector->extra_colormap; + if (thing->subsector->sector->numlights) + shadow->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap; + else + shadow->extra_colormap = thing->subsector->sector->extra_colormap; + } shadow->transmap = R_GetTranslucencyTable(trans + 1); shadow->colormap = scalelight[0][0]; // full dark! From 39d003d6f7bdc1cd8f8ebecf7708577e878b322f Mon Sep 17 00:00:00 2001 From: Zippy_Zolton Date: Wed, 28 Oct 2020 01:23:05 -0500 Subject: [PATCH 44/81] Flame Shield Changes --- src/p_user.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index 0d7331293..0cf5321ad 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -5107,6 +5107,8 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock 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; + player->pflags &= ~PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); S_StartSound(player->mo, sfx_s3k43); default: break; From 16cc066e2e6ac9f5d5a45251d995049c81b49aa9 Mon Sep 17 00:00:00 2001 From: Zippy_Zolton Date: Thu, 29 Oct 2020 12:32:42 -0500 Subject: [PATCH 45/81] thunder shield :D --- src/p_user.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index 0cf5321ad..e886e1331 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4835,6 +4835,8 @@ void P_DoJumpShield(player_t *player) } #undef limitangle #undef numangles + player->pflags &= ~PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); S_StartSound(player->mo, sfx_s3k45); } else From 928ea1abc9326ee1cad4ef0168535d49b50494b7 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 4 Nov 2020 21:43:16 -0300 Subject: [PATCH 46/81] R_DrawSplatSprite -> R_DrawFloorSprite --- src/r_splats.c | 2 +- src/r_splats.h | 2 +- src/r_things.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/r_splats.c b/src/r_splats.c index 6de0a7917..7d091d9ff 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -137,7 +137,7 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 } } -void R_DrawSplatSprite(vissprite_t *spr) +void R_DrawFloorSprite(vissprite_t *spr) { floorsplat_t splat; mobj_t *mobj = spr->mobj; diff --git a/src/r_splats.h b/src/r_splats.h index 737a2c703..e1f836f48 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -42,7 +42,7 @@ typedef struct floorsplat_s mobj_t *mobj; // Mobj it is tied to } floorsplat_t; -void R_DrawSplatSprite(vissprite_t *spr); +void R_DrawFloorSprite(vissprite_t *spr); void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis); #endif /*__R_SPLATS_H__*/ diff --git a/src/r_things.c b/src/r_things.c index 5db78b346..1ca0349e9 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2787,7 +2787,7 @@ static void R_DrawSprite(vissprite_t *spr) mceilingclip = spr->cliptop; if (spr->cut & SC_SPLAT) - R_DrawSplatSprite(spr); + R_DrawFloorSprite(spr); else R_DrawVisSprite(spr); } @@ -3075,12 +3075,12 @@ boolean R_ThingIsFloorSprite(mobj_t *thing) return (thing->flags2 & MF2_SPLAT || thing->renderflags & RF_FLOORSPRITE); } -boolean R_ThingIsFullBright (mobj_t *thing) +boolean R_ThingIsFullBright(mobj_t *thing) { return (thing->frame & FF_FULLBRIGHT || thing->renderflags & RF_FULLBRIGHT); } -boolean R_ThingIsFullDark (mobj_t *thing) +boolean R_ThingIsFullDark(mobj_t *thing) { return (thing->renderflags & RF_FULLDARK); } From 917f8bbb665899855d42ed06bae5bc8c604ba0f4 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 4 Nov 2020 23:46:34 -0300 Subject: [PATCH 47/81] Plane optimization and cleanup --- src/r_draw.c | 6 +- src/r_draw.h | 5 +- src/r_main.c | 10 +++ src/r_plane.c | 193 ++++++++++++++++++++++++++++--------------------- src/r_splats.c | 73 ++++++++----------- 5 files changed, 157 insertions(+), 130 deletions(-) diff --git a/src/r_draw.c b/src/r_draw.c index ac9b7a2cd..eb4dc412f 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -104,11 +104,11 @@ 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_source; // points to the start of a flat UINT8 *ds_transmap; // one of the translucency tables -pslope_t *ds_slope; // Current slope being used -floatv3_t ds_su[MAXVIDHEIGHT], ds_sv[MAXVIDHEIGHT], ds_sz[MAXVIDHEIGHT]; // Vectors for... stuff? +// Vectors for Software's tilted slope drawers +floatv3_t *ds_su, *ds_sv, *ds_sz; floatv3_t *ds_sup, *ds_svp, *ds_szp; float focallengthf, zeroheight; diff --git a/src/r_draw.h b/src/r_draw.h index 8ee028892..fd40c76ce 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -59,6 +59,7 @@ extern lighttable_t *ds_translation; 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_transmap; @@ -66,8 +67,8 @@ typedef struct { float x, y, z; } floatv3_t; -extern pslope_t *ds_slope; // Current slope being used -extern floatv3_t ds_su[MAXVIDHEIGHT], ds_sv[MAXVIDHEIGHT], ds_sz[MAXVIDHEIGHT]; // Vectors for... stuff? +// Vectors for Software's tilted slope drawers +extern floatv3_t *ds_su, *ds_sv, *ds_sz; extern floatv3_t *ds_sup, *ds_svp, *ds_szp; extern float focallengthf, zeroheight; diff --git a/src/r_main.c b/src/r_main.c index 2706522f5..4f8990b21 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -958,6 +958,16 @@ void R_ExecuteSetViewSize(void) dy = FixedMul(abs(dy), fovtan); yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy); } + + if (ds_su) + Z_Free(ds_su); + if (ds_sv) + Z_Free(ds_sv); + if (ds_sz) + Z_Free(ds_sz); + + ds_su = ds_sv = ds_sz = NULL; + ds_sup = ds_svp = ds_szp = NULL; } memset(scalelight, 0xFF, sizeof(scalelight)); diff --git a/src/r_plane.c b/src/r_plane.c index 5cd6a8c1f..789134534 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -117,29 +117,41 @@ void R_InitPlanes(void) // // Water ripple effect!! // Needs the height of the plane, and the vertical position of the span. -// Sets ripple_xfrac and ripple_yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. +// Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. // #ifndef NOWATER INT32 ds_bgofs; INT32 ds_waterofs; -static INT32 wtofs=0; -static boolean itswater; -static fixed_t ripple_xfrac; -static fixed_t ripple_yfrac; +struct +{ + INT32 offset; + fixed_t xfrac, yfrac; + boolean active; +} planeripple; -static void R_PlaneRipple(visplane_t *plane, INT32 y, fixed_t plheight) +static void R_CalculatePlaneRipple(visplane_t *plane, INT32 y, fixed_t plheight, boolean calcfrac) { fixed_t distance = FixedMul(plheight, yslope[y]); - const INT32 yay = (wtofs + (distance>>9) ) & 8191; + const INT32 yay = (planeripple.offset + (distance>>9)) & 8191; + // ripples da water texture - angle_t angle = (plane->viewangle + plane->plangle)>>ANGLETOFINESHIFT; ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; - angle = (angle + 2048) & 8191; // 90 degrees - ripple_xfrac = FixedMul(FINECOSINE(angle), (ds_bgofs<viewangle + plane->plangle)>>ANGLETOFINESHIFT; + angle = (angle + 2048) & 8191; // 90 degrees + planeripple.xfrac = FixedMul(FINECOSINE(angle), (ds_bgofs<= vid.width) x1 = vid.width - 1; + if (x1 >= vid.width) + x1 = vid.width - 1; - angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT; - planecos = FINECOSINE(angle); - planesin = FINESINE(angle); - - if (planeheight != cachedheight[y]) + if (!currentplane->slope) { - cachedheight[y] = planeheight; - distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); - ds_xstep = cachedxstep[y] = FixedMul(distance, basexscale); - ds_ystep = cachedystep[y] = FixedMul(distance, baseyscale); + angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT; + planecos = FINECOSINE(angle); + planesin = FINESINE(angle); - if ((span = abs(centery-y))) + if (planeheight != cachedheight[y]) { - ds_xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span; - ds_ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span; - } - } - else - { - distance = cacheddistance[y]; - ds_xstep = cachedxstep[y]; - ds_ystep = cachedystep[y]; - } + cachedheight[y] = planeheight; + cacheddistance[y] = distance = FixedMul(planeheight, yslope[y]); + span = abs(centery - y); - ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; - ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; + if (span) // don't divide by zero + { + ds_xstep = FixedMul(planesin, planeheight) / span; + ds_ystep = FixedMul(planecos, planeheight) / span; + } + else + { + ds_xstep = FixedMul(distance, basexscale); + ds_ystep = FixedMul(distance, baseyscale); + } + + cachedxstep[y] = ds_xstep; + cachedystep[y] = ds_ystep; + } + else + { + distance = cacheddistance[y]; + ds_xstep = cachedxstep[y]; + ds_ystep = cachedystep[y]; + } + + ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; + ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; + } #ifndef NOWATER - if (itswater) + if (planeripple.active) { // Needed for ds_bgofs - R_PlaneRipple(currentplane, y, planeheight); + R_CalculatePlaneRipple(currentplane, y, planeheight, (!currentplane->slope)); if (currentplane->slope) { @@ -211,25 +233,26 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) } else { - ds_xfrac += ripple_xfrac; - ds_yfrac += ripple_yfrac; + ds_xfrac += planeripple.xfrac; + ds_yfrac += planeripple.yfrac; } - if (y+ds_bgofs>=viewheight) + if ((y + ds_bgofs) >= viewheight) ds_bgofs = viewheight-y-1; - if (y+ds_bgofs<0) + if ((y + ds_bgofs) < 0) ds_bgofs = -y; } #endif - pindex = distance >> LIGHTZSHIFT; - if (pindex >= MAXLIGHTZ) - pindex = MAXLIGHTZ - 1; - if (currentplane->slope) ds_colormap = colormaps; else + { + pindex = distance >> LIGHTZSHIFT; + if (pindex >= MAXLIGHTZ) + pindex = MAXLIGHTZ - 1; ds_colormap = planezlight[pindex]; + } if (currentplane->extra_colormap) ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); @@ -596,9 +619,9 @@ void R_DrawPlanes(void) R_DrawSinglePlane(pl); } } + #ifndef NOWATER - ds_waterofs = (leveltime & 1)*16384; - wtofs = leveltime * 140; + R_UpdatePlaneRipple(); #endif } @@ -738,12 +761,20 @@ d->z = (v1.x * v2.y) - (v1.y * v2.x) #undef SFMULT } -static void R_SlopePlaneVectors(visplane_t *pl, INT32 i, float fudge) +static void R_SetSlopePlaneVectors(visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge) { - ds_sup = &ds_su[i]; - ds_svp = &ds_sv[i]; - ds_szp = &ds_sz[i]; - R_CalculateSlopeVectors(pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoffs, yoffs, pl->viewangle, pl->plangle, fudge); + if (ds_su == NULL) + ds_su = Z_Malloc(sizeof(*ds_su) * vid.height, PU_STATIC, NULL); + if (ds_sv == NULL) + ds_sv = Z_Malloc(sizeof(*ds_sv) * vid.height, PU_STATIC, NULL); + if (ds_sz == NULL) + ds_sz = Z_Malloc(sizeof(*ds_sz) * vid.height, PU_STATIC, NULL); + + ds_sup = &ds_su[y]; + ds_svp = &ds_sv[y]; + ds_szp = &ds_sz[y]; + + R_CalculateSlopeVectors(pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoff, yoff, pl->viewangle, pl->plangle, fudge); } void R_DrawSinglePlane(visplane_t *pl) @@ -768,7 +799,7 @@ void R_DrawSinglePlane(visplane_t *pl) } #ifndef NOWATER - itswater = false; + planeripple.active = false; #endif spanfunc = spanfuncs[BASEDRAWFUNC]; @@ -851,12 +882,13 @@ void R_DrawSinglePlane(visplane_t *pl) } else light = (pl->lightlevel >> LIGHTSEGSHIFT); - #ifndef NOWATER +#ifndef NOWATER if (pl->ffloor->flags & FF_RIPPLE) { INT32 top, bottom; - itswater = true; + planeripple.active = true; + if (spanfunctype == SPANDRAWFUNC_TRANS) { spanfunctype = SPANDRAWFUNC_WATER; @@ -876,7 +908,7 @@ void R_DrawSinglePlane(visplane_t *pl) vid.width, vid.width); } } - #endif +#endif } else light = (pl->lightlevel >> LIGHTSEGSHIFT); @@ -979,50 +1011,45 @@ void R_DrawSinglePlane(visplane_t *pl) 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*fudgecanyon); yoffs = (fixed_t)(yoffs/fudgecanyon); } - ds_sup = &ds_su[0]; - ds_svp = &ds_sv[0]; - ds_szp = &ds_sz[0]; - #ifndef NOWATER - if (itswater) + if (planeripple.active) { - INT32 i; fixed_t plheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); - fixed_t rxoffs = xoffs; - fixed_t ryoffs = yoffs; R_PlaneBounds(pl); - for (i = pl->high; i < pl->low; i++) + for (x = pl->high; x < pl->low; x++) { - R_PlaneRipple(pl, i, plheight); - xoffs = rxoffs + ripple_xfrac; - yoffs = ryoffs + ripple_yfrac; - R_SlopePlaneVectors(pl, i, fudgecanyon); + R_CalculatePlaneRipple(pl, x, plheight, true); + R_SetSlopePlaneVectors(pl, x, (xoffs + planeripple.xfrac), (yoffs + planeripple.yfrac), fudgecanyon); } - - xoffs = rxoffs; - yoffs = ryoffs; } else #endif - R_SlopePlaneVectors(pl, 0, fudgecanyon); + R_SetSlopePlaneVectors(pl, 0, xoffs, yoffs, fudgecanyon); + switch (spanfunctype) + { #ifndef NOWATER - if (itswater && (spanfunctype == SPANDRAWFUNC_WATER)) - spanfunctype = SPANDRAWFUNC_TILTEDWATER; - else + case SPANDRAWFUNC_WATER: + spanfunctype = SPANDRAWFUNC_TILTEDWATER; + break; #endif - if (spanfunctype == SPANDRAWFUNC_TRANS) - spanfunctype = SPANDRAWFUNC_TILTEDTRANS; - else if (spanfunctype == SPANDRAWFUNC_SPLAT) - spanfunctype = SPANDRAWFUNC_TILTEDSPLAT; - else - spanfunctype = SPANDRAWFUNC_TILTED; + case SPANDRAWFUNC_TRANS: + spanfunctype = SPANDRAWFUNC_TILTEDTRANS; + break; + case SPANDRAWFUNC_SPLAT: + spanfunctype = SPANDRAWFUNC_TILTEDSPLAT; + break; + default: + spanfunctype = SPANDRAWFUNC_TILTED; + break; + } planezlight = scalelight[light]; } diff --git a/src/r_splats.c b/src/r_splats.c index 7d091d9ff..636aa30ed 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -344,13 +344,9 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis INT32 miny = viewheight + 1, maxy = 0; INT32 y, x1, ry1, x2, y2, i; fixed_t offsetx = 0, offsety = 0; + fixed_t planeheight = 0; fixed_t step; - fixed_t planeheight; - fixed_t xstep, ystep; - angle_t angle, planecos, planesin; - fixed_t distance, span; - int spanfunctype = SPANDRAWFUNC_SPRITE; prepare_rastertab(); @@ -431,14 +427,17 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis } else { + planeheight = abs(pSplat->z - viewz); + if (pSplat->angle) { // Add the view offset, rotated by the plane angle. fixed_t a = -pSplat->verts[0].x + viewx; fixed_t b = -pSplat->verts[0].y + viewy; - angle = (pSplat->angle >> ANGLETOFINESHIFT); + angle_t angle = (pSplat->angle >> ANGLETOFINESHIFT); offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b,FINESINE(angle)); offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b,FINECOSINE(angle)); + memset(cachedheight, 0, sizeof(cachedheight)); } else { @@ -477,21 +476,6 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis else spanfunc = spanfuncs_npo2[spanfunctype]; - if (pSplat->angle && !pSplat->tilted) - { - memset(cachedheight, 0, sizeof(cachedheight)); - angle = (viewangle + pSplat->angle - ANGLE_90) >> ANGLETOFINESHIFT; - basexscale = FixedDiv(FINECOSINE(angle), centerxfrac); - baseyscale = -FixedDiv(FINESINE(angle), centerxfrac); - } - else - { - angle = (viewangle - ANGLE_90) >> ANGLETOFINESHIFT; - basexscale = FixedDiv(FINECOSINE(angle), centerxfrac); - baseyscale = -FixedDiv(FINESINE(angle), centerxfrac); - } - - planeheight = abs(pSplat->z - viewz); if (maxy >= vid.height) maxy = vid.height-1; @@ -543,25 +527,38 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis break; } + if (x2 < x1) + continue; + if (!pSplat->tilted) { - angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT; - planecos = FINECOSINE(angle); - planesin = FINESINE(angle); + fixed_t xstep, ystep; + fixed_t distance, span; + + angle_t angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT; + angle_t planecos = FINECOSINE(angle); + angle_t planesin = FINESINE(angle); if (planeheight != cachedheight[y]) { cachedheight[y] = planeheight; distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); - xstep = cachedxstep[y] = FixedMul(distance, basexscale); - ystep = cachedystep[y] = FixedMul(distance, baseyscale); + span = abs(centery - y); - // don't divide by zero - if ((span = abs(centery-y))) + if (span) // don't divide by zero { - xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span; - ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span; + xstep = FixedMul(planesin, planeheight) / span; + ystep = FixedMul(planecos, planeheight) / span; } + else + { + // ah + xstep = FRACUNIT; + ystep = FRACUNIT; + } + + cachedxstep[y] = xstep; + cachedystep[y] = ystep; } else { @@ -577,25 +574,17 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis ds_yfrac = FixedDiv(offsety - FixedMul(planesin, distance) + (x1 - centerx) * ystep, pSplat->yscale); } - if (x2 >= x1) - { - ds_y = y; - ds_x1 = x1; - ds_x2 = x2; - spanfunc(); - } + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + spanfunc(); rastertab[y].minx = INT32_MAX; rastertab[y].maxx = INT32_MIN; } if (pSplat->angle && !pSplat->tilted) - { memset(cachedheight, 0, sizeof(cachedheight)); - angle = (viewangle - ANGLE_90) >> ANGLETOFINESHIFT; - basexscale = FixedDiv(FINECOSINE(angle), centerxfrac); - baseyscale = -FixedDiv(FINESINE(angle), centerxfrac); - } } static void prepare_rastertab(void) From cac8e06e7d228cfd623efa631ccee9c1b1b34bc3 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 5 Nov 2020 00:00:08 -0300 Subject: [PATCH 48/81] Remove NOWATER define --- src/r_draw.c | 3 +++ src/r_draw.h | 10 +++------- src/r_draw8.c | 4 ---- src/r_draw8_npo2.c | 2 -- src/r_plane.c | 26 +++----------------------- src/screen.c | 24 ++++++++---------------- src/screen.h | 16 ++++++++-------- 7 files changed, 25 insertions(+), 60 deletions(-) diff --git a/src/r_draw.c b/src/r_draw.c index eb4dc412f..d9ea942a2 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -100,7 +100,10 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight; INT32 ds_y, ds_x1, ds_x2; lighttable_t *ds_colormap; lighttable_t *ds_translation; // Lactozilla: Sprite splat drawer + fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; +INT32 ds_waterofs, ds_bgofs; + UINT16 ds_flatwidth, ds_flatheight; boolean ds_powersoftwo; diff --git a/src/r_draw.h b/src/r_draw.h index fd40c76ce..9957541ca 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -56,7 +56,10 @@ extern INT32 dc_texheight; extern INT32 ds_y, ds_x1, ds_x2; extern lighttable_t *ds_colormap; extern lighttable_t *ds_translation; + extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; +extern INT32 ds_waterofs, ds_bgofs; + extern UINT16 ds_flatwidth, ds_flatheight; extern boolean ds_powersoftwo; @@ -188,14 +191,9 @@ void R_DrawTiltedTranslucentFloorSprite_8(void); void R_CalcTiltedLighting(fixed_t start, fixed_t end); extern INT32 tiltlighting[MAXVIDWIDTH]; -#ifndef NOWATER void R_DrawTranslucentWaterSpan_8(void); void R_DrawTiltedTranslucentWaterSpan_8(void); -extern INT32 ds_bgofs; -extern INT32 ds_waterofs; -#endif - void R_DrawFogSpan_8(void); // Lactozilla: Non-powers-of-two @@ -213,10 +211,8 @@ void R_DrawTranslucentFloorSprite_NPO2_8(void); void R_DrawTiltedFloorSprite_NPO2_8(void); void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void); -#ifndef NOWATER void R_DrawTranslucentWaterSpan_NPO2_8(void); void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void); -#endif #ifdef USEASM void ASMCALL R_DrawColumn_8_ASM(void); diff --git a/src/r_draw8.c b/src/r_draw8.c index c28a25cbc..e78ba8a6c 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -911,7 +911,6 @@ void R_DrawTiltedTranslucentSpan_8(void) #endif } -#ifndef NOWATER /** \brief The R_DrawTiltedTranslucentWaterSpan_8 function Like DrawTiltedTranslucentSpan, but for water */ @@ -1045,7 +1044,6 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) } #endif } -#endif // NOWATER void R_DrawTiltedSplat_8(void) { @@ -1934,7 +1932,6 @@ void R_DrawTranslucentSpan_8 (void) } } -#ifndef NOWATER void R_DrawTranslucentWaterSpan_8(void) { UINT32 xposition; @@ -2011,7 +2008,6 @@ void R_DrawTranslucentWaterSpan_8(void) yposition += ystep; } } -#endif /** \brief The R_DrawFogSpan_8 function Draws the actual span with fogging. diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 895869e2d..d55e40302 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -1190,7 +1190,6 @@ void R_DrawTranslucentSpan_NPO2_8 (void) } } -#ifndef NOWATER void R_DrawTranslucentWaterSpan_NPO2_8(void) { fixed_t xposition; @@ -1426,4 +1425,3 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) } #endif } -#endif // NOWATER diff --git a/src/r_plane.c b/src/r_plane.c index 789134534..c3bec9a9e 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -115,15 +115,11 @@ void R_InitPlanes(void) } // -// Water ripple effect!! +// Water ripple effect // Needs the height of the plane, and the vertical position of the span. // Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. // -#ifndef NOWATER -INT32 ds_bgofs; -INT32 ds_waterofs; - struct { INT32 offset; @@ -153,7 +149,6 @@ static void R_UpdatePlaneRipple(void) ds_waterofs = (leveltime & 1)*16384; planeripple.offset = (leveltime * 140); } -#endif // // R_MapPlane @@ -219,7 +214,7 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; } -#ifndef NOWATER + // Water ripple effect if (planeripple.active) { // Needed for ds_bgofs @@ -242,7 +237,6 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) if ((y + ds_bgofs) < 0) ds_bgofs = -y; } -#endif if (currentplane->slope) ds_colormap = colormaps; @@ -605,9 +599,7 @@ void R_DrawPlanes(void) visplane_t *pl; INT32 i; - // Note: are these two lines really needed? - // R_DrawSinglePlane and R_DrawSkyPlane do span/column drawer resets themselves anyway - spanfunc = spanfuncs[BASEDRAWFUNC]; + R_UpdatePlaneRipple(); for (i = 0; i < MAXVISPLANES; i++, pl++) { @@ -619,10 +611,6 @@ void R_DrawPlanes(void) R_DrawSinglePlane(pl); } } - -#ifndef NOWATER - R_UpdatePlaneRipple(); -#endif } // R_DrawSkyPlane @@ -798,9 +786,7 @@ void R_DrawSinglePlane(visplane_t *pl) return; } -#ifndef NOWATER planeripple.active = false; -#endif spanfunc = spanfuncs[BASEDRAWFUNC]; if (pl->polyobj) @@ -882,7 +868,6 @@ void R_DrawSinglePlane(visplane_t *pl) } else light = (pl->lightlevel >> LIGHTSEGSHIFT); -#ifndef NOWATER if (pl->ffloor->flags & FF_RIPPLE) { INT32 top, bottom; @@ -908,7 +893,6 @@ void R_DrawSinglePlane(visplane_t *pl) vid.width, vid.width); } } -#endif } else light = (pl->lightlevel >> LIGHTSEGSHIFT); @@ -1016,7 +1000,6 @@ void R_DrawSinglePlane(visplane_t *pl) yoffs = (fixed_t)(yoffs/fudgecanyon); } -#ifndef NOWATER if (planeripple.active) { fixed_t plheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); @@ -1030,16 +1013,13 @@ void R_DrawSinglePlane(visplane_t *pl) } } else -#endif R_SetSlopePlaneVectors(pl, 0, xoffs, yoffs, fudgecanyon); switch (spanfunctype) { -#ifndef NOWATER case SPANDRAWFUNC_WATER: spanfunctype = SPANDRAWFUNC_TILTEDWATER; break; -#endif case SPANDRAWFUNC_TRANS: spanfunctype = SPANDRAWFUNC_TILTEDTRANS; break; diff --git a/src/screen.c b/src/screen.c index 8b6c05b6a..f14cf4bf6 100644 --- a/src/screen.c +++ b/src/screen.c @@ -122,42 +122,34 @@ void SCR_SetDrawFuncs(void) colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8; spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8; + spanfuncs[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_8; + spanfuncs[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_8; spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8; spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8; + spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8; spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8; spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8; spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8; spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_8; - spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8; -#ifndef NOWATER spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8; -#endif - spanfuncs[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_8; - spanfuncs[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_8; -#ifndef NOWATER spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_8; -#endif - spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8; + spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8; // Lactozilla: Non-powers-of-two spanfuncs_npo2[BASEDRAWFUNC] = R_DrawSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_NPO2_8; - spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed -#ifndef NOWATER spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8; -#endif - spanfuncs_npo2[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_NPO2_8; - spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_NPO2_8; -#ifndef NOWATER spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8; -#endif - spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed #ifdef RUSEASM if (R_ASM) diff --git a/src/screen.h b/src/screen.h index b139bd3b4..66452289c 100644 --- a/src/screen.h +++ b/src/screen.h @@ -140,22 +140,22 @@ enum { SPANDRAWFUNC_BASE = BASEDRAWFUNC, SPANDRAWFUNC_TRANS, + SPANDRAWFUNC_TILTED, + SPANDRAWFUNC_TILTEDTRANS, + SPANDRAWFUNC_SPLAT, SPANDRAWFUNC_TRANSSPLAT, + SPANDRAWFUNC_TILTEDSPLAT, + SPANDRAWFUNC_SPRITE, SPANDRAWFUNC_TRANSSPRITE, SPANDRAWFUNC_TILTEDSPRITE, SPANDRAWFUNC_TILTEDTRANSSPRITE, - SPANDRAWFUNC_FOG, -#ifndef NOWATER + SPANDRAWFUNC_WATER, -#endif - SPANDRAWFUNC_TILTED, - SPANDRAWFUNC_TILTEDTRANS, - SPANDRAWFUNC_TILTEDSPLAT, -#ifndef NOWATER SPANDRAWFUNC_TILTEDWATER, -#endif + + SPANDRAWFUNC_FOG, SPANDRAWFUNC_MAX }; From da0f2286e326917a44883b0c0fc44f94e2a6f772 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 5 Nov 2020 00:42:14 -0300 Subject: [PATCH 49/81] P_DeleteFloorSpriteSlope -> P_RemoveFloorSpriteSlope --- src/lua_baselib.c | 6 +++--- src/p_mobj.c | 7 +++---- src/p_mobj.h | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index f320cfdce..b3f826532 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -921,14 +921,14 @@ static int lib_pCreateFloorSpriteSlope(lua_State *L) return 1; } -static int lib_pDeleteFloorSpriteSlope(lua_State *L) +static int lib_pRemoveFloorSpriteSlope(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); - P_DeleteFloorSpriteSlope(mobj); + P_RemoveFloorSpriteSlope(mobj); return 1; } @@ -3559,7 +3559,7 @@ static luaL_Reg lib[] = { {"P_CanRunOnWater",lib_pCanRunOnWater}, {"P_MaceRotate",lib_pMaceRotate}, {"P_CreateFloorSpriteSlope",lib_pCreateFloorSpriteSlope}, - {"P_DeleteFloorSpriteSlope",lib_pDeleteFloorSpriteSlope}, + {"P_RemoveFloorSpriteSlope",lib_pRemoveFloorSpriteSlope}, {"P_RailThinker",lib_pRailThinker}, {"P_XYMovement",lib_pXYMovement}, {"P_RingXYMovement",lib_pRingXYMovement}, diff --git a/src/p_mobj.c b/src/p_mobj.c index 7529b196a..84d9a70b6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10884,7 +10884,7 @@ void *P_CreateFloorSpriteSlope(mobj_t *mobj) return (void *)mobj->floorspriteslope; } -void P_DeleteFloorSpriteSlope(mobj_t *mobj) +void P_RemoveFloorSpriteSlope(mobj_t *mobj) { if (mobj->floorspriteslope) Z_Free(mobj->floorspriteslope); @@ -10947,14 +10947,13 @@ void P_RemoveMobj(mobj_t *mobj) P_DelSeclist(sector_list); sector_list = NULL; } + mobj->flags |= MF_NOSECTOR|MF_NOBLOCKMAP; mobj->subsector = NULL; mobj->state = NULL; mobj->player = NULL; - if (mobj->floorspriteslope) - Z_Free(mobj->floorspriteslope); - mobj->floorspriteslope = NULL; + P_RemoveFloorSpriteSlope(mobj); // stop any playing sound S_StopSound(mobj); diff --git a/src/p_mobj.h b/src/p_mobj.h index a60da67d3..5bb7c908e 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -477,7 +477,7 @@ void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT void P_SpawnPrecipitation(void); void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, statenum_t nstate, angle_t rotangle, boolean spawncenter); void *P_CreateFloorSpriteSlope(mobj_t *mobj); -void P_DeleteFloorSpriteSlope(mobj_t *mobj); +void P_RemoveFloorSpriteSlope(mobj_t *mobj); boolean P_BossTargetPlayer(mobj_t *actor, boolean closest); boolean P_SupermanLook4Players(mobj_t *actor); void P_DestroyRobots(void); From 8599447c7061f8dec37a77c5a6954b69a335815b Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 5 Nov 2020 00:44:10 -0300 Subject: [PATCH 50/81] Remove RF_VOXELSPRITE --- src/dehacked.c | 1 - src/r_defs.h | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 67e83e4d5..820350f20 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9606,7 +9606,6 @@ struct { {"RF_SPRITETYPEMASK",RF_SPRITETYPEMASK}, {"RF_PAPERSPRITE",RF_PAPERSPRITE}, {"RF_FLOORSPRITE",RF_FLOORSPRITE}, - {"RF_VOXELSPRITE",RF_VOXELSPRITE}, {"RF_SHADOWDRAW",RF_SHADOWDRAW}, {"RF_SHADOWEFFECTS",RF_SHADOWEFFECTS}, {"RF_DROPSHADOW",RF_DROPSHADOW}, diff --git a/src/r_defs.h b/src/r_defs.h index 9d0f4247c..664ed5e86 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -731,10 +731,9 @@ typedef enum RF_FULLDARK = 0x0200, // Sprite is drawn completely dark RF_NOCOLORMAPS = 0x0400, // Sprite is not drawn with colormaps - RF_SPRITETYPEMASK = 0x7000, // ---Different sprite types, not all implemented + RF_SPRITETYPEMASK = 0x7000, // ---Different sprite types RF_PAPERSPRITE = 0x1000, // Paper sprite RF_FLOORSPRITE = 0x2000, // Floor sprite - RF_VOXELSPRITE = 0x3000, // Voxel object RF_SHADOWDRAW = 0x10000, // Stretches and skews the sprite like a shadow. RF_SHADOWEFFECTS = 0x20000, // Scales and becomes transparent like a shadow. From 7bf8a4d05679572f589d9548b27a54ffb54bc63c Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Thu, 5 Nov 2020 12:37:49 -0600 Subject: [PATCH 51/81] Make `emeralds` writable. --- src/lua_script.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 6e40cb785..98336c9bf 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -376,6 +376,8 @@ int LUA_CheckGlobals(lua_State *L, const char *word) redscore = (UINT32)luaL_checkinteger(L, 2); else if (fastcmp(word, "bluescore")) bluescore = (UINT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "emeralds")) + emeralds = (UINT16)luaL_checkinteger(L, 2); else return 0; From 69f24e34adbbaf3f5a706e649c53452c2cb98d4f Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Thu, 5 Nov 2020 12:38:47 -0600 Subject: [PATCH 52/81] Make `token` writable. --- src/lua_script.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 98336c9bf..da348d458 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -378,6 +378,8 @@ int LUA_CheckGlobals(lua_State *L, const char *word) bluescore = (UINT32)luaL_checkinteger(L, 2); else if (fastcmp(word, "emeralds")) emeralds = (UINT16)luaL_checkinteger(L, 2); + else if (fastcmp(word, "token")) + token = (UINT32)luaL_checkinteger(L, 2); else return 0; From 4a0fd2309eff425d85e7fcd71d465b71ad97dc73 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Thu, 5 Nov 2020 12:39:03 -0600 Subject: [PATCH 53/81] Make `gravity` writable. --- src/lua_script.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index da348d458..3e749b31b 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -380,6 +380,8 @@ int LUA_CheckGlobals(lua_State *L, const char *word) emeralds = (UINT16)luaL_checkinteger(L, 2); else if (fastcmp(word, "token")) token = (UINT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "gravity")) + gravity = (fixed_t)luaL_checkinteger(L, 2); else return 0; From 3125128be760e901ed624ecc36c436cff3600c35 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Thu, 5 Nov 2020 13:43:33 -0600 Subject: [PATCH 54/81] Make `displayplayer` writable. --- src/lua_script.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 3e749b31b..be33cd35b 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -382,6 +382,13 @@ int LUA_CheckGlobals(lua_State *L, const char *word) token = (UINT32)luaL_checkinteger(L, 2); else if (fastcmp(word, "gravity")) gravity = (fixed_t)luaL_checkinteger(L, 2); + else if (fastcmp(word, "displayplayer")) + { + player_t *player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); + + if (player) + displayplayer = player - players; + } else return 0; From cf3d6eb0af9d6e10b75d7d47bdce1a2f98db078c Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Thu, 5 Nov 2020 15:22:45 -0600 Subject: [PATCH 55/81] Make `stoppedclock` writable. --- src/lua_script.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index be33cd35b..2805a969b 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -382,6 +382,8 @@ int LUA_CheckGlobals(lua_State *L, const char *word) token = (UINT32)luaL_checkinteger(L, 2); else if (fastcmp(word, "gravity")) gravity = (fixed_t)luaL_checkinteger(L, 2); + else if (fastcmp(word, "stoppedclock")) + stoppedclock = luaL_checkboolean(L, 2); else if (fastcmp(word, "displayplayer")) { player_t *player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); From fbd20c959195e0b174359110ecf73cd73ab0c550 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Thu, 5 Nov 2020 17:38:32 -0600 Subject: [PATCH 56/81] Make `skincolor_*` CTF color variables writable. --- src/lua_script.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 2805a969b..29ee094d9 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -376,6 +376,14 @@ int LUA_CheckGlobals(lua_State *L, const char *word) redscore = (UINT32)luaL_checkinteger(L, 2); else if (fastcmp(word, "bluescore")) bluescore = (UINT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "skincolor_redteam")) + skincolor_redteam = (UINT16)luaL_checkinteger(L, 2); + else if (fastcmp(word, "skincolor_blueteam")) + skincolor_blueteam = (UINT16)luaL_checkinteger(L, 2); + else if (fastcmp(word, "skincolor_redring")) + skincolor_redring = (UINT16)luaL_checkinteger(L, 2); + else if (fastcmp(word, "skincolor_bluering")) + skincolor_bluering = (UINT16)luaL_checkinteger(L, 2); else if (fastcmp(word, "emeralds")) emeralds = (UINT16)luaL_checkinteger(L, 2); else if (fastcmp(word, "token")) From 6126e8badf5f9fe0afb6180746bf490720fa8c79 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Thu, 5 Nov 2020 18:12:35 -0600 Subject: [PATCH 57/81] Make `mapmusflags` and `mapmusname` writable. --- src/lua_script.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 29ee094d9..c0e31557e 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -399,6 +399,21 @@ int LUA_CheckGlobals(lua_State *L, const char *word) if (player) displayplayer = player - players; } + else if (fastcmp(word, "mapmusname")) + { + size_t strlength; + const char *str = luaL_checkstring(L, 2, &strlength); + + if (strlength > 6) + return luaL_error(L, "string length out of range (maximum 6 characters)"); + + if (strlen(str) < strlength) + return luaL_error(L, "string must not contain embedded zeros!"); + + strncpy(mapmusname, str, strlength); + } + else if (fastcmp(word, "mapmusflags")) + mapmusflags = (UINT16)luaL_checkinteger(L, 2); else return 0; From 9bb22d5fce67f9523855d3a9dd9e5fe53b3b010e Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 2 Nov 2020 02:33:49 -0800 Subject: [PATCH 58/81] Check that top of sprite is above plane or bottom is below This fixes slightly raised fofs drawing on top of sprites that should be in front of them. Previously would check that the bottom of the object was above the plane. Now also uses sprite offsets like the fof seg sorting does. --- src/r_things.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index cc205f9ea..52ee6617f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2387,19 +2387,15 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps planeobjectz = P_GetZAt(r2->plane->slope, rover->gx, rover->gy, r2->plane->height); planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy, r2->plane->height); - if (rover->mobjflags & MF_NOCLIPHEIGHT) + // bird: if any part of the sprite peeks in front the plane + if (planecameraz < viewz) { - //Objects with NOCLIPHEIGHT can appear halfway in. - if (planecameraz < viewz && rover->pz+(rover->thingheight/2) >= planeobjectz) - continue; - if (planecameraz > viewz && rover->pzt-(rover->thingheight/2) <= planeobjectz) + if (rover->gzt >= planeobjectz) continue; } - else + else if (planecameraz > viewz) { - if (planecameraz < viewz && rover->pz >= planeobjectz) - continue; - if (planecameraz > viewz && rover->pzt <= planeobjectz) + if (rover->gz <= planeobjectz) continue; } From fb181a5b3898be75dce578f17220c37ba8aebb76 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 2 Nov 2020 03:37:16 -0800 Subject: [PATCH 59/81] Remove unused stuff --- src/r_things.c | 20 +------------------- src/r_things.h | 4 +--- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 52ee6617f..da9887108 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1068,14 +1068,6 @@ static void R_SplitSprite(vissprite_t *sprite) sprite->sz = cutfrac; newsprite->szt = (INT16)(sprite->sz - 1); - if (testheight < sprite->pzt && testheight > sprite->pz) - sprite->pz = newsprite->pzt = testheight; - else - { - newsprite->pz = newsprite->gz; - newsprite->pzt = newsprite->gzt; - } - newsprite->szt -= 8; newsprite->cut |= SC_TOP; @@ -1293,16 +1285,12 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, shadow->patch = patch; shadow->heightsec = vis->heightsec; - shadow->thingheight = FRACUNIT; - shadow->pz = groundz + (isflipped ? -shadow->thingheight : 0); - shadow->pzt = shadow->pz + shadow->thingheight; - shadow->mobjflags = 0; shadow->sortscale = vis->sortscale; shadow->dispoffset = vis->dispoffset - 5; shadow->gx = thing->x; shadow->gy = thing->y; - shadow->gzt = (isflipped ? shadow->pzt : shadow->pz) + SHORT(patch->height) * shadowyscale / 2; + shadow->gzt = groundz + SHORT(patch->height) * shadowyscale / 2; shadow->gz = shadow->gzt - SHORT(patch->height) * shadowyscale; shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) @@ -1783,9 +1771,6 @@ static void R_ProjectSprite(mobj_t *thing) vis->gy = thing->y; vis->gz = gz; vis->gzt = gzt; - vis->thingheight = thing->height; - vis->pz = thing->z; - vis->pzt = vis->pz + vis->thingheight; vis->texturemid = vis->gzt - viewz; vis->scalestep = scalestep; vis->paperoffset = paperoffset; @@ -1991,9 +1976,6 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis->gy = thing->y; vis->gz = gz; vis->gzt = gzt; - vis->thingheight = 4*FRACUNIT; - vis->pz = thing->z; - vis->pzt = vis->pz + vis->thingheight; vis->texturemid = vis->gzt - viewz; vis->scalestep = 0; vis->paperdistance = 0; diff --git a/src/r_things.h b/src/r_things.h index b13c5dc55..c9a48dd28 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -138,8 +138,7 @@ typedef struct vissprite_s INT32 x1, x2; fixed_t gx, gy; // for line side calculation - fixed_t gz, gzt; // global bottom/top for silhouette clipping - fixed_t pz, pzt; // physical bottom/top for sorting with 3D floors + fixed_t gz, gzt; // global bottom/top for silhouette clipping and sorting with 3D floors fixed_t startfrac; // horizontal position of x1 fixed_t scale, sortscale; // sortscale only differs from scale for paper sprites and MF2_LINKDRAW @@ -171,7 +170,6 @@ typedef struct vissprite_s fixed_t xscale; // Precalculated top and bottom screen coords for the sprite. - fixed_t thingheight; // The actual height of the thing (for 3D floors) sector_t *sector; // The sector containing the thing. INT16 sz, szt; From cb7b7763cdf0deef185fca9670f5181dfbec6e89 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 5 Nov 2020 04:55:01 -0800 Subject: [PATCH 60/81] Do not factor height into sprite thickseg sorting --- src/r_things.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index da9887108..7d3f2be3d 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2410,7 +2410,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps } else if (r2->thickseg) { - fixed_t topplaneobjectz, topplanecameraz, botplaneobjectz, botplanecameraz; + //fixed_t topplaneobjectz, topplanecameraz, botplaneobjectz, botplanecameraz; if (rover->x1 > r2->thickseg->x2 || rover->x2 < r2->thickseg->x1) continue; @@ -2421,6 +2421,11 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps if (scale <= rover->sortscale) continue; + // bird: Always sort sprites behind segs. This helps the plane + // sorting above too. Basically if the sprite gets sorted behind + // the seg here, it will be behind the plane too, since planes + // are added after segs in the list. +#if 0 topplaneobjectz = P_GetFFloorTopZAt (r2->ffloor, rover->gx, rover->gy); topplanecameraz = P_GetFFloorTopZAt (r2->ffloor, viewx, viewy); botplaneobjectz = P_GetFFloorBottomZAt(r2->ffloor, rover->gx, rover->gy); @@ -2429,6 +2434,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps if ((topplanecameraz > viewz && botplanecameraz < viewz) || (topplanecameraz < viewz && rover->gzt < topplaneobjectz) || (botplanecameraz > viewz && rover->gz > botplaneobjectz)) +#endif { entry = R_CreateDrawNode(NULL); (entry->prev = r2->prev)->next = entry; From d2e8823d50b9e2b451d85b67dc9d05cfb3f205ac Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sun, 8 Nov 2020 20:43:16 -0600 Subject: [PATCH 61/81] Add skincolor vars to the NetSave --- src/p_saveg.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 4f6f31803..9dbe5445b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3990,6 +3990,12 @@ static void P_NetArchiveMisc(void) WRITEINT32(save_p, sstimer); WRITEUINT32(save_p, bluescore); WRITEUINT32(save_p, redscore); + + WRITEUINT16(save_p, skincolor_redteam); + WRITEUINT16(save_p, skincolor_blueteam); + WRITEUINT16(save_p, skincolor_redring); + WRITEUINT16(save_p, skincolor_bluering); + WRITEINT32(save_p, modulothing); WRITEINT16(save_p, autobalance); @@ -4074,6 +4080,12 @@ static inline boolean P_NetUnArchiveMisc(void) sstimer = READINT32(save_p); bluescore = READUINT32(save_p); redscore = READUINT32(save_p); + + skincolor_redteam = READUINT16(save_p); + skincolor_blueteam = READUINT16(save_p); + skincolor_redring = READUINT16(save_p); + skincolor_bluering = READUINT16(save_p); + modulothing = READINT32(save_p); autobalance = READINT16(save_p); From 3b48adc98aee265efd2ded3d41df3d22a34e19f0 Mon Sep 17 00:00:00 2001 From: Riku Salminen <38985578+Riku-S@users.noreply.github.com> Date: Mon, 9 Nov 2020 17:01:20 +0200 Subject: [PATCH 62/81] Made height/spinheight and height change values in replays more accurate --- src/g_demo.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 0f72ad109..9d3b86015 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -453,8 +453,7 @@ void G_WriteGhostTic(mobj_t *ghost) WRITEUINT16(demo_p,oldghost.sprite); if (ghostext.flags & EZT_HEIGHT) { - height >>= FRACBITS; - WRITEINT16(demo_p, height); + WRITEFIXED(demo_p, height); } ghostext.flags = 0; } @@ -610,7 +609,7 @@ void G_ConsGhostTic(void) if (xziptic & EZT_SPRITE) demo_p += sizeof(UINT16); if (xziptic & EZT_HEIGHT) - demo_p += sizeof(INT16); + demo_p += (demoversion < 0x000e) ? sizeof(INT16) : sizeof(fixed_t); } if (ziptic & GZT_FOLLOW) @@ -842,7 +841,7 @@ void G_GhostTicker(void) g->mo->sprite = READUINT16(g->p); if (xziptic & EZT_HEIGHT) { - fixed_t temp = READINT16(g->p)<version < 0x000e) ? READINT16(g->p)<p); g->mo->height = FixedMul(temp, g->mo->scale); } } @@ -1106,7 +1105,7 @@ void G_ReadMetalTic(mobj_t *metal) metal->sprite = READUINT16(metal_p); if (xziptic & EZT_HEIGHT) { - fixed_t temp = READINT16(metal_p)<height = FixedMul(temp, metal->scale); } } @@ -1293,8 +1292,7 @@ void G_WriteMetalTic(mobj_t *metal) WRITEUINT16(demo_p,oldmetal.sprite); if (ghostext.flags & EZT_HEIGHT) { - height >>= FRACBITS; - WRITEINT16(demo_p, height); + WRITEFIXED(demo_p, height); } ghostext.flags = 0; } @@ -1474,8 +1472,8 @@ void G_BeginRecording(void) WRITEUINT8(demo_p,player->thrustfactor); WRITEUINT8(demo_p,player->accelstart); WRITEUINT8(demo_p,player->acceleration); - WRITEUINT8(demo_p,player->height>>FRACBITS); - WRITEUINT8(demo_p,player->spinheight>>FRACBITS); + WRITEFIXED(demo_p,player->height); + WRITEFIXED(demo_p,player->spinheight); WRITEUINT8(demo_p,player->camerascale>>FRACBITS); WRITEUINT8(demo_p,player->shieldscale>>FRACBITS); @@ -1901,8 +1899,8 @@ void G_DoPlayDemo(char *defdemoname) thrustfactor = READUINT8(demo_p); accelstart = READUINT8(demo_p); acceleration = READUINT8(demo_p); - height = (fixed_t)READUINT8(demo_p)< Date: Mon, 9 Nov 2020 18:55:00 -0500 Subject: [PATCH 63/81] Make the replay camera follow the player --- src/p_tick.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/p_tick.c b/src/p_tick.c index f84ae96c0..4fd08f987 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -639,7 +639,12 @@ void P_Ticker(boolean run) if (demorecording) G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); if (demoplayback) + { G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); + P_SetPlayerAngle(&players[consoleplayer], players[consoleplayer].mo->angle); + P_ForceLocalAngle(&players[consoleplayer], players[consoleplayer].mo->angle); + localaiming = players[consoleplayer].aiming; + } LUAh_PreThinkFrame(); From 222359a464251682e8d7da0a249d44d44a4b1547 Mon Sep 17 00:00:00 2001 From: Riku Salminen Date: Tue, 10 Nov 2020 04:17:25 -0500 Subject: [PATCH 64/81] Update p_tick.c, got rid of an useless angle change function --- src/p_tick.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_tick.c b/src/p_tick.c index 4fd08f987..b49b27cc8 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -640,10 +640,10 @@ void P_Ticker(boolean run) G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); if (demoplayback) { - G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); - P_SetPlayerAngle(&players[consoleplayer], players[consoleplayer].mo->angle); - P_ForceLocalAngle(&players[consoleplayer], players[consoleplayer].mo->angle); - localaiming = players[consoleplayer].aiming; + player_t* p = &players[consoleplayer]; + G_ReadDemoTiccmd(&p->cmd, 0); + P_ForceLocalAngle(p, p->mo->angle); + localaiming = p->aiming; } LUAh_PreThinkFrame(); From 5c108205146a5d3144e21246eb5e25c1c87effaa Mon Sep 17 00:00:00 2001 From: Riku Salminen Date: Tue, 10 Nov 2020 04:31:26 -0500 Subject: [PATCH 65/81] Update p_tick.c, Replacing mobj angle with cmd angleturn --- src/p_tick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_tick.c b/src/p_tick.c index b49b27cc8..15ec57054 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -642,7 +642,7 @@ void P_Ticker(boolean run) { player_t* p = &players[consoleplayer]; G_ReadDemoTiccmd(&p->cmd, 0); - P_ForceLocalAngle(p, p->mo->angle); + P_ForceLocalAngle(p, p->cmd.angleturn << 16); localaiming = p->aiming; } From cd18b9365b377793e1d359056cdf1906e46f9169 Mon Sep 17 00:00:00 2001 From: Riku Salminen <38985578+Riku-S@users.noreply.github.com> Date: Tue, 10 Nov 2020 13:06:47 +0200 Subject: [PATCH 66/81] Try to add cvars for old camera --- src/d_netcmd.c | 2 ++ src/p_tick.c | 8 ++++++-- src/p_tick.h | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 68b8ecfc1..ac1c0da1e 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -884,6 +884,8 @@ void D_RegisterClientCommands(void) // CV_RegisterVar(&cv_grid); // CV_RegisterVar(&cv_snapto); + CV_RegisterVar(&cv_freedemocamera); + // add cheat commands COM_AddCommand("noclip", Command_CheatNoClip_f); COM_AddCommand("god", Command_CheatGod_f); diff --git a/src/p_tick.c b/src/p_tick.c index 15ec57054..05ffefa7a 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -37,6 +37,7 @@ tic_t leveltime; // The entries will behave like both the head and tail of the lists. thinker_t thlist[NUM_THINKERLISTS]; +consvar_t cv_freedemocamera = {"freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; void Command_Numthinkers_f(void) { @@ -642,8 +643,11 @@ void P_Ticker(boolean run) { player_t* p = &players[consoleplayer]; G_ReadDemoTiccmd(&p->cmd, 0); - P_ForceLocalAngle(p, p->cmd.angleturn << 16); - localaiming = p->aiming; + if (!cv_freedemocamera.value) + { + P_ForceLocalAngle(p, p->cmd.angleturn << 16); + localaiming = p->aiming; + } } LUAh_PreThinkFrame(); diff --git a/src/p_tick.h b/src/p_tick.h index 1fb88f3f2..3b04a427a 100644 --- a/src/p_tick.h +++ b/src/p_tick.h @@ -19,6 +19,7 @@ #endif extern tic_t leveltime; +extern consvar_t cv_freedemocamera; // Called by G_Ticker. Carries out all thinking of enemies and players. void Command_Numthinkers_f(void); From 1d1b508cc899bee31e7b888ed015d96e383f4bbd Mon Sep 17 00:00:00 2001 From: Riku Salminen Date: Mon, 9 Nov 2020 18:55:00 -0500 Subject: [PATCH 67/81] Make the replay camera follow the player --- src/p_tick.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/p_tick.c b/src/p_tick.c index 451e5e626..a2ea2ff0f 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -643,7 +643,12 @@ void P_Ticker(boolean run) if (demorecording) G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); if (demoplayback) + { G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); + P_SetPlayerAngle(&players[consoleplayer], players[consoleplayer].mo->angle); + P_ForceLocalAngle(&players[consoleplayer], players[consoleplayer].mo->angle); + localaiming = players[consoleplayer].aiming; + } ps_lua_mobjhooks = 0; ps_checkposition_calls = 0; From bb162168390200c6ada43b0898a683aab4759e80 Mon Sep 17 00:00:00 2001 From: Riku Salminen Date: Tue, 10 Nov 2020 04:17:25 -0500 Subject: [PATCH 68/81] Update p_tick.c, got rid of an useless angle change function --- src/p_tick.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_tick.c b/src/p_tick.c index a2ea2ff0f..c03884eeb 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -644,10 +644,10 @@ void P_Ticker(boolean run) G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); if (demoplayback) { - G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); - P_SetPlayerAngle(&players[consoleplayer], players[consoleplayer].mo->angle); - P_ForceLocalAngle(&players[consoleplayer], players[consoleplayer].mo->angle); - localaiming = players[consoleplayer].aiming; + player_t* p = &players[consoleplayer]; + G_ReadDemoTiccmd(&p->cmd, 0); + P_ForceLocalAngle(p, p->mo->angle); + localaiming = p->aiming; } ps_lua_mobjhooks = 0; From 27931ca32e0d9fd87f1b8ba8ba0814c6a58b3449 Mon Sep 17 00:00:00 2001 From: Riku Salminen Date: Tue, 10 Nov 2020 04:31:26 -0500 Subject: [PATCH 69/81] Update p_tick.c, Replacing mobj angle with cmd angleturn --- src/p_tick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_tick.c b/src/p_tick.c index c03884eeb..90f410f9d 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -646,7 +646,7 @@ void P_Ticker(boolean run) { player_t* p = &players[consoleplayer]; G_ReadDemoTiccmd(&p->cmd, 0); - P_ForceLocalAngle(p, p->mo->angle); + P_ForceLocalAngle(p, p->cmd.angleturn << 16); localaiming = p->aiming; } From 16a4ab37d31394647e556a7818a8a079617d9387 Mon Sep 17 00:00:00 2001 From: Riku Salminen <38985578+Riku-S@users.noreply.github.com> Date: Tue, 10 Nov 2020 13:06:47 +0200 Subject: [PATCH 70/81] Try to add cvars for old camera --- src/d_netcmd.c | 2 ++ src/p_tick.c | 8 ++++++-- src/p_tick.h | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 87abd596a..a113460f5 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -880,6 +880,8 @@ void D_RegisterClientCommands(void) // CV_RegisterVar(&cv_grid); // CV_RegisterVar(&cv_snapto); + CV_RegisterVar(&cv_freedemocamera); + // add cheat commands COM_AddCommand("noclip", Command_CheatNoClip_f); COM_AddCommand("god", Command_CheatGod_f); diff --git a/src/p_tick.c b/src/p_tick.c index 90f410f9d..24d5005e1 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -39,6 +39,7 @@ tic_t leveltime; // The entries will behave like both the head and tail of the lists. thinker_t thlist[NUM_THINKERLISTS]; +consvar_t cv_freedemocamera = {"freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; void Command_Numthinkers_f(void) { @@ -646,8 +647,11 @@ void P_Ticker(boolean run) { player_t* p = &players[consoleplayer]; G_ReadDemoTiccmd(&p->cmd, 0); - P_ForceLocalAngle(p, p->cmd.angleturn << 16); - localaiming = p->aiming; + if (!cv_freedemocamera.value) + { + P_ForceLocalAngle(p, p->cmd.angleturn << 16); + localaiming = p->aiming; + } } ps_lua_mobjhooks = 0; diff --git a/src/p_tick.h b/src/p_tick.h index 1fb88f3f2..3b04a427a 100644 --- a/src/p_tick.h +++ b/src/p_tick.h @@ -19,6 +19,7 @@ #endif extern tic_t leveltime; +extern consvar_t cv_freedemocamera; // Called by G_Ticker. Carries out all thinking of enemies and players. void Command_Numthinkers_f(void); From 0cefac70d3475509bacdbf416408c1639ae69b5d Mon Sep 17 00:00:00 2001 From: Riku Salminen <38985578+Riku-S@users.noreply.github.com> Date: Tue, 10 Nov 2020 13:53:31 +0200 Subject: [PATCH 71/81] Declared the cvar in netcmd to get rid of warnings --- src/d_netcmd.c | 1 + src/d_netcmd.h | 2 ++ src/p_tick.c | 1 - src/p_tick.h | 1 - 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a113460f5..6f4675e4a 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -374,6 +374,7 @@ consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL) static CV_PossibleValue_t perfstats_cons_t[] = { {0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}}; consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL); +consvar_t cv_freedemocamera = CVAR_INIT("freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL); char timedemo_name[256]; boolean timedemo_csv; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 841f71acd..7ecdd4e12 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -121,6 +121,8 @@ extern boolean timedemo_csv; extern char timedemo_csv_id[256]; extern boolean timedemo_quit; +extern consvar_t cv_freedemocamera; + typedef enum { XD_NAMEANDCOLOR = 1, diff --git a/src/p_tick.c b/src/p_tick.c index 24d5005e1..da2a980c4 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -39,7 +39,6 @@ tic_t leveltime; // The entries will behave like both the head and tail of the lists. thinker_t thlist[NUM_THINKERLISTS]; -consvar_t cv_freedemocamera = {"freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; void Command_Numthinkers_f(void) { diff --git a/src/p_tick.h b/src/p_tick.h index 3b04a427a..1fb88f3f2 100644 --- a/src/p_tick.h +++ b/src/p_tick.h @@ -19,7 +19,6 @@ #endif extern tic_t leveltime; -extern consvar_t cv_freedemocamera; // Called by G_Ticker. Carries out all thinking of enemies and players. void Command_Numthinkers_f(void); From 19b11a8c7548d45246fd2ec9e0ea12e98cff1fc4 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Fri, 13 Nov 2020 11:33:27 +0100 Subject: [PATCH 72/81] Remove direct definition for D__USE_MINGW_ANSI_STDIO, as the latest standards consider this to be deprecated. --- src/win32/Makefile.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg index bf68f8c97..486616f2d 100644 --- a/src/win32/Makefile.cfg +++ b/src/win32/Makefile.cfg @@ -59,7 +59,6 @@ endif ifndef SDL OPTS+=-D_WINDOWS endif - OPTS+=-D__USE_MINGW_ANSI_STDIO=0 ifndef SDL LIBS+=-lmingw32 -mwindows -ldinput -ldxguid -lgdi32 -lwinmm From 3840303b0246e42906eec2b593c8b483fa4cfeda Mon Sep 17 00:00:00 2001 From: lachwright Date: Sun, 15 Nov 2020 01:13:41 +1100 Subject: [PATCH 73/81] Use SDL version of executable icon at runtime on macOS --- src/sdl/i_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index c8f67da77..413ba0b4e 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -42,7 +42,7 @@ #ifdef HAVE_IMAGE #include "SDL_image.h" -#elif defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) // Windows doesn't need this, as SDL will do it for us. +#elif defined (__unix__) || !defined(__APPLE__) && defined (UNIXCOMMON) // Windows & Mac don'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 From 66edde25567ae22f108423d2c5ddbdffc909f8bd Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 14 Nov 2020 15:56:40 -0800 Subject: [PATCH 74/81] Remove unused music type enums --- src/dehacked.c | 1 - src/i_sound.h | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 3ef3a9572..532c5c2c8 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -10111,7 +10111,6 @@ struct { // music types {"MU_NONE", MU_NONE}, - {"MU_CMD", MU_CMD}, {"MU_WAV", MU_WAV}, {"MU_MOD", MU_MOD}, {"MU_MID", MU_MID}, diff --git a/src/i_sound.h b/src/i_sound.h index a2249a102..d45c0b323 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -21,15 +21,12 @@ // copied from SDL mixer, plus GME typedef enum { MU_NONE, - MU_CMD, MU_WAV, MU_MOD, MU_MID, MU_OGG, MU_MP3, - MU_MP3_MAD_UNUSED, // use MU_MP3 instead MU_FLAC, - MU_MODPLUG_UNUSED, // use MU_MOD instead MU_GME, MU_MOD_EX, // libopenmpt MU_MID_EX // Non-native MIDI From dd4065795a7955955cf993124d03bd32eea6b76a Mon Sep 17 00:00:00 2001 From: lachwright Date: Sun, 15 Nov 2020 15:52:55 +1100 Subject: [PATCH 75/81] Add parentheses --- src/sdl/i_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 413ba0b4e..972d208d4 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -42,7 +42,7 @@ #ifdef HAVE_IMAGE #include "SDL_image.h" -#elif defined (__unix__) || !defined(__APPLE__) && defined (UNIXCOMMON) // Windows & Mac don't need this, as SDL will do it for us. +#elif defined (__unix__) || (!defined(__APPLE__) && defined (UNIXCOMMON)) // Windows & Mac don'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 From 6f315c7bb1e504f0e95034dfbff14146520f7024 Mon Sep 17 00:00:00 2001 From: lachwright Date: Mon, 16 Nov 2020 17:37:12 +1100 Subject: [PATCH 76/81] Uncap palette lump palettes & allow flashpal palettes to display during pause --- src/st_stuff.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 86e0b3754..246272c3a 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -203,9 +203,7 @@ void ST_doPaletteStuff(void) { INT32 palette; - if (paused || P_AutoPause()) - palette = 0; - else if (stplyr && stplyr->flashcount) + if (stplyr && stplyr->flashcount) palette = stplyr->flashpal; else palette = 0; @@ -215,8 +213,6 @@ void ST_doPaletteStuff(void) palette = 0; // No flashpals here in OpenGL #endif - palette = min(max(palette, 0), 13); - if (palette != st_palette) { st_palette = palette; From 09fe7d5f1b2a4dda7b01bba0fabb765f8b13624e Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Thu, 19 Nov 2020 00:59:37 -0300 Subject: [PATCH 77/81] Update R_DrawFloorSprite_NPO2_8 and R_DrawTranslucentFloorSprite_NPO2_8 to have the lastest NPO2 optimizations --- src/r_draw8_npo2.c | 86 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index ea5691e7c..a34a20e9a 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -818,6 +818,8 @@ void R_DrawFloorSprite_NPO2_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + fixed_t x, y; + fixed_t fixedwidth, fixedheight; UINT16 *source; UINT8 *translation; @@ -836,20 +838,39 @@ void R_DrawFloorSprite_NPO2_8 (void) translation = ds_translation; dest = ylookup[ds_y] + columnofs[ds_x1]; + fixedwidth = ds_flatwidth << FRACBITS; + fixedheight = ds_flatheight << FRACBITS; + + // Fix xposition and yposition if they are out of bounds. + if (xposition < 0) + xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth); + else if (xposition >= fixedwidth) + xposition %= fixedwidth; + if (yposition < 0) + yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight); + else if (yposition >= fixedheight) + yposition %= fixedheight; + 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; + // The loops here keep the texture coordinates within the texture. + // They will rarely iterate multiple times, and are cheaper than a modulo operation, + // even if using libdivide. + if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop + while (xposition < 0) + xposition += fixedwidth; + else + while (xposition >= fixedwidth) + xposition -= fixedwidth; + if (ystep < 0) + while (yposition < 0) + yposition += fixedheight; + else + while (yposition >= fixedheight) + yposition -= fixedheight; + x = (xposition >> FRACBITS); + y = (yposition >> FRACBITS); val = source[((y * ds_flatwidth) + x)]; if (val & 0xFF00) *dest = colormap[translation[val & 0xFF]]; @@ -867,6 +888,8 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + fixed_t x, y; + fixed_t fixedwidth, fixedheight; UINT16 *source; UINT8 *translation; @@ -885,20 +908,39 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void) translation = ds_translation; dest = ylookup[ds_y] + columnofs[ds_x1]; + fixedwidth = ds_flatwidth << FRACBITS; + fixedheight = ds_flatheight << FRACBITS; + + // Fix xposition and yposition if they are out of bounds. + if (xposition < 0) + xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth); + else if (xposition >= fixedwidth) + xposition %= fixedwidth; + if (yposition < 0) + yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight); + else if (yposition >= fixedheight) + yposition %= fixedheight; + 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; + // The loops here keep the texture coordinates within the texture. + // They will rarely iterate multiple times, and are cheaper than a modulo operation, + // even if using libdivide. + if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop + while (xposition < 0) + xposition += fixedwidth; + else + while (xposition >= fixedwidth) + xposition -= fixedwidth; + if (ystep < 0) + while (yposition < 0) + yposition += fixedheight; + else + while (yposition >= fixedheight) + yposition -= fixedheight; + x = (xposition >> FRACBITS); + y = (yposition >> FRACBITS); val = source[((y * ds_flatwidth) + x)]; if (val & 0xFF00) *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); From f49136136aa91c00c1fd4e405c8425a3915bfd42 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Thu, 19 Nov 2020 15:17:56 -0600 Subject: [PATCH 78/81] Echo filenames when compiling without ECHO=1 --- src/Makefile | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/Makefile b/src/Makefile index 5d5db056f..fe1f6bec6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -537,6 +537,13 @@ OBJS:=$(i_main_o) \ $(i_sound_o) \ $(OBJS) + +ifndef ECHO +define echoName = + @echo -- $< ... +endef +endif + # List of languages to compile. # For reference, this is the command I use to build a srb2.pot file from the source code. # (The listed source files are the ones containing translated strings). @@ -697,6 +704,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ else $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ @@ -706,6 +714,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@ endif endif @@ -734,43 +743,55 @@ endif ifdef VALGRIND $(OBJDIR)/z_zone.o: z_zone.c + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -DHAVE_VALGRIND $(VALGRIND_CFLAGS) -c $< -o $@ endif $(OBJDIR)/comptime.o: comptime.c pre-build + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(BIN)/%.mo: locale/%.po -$(MKDIR) $(BIN) + $(echoName) $(MSGFMT) -f -o $@ $< $(OBJDIR)/%.o: %.c + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(OBJDIR)/%.o: $(INTERFACE)/%.c + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ ifdef MACOSX $(OBJDIR)/%.o: sdl/macosx/%.c + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ endif $(OBJDIR)/%.o: hardware/%.c + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(OBJDIR)/%.o: blua/%.c + $(echoName) $(CC) $(CFLAGS) $(LUA_CFLAGS) $(WFLAGS) -c $< -o $@ $(OBJDIR)/%.o: %.nas + $(echoName) $(NASM) $(NASMOPTS) -o $@ -f $(NASMFORMAT) $< $(OBJDIR)/vid_copy.o: vid_copy.s asm_defs.inc + $(echoName) $(CC) $(OPTS) $(ASFLAGS) -x assembler-with-cpp -c $< -o $@ $(OBJDIR)/%.o: %.s + $(echoName) $(CC) $(OPTS) -x assembler-with-cpp -c $< -o $@ $(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h + $(echoName) $(WINDRES) -i $< -O rc $(WINDRESFLAGS) --include-dir=win32 -o $@ -O coff @@ -784,6 +805,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \ @@ -793,6 +815,7 @@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \ hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@ endif @@ -803,31 +826,37 @@ ifdef SDL ifdef MINGW $(OBJDIR)/win_dbg.o: win32/win_dbg.c + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ endif ifdef STATICHS $(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \ hardware/hw_dll.h + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \ hardware/hw_dll.h + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ ifdef MINGW $(OBJDIR)/s_ds3d.o: hardware/s_ds3d/s_ds3d.c hardware/hw3dsdrv.h \ hardware/hw_dll.h + $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ endif else $(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \ hardware/hw_dll.h + $(echoName) $(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_fmod.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_fmod/s_fmod.c $(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \ hardware/hw_dll.h + $(echoName) $(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_openal.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_openal/s_openal.c endif endif From b4c88e92d9aff506e8d2580555e124867b9ae73e Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sat, 21 Nov 2020 22:21:18 -0600 Subject: [PATCH 79/81] Add NOECHOFILENAMES, if people don't want logspam. --- src/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Makefile b/src/Makefile index fe1f6bec6..71f4b4cc9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -539,10 +539,12 @@ OBJS:=$(i_main_o) \ ifndef ECHO +ifndef NOECHOFILENAMES define echoName = @echo -- $< ... endef endif +endif # List of languages to compile. # For reference, this is the command I use to build a srb2.pot file from the source code. From 1a2c2c84718eb63b053b25d5e178d37a60973e12 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 22 Nov 2020 15:12:34 -0800 Subject: [PATCH 80/81] Resolve one last conflict in splat sorting Can't use gz/gzt because there is no transformation to make those work differently for splats. --- src/r_things.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 2daa6984d..01c02aec4 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2656,23 +2656,11 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps if (!behind) { - fixed_t z1 = 0, z2 = 0; - - if (rover->mobj->z - viewz > 0) - { - z1 = rover->pz; - z2 = r2->sprite->pz; - } + // FIXME: calculate gz and gzt for splats properly and use that + if (rover->mobj->z < viewz) + infront = (r2->sprite->mobj->z >= rover->mobj->z); else - { - z1 = r2->sprite->pz; - z2 = rover->pz; - } - - z1 -= viewz; - z2 -= viewz; - - infront = (z1 >= z2); + infront = (r2->sprite->mobj->z <= rover->mobj->z); } } else From 8a9c3c57f778aa22d3d676dadf7ff74d3847bcfc Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Mon, 23 Nov 2020 21:20:17 -0600 Subject: [PATCH 81/81] Fix a dumb typo of luaL_checklstring i made whoops --- src/lua_script.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_script.c b/src/lua_script.c index 160746e9e..14619a220 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -402,7 +402,7 @@ int LUA_CheckGlobals(lua_State *L, const char *word) else if (fastcmp(word, "mapmusname")) { size_t strlength; - const char *str = luaL_checkstring(L, 2, &strlength); + const char *str = luaL_checklstring(L, 2, &strlength); if (strlength > 6) return luaL_error(L, "string length out of range (maximum 6 characters)");