From da8809c911e2ccef05030d1be12317875184e06b Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 5 Dec 2022 13:12:41 -0800 Subject: [PATCH 1/4] Clean up code duplication around RANGECHECK in r_things.c --- src/r_things.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index cc0d46a2a..330029707 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1034,14 +1034,13 @@ static void R_DrawVisSprite(vissprite_t *vis) // 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; + +#ifdef RANGECHECK 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 + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); localcolfunc (column, NULL, baseclip); @@ -1056,14 +1055,13 @@ static void R_DrawVisSprite(vissprite_t *vis) // Non-paper drawing loop for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan) { -#ifdef RANGECHECK texturecolumn = frac>>FRACBITS; + +#ifdef RANGECHECK 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 + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); localcolfunc (column, NULL, baseclip); } } @@ -1079,9 +1077,7 @@ static void R_DrawVisSprite(vissprite_t *vis) static void R_DrawPrecipitationVisSprite(vissprite_t *vis) { column_t *column; -#ifdef RANGECHECK INT32 texturecolumn; -#endif fixed_t frac; patch_t *patch; fixed_t this_scale = vis->thingscale; @@ -1128,16 +1124,15 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) { -#ifdef RANGECHECK texturecolumn = frac>>FRACBITS; +#ifdef RANGECHECK if (texturecolumn < 0 || texturecolumn >= patch->width) I_Error("R_DrawPrecipitationSpriteRange: bad texturecolumn"); +#endif column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); -#else - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); -#endif + R_DrawMaskedColumn(column, NULL, -1); } From 9c8d6dfaa673a550debf19ea130f8bf7e0784894 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 3 Dec 2022 03:34:54 -0800 Subject: [PATCH 2/4] Add BrightMap support to SPRTINFO --- src/r_picformats.c | 17 ++++++++++++++--- src/r_picformats.h | 1 + src/r_things.c | 34 ++++++++++++++++++++++++++++++---- src/r_things.h | 1 + 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/r_picformats.c b/src/r_picformats.c index 1f39ae42c..f8e3d3ca5 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1474,9 +1474,10 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean size_t sprinfoTokenLength; char *frameChar = NULL; UINT8 frameFrame = 0xFF; - INT16 frameXPivot = 0; - INT16 frameYPivot = 0; + INT16 frameXPivot = INT16_MIN; + INT16 frameYPivot = INT16_MIN; rotaxis_t frameRotAxis = 0; + char *bright = NULL; if (all) { @@ -1541,6 +1542,11 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean else if ((stricmp(sprinfoToken, "Z")==0) || (stricmp(sprinfoToken, "ZAXIS")==0) || (stricmp(sprinfoToken, "YAW")==0)) frameRotAxis = ROTAXIS_Z; } + else if (stricmp(sprinfoToken, "BRIGHTMAP")==0) + { + Z_Free(bright); + bright = M_GetToken(NULL); + } Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); @@ -1557,8 +1563,13 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean parser->info->pivot[frameFrame].x = frameXPivot; parser->info->pivot[frameFrame].y = frameYPivot; parser->info->pivot[frameFrame].rotaxis = frameRotAxis; + Z_Free(parser->info->bright[frameFrame]); + parser->info->bright[frameFrame] = bright; - set_bit_array(parser->info->available, frameFrame); + if (frameXPivot != INT16_MIN || frameYPivot != INT16_MIN) + { + set_bit_array(parser->info->available, frameFrame); + } if (parser->spr2) { diff --git a/src/r_picformats.h b/src/r_picformats.h index 57af58100..3ab520f5f 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -103,6 +103,7 @@ struct spriteinfo_t spriteframepivot_t pivot[64 + 1]; #define SPRINFO_DEFAULT_PIVOT (64) UINT8 available[BIT_ARRAY_SIZE(64 + 1)]; // 1 extra for default_pivot + char *bright[64 + 1]; // brightmap lump name }; // Portable Network Graphics diff --git a/src/r_things.c b/src/r_things.c index 330029707..6f1dd436a 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -862,12 +862,13 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis) // static void R_DrawVisSprite(vissprite_t *vis) { - column_t *column; + column_t *column, *bmcol = NULL; void (*localcolfunc)(column_t *, column_t *, INT32); INT32 texturecolumn; INT32 pwidth; fixed_t frac; patch_t *patch = vis->patch; + patch_t *bmpatch = vis->bright; fixed_t this_scale = vis->thingscale; INT32 x1, x2; INT64 overflow_test; @@ -1022,7 +1023,10 @@ static void R_DrawVisSprite(vissprite_t *vis) column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - localcolfunc (column, NULL, baseclip); + if (bmpatch) + bmcol = (column_t *)((UINT8 *)bmpatch->columns + (bmpatch->columnofs[texturecolumn])); + + localcolfunc (column, bmcol, baseclip); } } else if (vis->cut & SC_SHEAR) @@ -1041,9 +1045,11 @@ static void R_DrawVisSprite(vissprite_t *vis) I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); #endif column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); + if (bmpatch) + bmcol = (column_t *)((UINT8 *)bmpatch->columns + (bmpatch->columnofs[texturecolumn])); sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); - localcolfunc (column, NULL, baseclip); + localcolfunc (column, bmcol, baseclip); } } else @@ -1062,7 +1068,11 @@ static void R_DrawVisSprite(vissprite_t *vis) I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); #endif column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - localcolfunc (column, NULL, baseclip); + + if (bmpatch) + bmcol = (column_t *)((UINT8 *)bmpatch->columns + (bmpatch->columnofs[texturecolumn])); + + localcolfunc (column, bmcol, baseclip); } } @@ -1219,6 +1229,18 @@ static void R_SplitSprite(vissprite_t *sprite) } } +static patch_t *R_CacheSpriteBrightMap(const spriteinfo_t *sprinfo, UINT8 frame) +{ + const char *name = sprinfo->bright[frame]; + + if (name == NULL) + { + name = sprinfo->bright[SPRINFO_DEFAULT_PIVOT]; + } + + return W_CachePatchNum(W_CheckNumForLongName(name), PU_SPRITE); +} + // // R_GetShadowZ(thing, shadowslope) // Get the first visible floor below the object for shadows @@ -1395,6 +1417,7 @@ static void R_ProjectDropShadow( shadow = R_NewVisSprite(); shadow->patch = patch; + shadow->bright = NULL; shadow->heightsec = vis->heightsec; shadow->mobjflags = 0; @@ -2320,6 +2343,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->cut |= SC_SPLAT; // I like ya cut g vis->patch = patch; + vis->bright = R_CacheSpriteBrightMap(sprinfo, frame); if (thing->subsector->sector->numlights && !(shadowdraw || splat)) R_SplitSprite(vis); @@ -2503,6 +2527,8 @@ 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_SPRITE); + vis->bright = R_CacheSpriteBrightMap(&spriteinfo[thing->sprite], + thing->frame & FF_FRAMEMASK); vis->transmap = R_GetBlendTable(blendmode, trans); diff --git a/src/r_things.h b/src/r_things.h index f27f3a7c9..bf49e9f13 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -186,6 +186,7 @@ struct vissprite_t fixed_t texturemid; patch_t *patch; + patch_t *bright; lighttable_t *colormap; // for color translation and shadow draw // maxbright frames as well From c90d4f8b976364b7efa8a34e33cf1a847a495687 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 5 Dec 2022 13:34:07 -0800 Subject: [PATCH 3/4] Lua spriteinfo brightmap support --- src/lua_infolib.c | 64 ++++++++++++++++++++++++++++++++++++++--------- src/lua_libs.h | 1 + 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 0b8359065..0c90dd00f 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -266,6 +266,20 @@ static UINT8 GetPivotFrame(lua_State *L, int idx) return frame; } +static int PushCast(lua_State *L, const char *meta) +{ + // bypass LUA_PushUserdata + void **userdata = lua_newuserdata(L, sizeof(void *)); + + *userdata = lua_touserdata(L, 1); + + luaL_getmetatable(L, meta); + lua_setmetatable(L, -2); + + // stack is left with the userdata on top, as if getting it had originally succeeded. + return 1; +} + // spriteinfo[] static int lib_getSpriteInfo(lua_State *L) { @@ -454,23 +468,15 @@ static int lib_spriteinfolen(lua_State *L) // spriteinfo_t static int spriteinfo_get(lua_State *L) { - spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEINFO)); const char *field = luaL_checkstring(L, 2); - I_Assert(sprinfo != NULL); + luaL_checkudata(L, 1, META_SPRITEINFO); // push spriteframepivot_t userdata if (fastcmp(field, "pivot")) - { - // bypass LUA_PushUserdata - void **userdata = lua_newuserdata(L, sizeof(void *)); - *userdata = sprinfo; - luaL_getmetatable(L, META_PIVOTLIST); - lua_setmetatable(L, -2); - - // stack is left with the userdata on top, as if getting it had originally succeeded. - return 1; - } + return PushCast(L, META_PIVOTLIST); + else if (fastcmp(field, "brightmap")) + return PushCast(L, META_SPRITEBRIGHTLIST); else return luaL_error(L, LUA_QL("spriteinfo_t") " has no field named " LUA_QS, field); @@ -640,6 +646,29 @@ static int framepivot_num(lua_State *L) return 1; } +static int brightlist_get(lua_State *L) +{ + const spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEBRIGHTLIST)); + const UINT8 frame = GetPivotFrame(L, 2); + + lua_pushstring(L, sprinfo->bright[frame]); + + return 1; +} + +static int brightlist_set(lua_State *L) +{ + spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEBRIGHTLIST)); + + const UINT8 frame = GetPivotFrame(L, 2); + const char *val = luaL_checkstring(L, 3); + + Z_Free(sprinfo->bright[frame]); + sprinfo->bright[frame] = Z_StrDup(val); + + return 0; +} + //////////////// // STATE INFO // //////////////// @@ -2033,6 +2062,17 @@ int LUA_InfoLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + luaL_newmetatable(L, META_SPRITEBRIGHTLIST); + lua_pushcfunction(L, brightlist_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, brightlist_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, pivotlist_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + luaL_newmetatable(L, META_PRECIPPROPS); lua_pushcfunction(L, precipprops_get); lua_setfield(L, -2, "__index"); diff --git a/src/lua_libs.h b/src/lua_libs.h index bc8e4141e..99e366167 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -28,6 +28,7 @@ extern lua_State *gL; #define META_SPRITEINFO "SPRITEINFO_T*" #define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]" #define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*" +#define META_SPRITEBRIGHTLIST "SPRITEBRIGHTMAP_T[]" #define META_PRECIPPROPS "PRECIPPROPS_T*" #define META_TAGLIST "TAGLIST" From 97497fa1a1b058bad530e45fec459dfd2d92c63a Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 16 Dec 2022 18:56:52 -0800 Subject: [PATCH 4/4] Guard against out of bounds sprite brightmap --- src/r_things.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/r_things.c b/src/r_things.c index 6f1dd436a..90b5cc1db 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -889,6 +889,13 @@ static void R_DrawVisSprite(vissprite_t *vis) if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto } + // Prevent an out of bounds error + if (bmpatch && (bmpatch->width != patch->width || + bmpatch->height != patch->height)) + { + return; + } + R_SetColumnFunc(BASEDRAWFUNC, false); // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; dc_fullbright = colormaps;