From 499c61a9f2d0f73c8b34a4dd8878c30bb151ede3 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 21 Sep 2022 01:19:13 -0700 Subject: [PATCH 1/6] Kill SPRITE/SPRITEINFO, SPRITE2INFO SOC headers Kill it because maintaining three parsers for the same data is insane. --- src/deh_soc.c | 236 ------------------------------------------------- src/deh_soc.h | 1 - src/dehacked.c | 24 ----- 3 files changed, 261 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index dd0fbf5eb..c1197c3cb 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -640,242 +640,6 @@ void readlight(MYFILE *f, INT32 num) } #endif // HWRENDER -static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame) -{ - char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); - char *word, *word2; - char *tmp; - INT32 value; - char *lastline; - - do - { - lastline = f->curpos; - if (myfgets(s, MAXLINELEN, f)) - { - if (s[0] == '\n') - break; - - // First remove trailing newline, if there is one - tmp = strchr(s, '\n'); - if (tmp) - *tmp = '\0'; - - tmp = strchr(s, '#'); - if (tmp) - *tmp = '\0'; - if (s == tmp) - continue; // Skip comment lines, but don't break. - - // Set / reset word - word = s; - while ((*word == '\t') || (*word == ' ')) - word++; - - // Get the part before the " = " - tmp = strchr(s, '='); - if (tmp) - { - *(tmp-1) = '\0'; - // Now get the part after - word2 = tmp += 2; - } - else - { - // Get the part before the " " - tmp = strchr(s, ' '); - if (tmp) - { - *tmp = '\0'; - // Now get the part after - tmp++; - word2 = tmp; - } - else - break; - } - strupr(word); - value = atoi(word2); // used for numerical settings - - if (fastcmp(word, "XPIVOT")) - sprinfo->pivot[frame].x = value; - else if (fastcmp(word, "YPIVOT")) - sprinfo->pivot[frame].y = value; - else if (fastcmp(word, "ROTAXIS")) - sprinfo->pivot[frame].rotaxis = value; - else - { - f->curpos = lastline; - break; - } - } - } while (!myfeof(f)); // finish when the line is empty - Z_Free(s); -} - -void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) -{ - char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); - char *word, *word2; - char *tmp; -#ifdef HWRENDER - INT32 value; -#endif - char *lastline; - INT32 skinnumbers[MAXSKINS]; - INT32 foundskins = 0; - - // allocate a spriteinfo - spriteinfo_t *info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); - info->available = true; - - do - { - lastline = f->curpos; - if (myfgets(s, MAXLINELEN, f)) - { - if (s[0] == '\n') - break; - - // First remove trailing newline, if there is one - tmp = strchr(s, '\n'); - if (tmp) - *tmp = '\0'; - - tmp = strchr(s, '#'); - if (tmp) - *tmp = '\0'; - if (s == tmp) - continue; // Skip comment lines, but don't break. - - // Set / reset word - word = s; - while ((*word == '\t') || (*word == ' ')) - word++; - - // Get the part before the " = " - tmp = strchr(s, '='); - if (tmp) - { - *(tmp-1) = '\0'; - // Now get the part after - word2 = tmp += 2; - } - else - { - // Get the part before the " " - tmp = strchr(s, ' '); - if (tmp) - { - *tmp = '\0'; - // Now get the part after - tmp++; - word2 = tmp; - } - else - break; - } - strupr(word); -#ifdef HWRENDER - value = atoi(word2); // used for numerical settings - - if (fastcmp(word, "LIGHTTYPE")) - { - if (sprite2) - deh_warning("Sprite2 %s: invalid word '%s'", spr2names[num], word); - else - { - INT32 oldvar; - for (oldvar = 0; t_lspr[num] != &lspr[oldvar]; oldvar++) - ; - t_lspr[num] = &lspr[value]; - } - } - else -#endif - if (fastcmp(word, "SKIN")) - { - INT32 skinnum = -1; - if (!sprite2) - { - deh_warning("Sprite %s: %s keyword found outside of SPRITE2INFO block, ignoring", spr2names[num], word); - continue; - } - - // make lowercase - strlwr(word2); - skinnum = R_SkinAvailable(word2); - if (skinnum == -1) - { - deh_warning("Sprite2 %s: unknown skin %s", spr2names[num], word2); - break; - } - - skinnumbers[foundskins] = skinnum; - foundskins++; - } - else if (fastcmp(word, "DEFAULT")) - { - if (!sprite2) - { - deh_warning("Sprite %s: %s keyword found outside of SPRITE2INFO block, ignoring", spr2names[num], word); - continue; - } - if (num < (INT32)free_spr2 && num >= (INT32)SPR2_FIRSTFREESLOT) - spr2defaults[num] = get_number(word2); - else - { - deh_warning("Sprite2 %s: out of range (%d - %d), ignoring", spr2names[num], SPR2_FIRSTFREESLOT, free_spr2-1); - continue; - } - } - else if (fastcmp(word, "FRAME")) - { - UINT8 frame = R_Char2Frame(word2[0]); - // frame number too high - if (frame >= 64) - { - if (sprite2) - deh_warning("Sprite2 %s: invalid frame %s", spr2names[num], word2); - else - deh_warning("Sprite %s: invalid frame %s", sprnames[num], word2); - break; - } - - // read sprite frame and store it in the spriteinfo_t struct - readspriteframe(f, info, frame); - if (sprite2) - { - INT32 i; - if (!foundskins) - { - deh_warning("Sprite2 %s: no skins specified", spr2names[num]); - break; - } - for (i = 0; i < foundskins; i++) - { - size_t skinnum = skinnumbers[i]; - skin_t *skin = &skins[skinnum]; - spriteinfo_t *sprinfo = skin->sprinfo; - M_Memcpy(&sprinfo[num], info, sizeof(spriteinfo_t)); - } - } - else - M_Memcpy(&spriteinfo[num], info, sizeof(spriteinfo_t)); - } - else - { - //deh_warning("Sprite %s: unknown word '%s'", sprnames[num], word); - f->curpos = lastline; - break; - } - } - } while (!myfeof(f)); // finish when the line is empty - - Z_Free(s); - Z_Free(info); -} - void readsprite2(MYFILE *f, INT32 num) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); diff --git a/src/deh_soc.h b/src/deh_soc.h index d19b67a1a..335260953 100644 --- a/src/deh_soc.h +++ b/src/deh_soc.h @@ -71,7 +71,6 @@ void readcutscene(MYFILE *f, INT32 num); void readlevelheader(MYFILE *f, INT32 num); void readgametype(MYFILE *f, char *gtname); void readsprite2(MYFILE *f, INT32 num); -void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2); #ifdef HWRENDER void readlight(MYFILE *f, INT32 num); #endif diff --git a/src/dehacked.c b/src/dehacked.c index d9a2084f1..4187a522b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -356,30 +356,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) } } #endif - else if (fastcmp(word, "SPRITE") || fastcmp(word, "SPRITEINFO")) - { - if (i == 0 && word2[0] != '0') // If word2 isn't a number - i = get_sprite(word2); // find a sprite by name - if (i < NUMSPRITES && i > 0) - readspriteinfo(f, i, false); - else - { - deh_warning("Sprite number %d out of range (0 - %d)", i, NUMSPRITES-1); - ignorelines(f); - } - } - else if (fastcmp(word, "SPRITE2INFO")) - { - if (i == 0 && word2[0] != '0') // If word2 isn't a number - i = get_sprite2(word2); // find a sprite by name - if (i < NUMPLAYERSPRITES && i >= 0) - readspriteinfo(f, i, true); - else - { - deh_warning("Sprite2 number %d out of range (0 - %d)", i, NUMPLAYERSPRITES-1); - ignorelines(f); - } - } else if (fastcmp(word, "LEVEL")) { // Support using the actual map name, From 58bc3294fabaa71ab777745acd707f5c8ca67777 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 21 Sep 2022 12:27:16 -0700 Subject: [PATCH 2/6] Refactor R_ParseSpriteInfo Splits up the function, thus makes me want to kill myself less. --- src/r_picformats.c | 145 +++++++++++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 58 deletions(-) diff --git a/src/r_picformats.c b/src/r_picformats.c index de9bb4857..deb2bcfde 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1396,12 +1396,56 @@ boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *to #endif #endif -// -// R_ParseSpriteInfoFrame -// -// Parse a SPRTINFO frame. -// -static void R_ParseSpriteInfoFrame(spriteinfo_t *info) +struct ParseSpriteInfoState { + boolean spr2; + spriteinfo_t *info; + spritenum_t sprnum; + playersprite_t spr2num; + INT32 skinnumbers[MAXSKINS]; + INT32 foundskins; +}; + +static void R_ParseSpriteInfoSkin(struct ParseSpriteInfoState *parser) +{ + char *sprinfoToken; + size_t sprinfoTokenLength; + + INT32 skinnum; + char *skinName = NULL; + + // Skin name + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where skin frame should be"); + } + + // copy skin name yada yada + sprinfoTokenLength = strlen(sprinfoToken); + skinName = (char *)Z_Malloc((sprinfoTokenLength+1)*sizeof(char),PU_STATIC,NULL); + M_Memcpy(skinName,sprinfoToken,sprinfoTokenLength*sizeof(char)); + skinName[sprinfoTokenLength] = '\0'; + strlwr(skinName); + + skinnum = R_SkinAvailable(skinName); + if (skinnum == -1) + I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); + + parser->skinnumbers[parser->foundskins] = skinnum; + parser->foundskins++; + + Z_Free(sprinfoToken); +} + +static void copy_to_skin (struct ParseSpriteInfoState *parser, INT32 skinnum) +{ + skin_t *skin = &skins[skinnum]; + spriteinfo_t *sprinfo = skin->sprinfo; + + M_Memcpy(&sprinfo[parser->spr2num], parser->info, sizeof(spriteinfo_t)); +} + +static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser) { char *sprinfoToken; size_t sprinfoTokenLength; @@ -1480,9 +1524,26 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) } // set fields - info->pivot[frameFrame].x = frameXPivot; - info->pivot[frameFrame].y = frameYPivot; - info->pivot[frameFrame].rotaxis = frameRotAxis; + parser->info->pivot[frameFrame].x = frameXPivot; + parser->info->pivot[frameFrame].y = frameYPivot; + parser->info->pivot[frameFrame].rotaxis = frameRotAxis; + + if (parser->spr2) + { + INT32 i; + + if (!parser->foundskins) + I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition"); + + for (i = 0; i < parser->foundskins; i++) + { + copy_to_skin(parser, parser->skinnumbers[i]); + } + } + else + { + M_Memcpy(&spriteinfo[parser->sprnum], parser->info, sizeof(spriteinfo_t)); + } } // @@ -1492,15 +1553,18 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) // static void R_ParseSpriteInfo(boolean spr2) { - spriteinfo_t *info; char *sprinfoToken; size_t sprinfoTokenLength; char newSpriteName[5]; // no longer dynamically allocated - spritenum_t sprnum = NUMSPRITES; - playersprite_t spr2num = NUMPLAYERSPRITES; + + struct ParseSpriteInfoState parser = { + .spr2 = spr2, + .sprnum = NUMSPRITES, + .spr2num = NUMPLAYERSPRITES, + .foundskins = 0, + }; + INT32 i; - INT32 skinnumbers[MAXSKINS]; - INT32 foundskins = 0; // Sprite name sprinfoToken = M_GetToken(NULL); @@ -1508,6 +1572,7 @@ static void R_ParseSpriteInfo(boolean spr2) { I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite name should be"); } + sprinfoTokenLength = strlen(sprinfoToken); if (sprinfoTokenLength != 4) { @@ -1520,6 +1585,7 @@ static void R_ParseSpriteInfo(boolean spr2) // ^^ we've confirmed that the token is == 4 characters so it will never overflow a 5 byte char buffer strupr(newSpriteName); // Just do this now so we don't have to worry about it } + Z_Free(sprinfoToken); if (!spr2) @@ -1530,7 +1596,7 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); if (!memcmp(newSpriteName,sprnames[i],4)) { - sprnum = i; + parser.sprnum = i; break; } } @@ -1543,15 +1609,15 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: Unknown sprite2 name \"%s\"", newSpriteName); if (!memcmp(newSpriteName,spr2names[i],4)) { - spr2num = i; + parser.spr2num = i; break; } } } // allocate a spriteinfo - info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); - info->available = true; + parser.info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); + parser.info->available = true; // Left Curly Brace sprinfoToken = M_GetToken(NULL); @@ -1571,53 +1637,16 @@ static void R_ParseSpriteInfo(boolean spr2) { if (stricmp(sprinfoToken, "SKIN")==0) { - INT32 skinnum; - char *skinName = NULL; if (!spr2) I_Error("Error parsing SPRTINFO lump: \"SKIN\" token found outside of a sprite2 definition"); Z_Free(sprinfoToken); - - // Skin name - sprinfoToken = M_GetToken(NULL); - if (sprinfoToken == NULL) - { - I_Error("Error parsing SPRTINFO lump: Unexpected end of file where skin frame should be"); - } - - // copy skin name yada yada - sprinfoTokenLength = strlen(sprinfoToken); - skinName = (char *)Z_Malloc((sprinfoTokenLength+1)*sizeof(char),PU_STATIC,NULL); - M_Memcpy(skinName,sprinfoToken,sprinfoTokenLength*sizeof(char)); - skinName[sprinfoTokenLength] = '\0'; - strlwr(skinName); - Z_Free(sprinfoToken); - - skinnum = R_SkinAvailable(skinName); - if (skinnum == -1) - I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); - - skinnumbers[foundskins] = skinnum; - foundskins++; + R_ParseSpriteInfoSkin(&parser); } else if (stricmp(sprinfoToken, "FRAME")==0) { - R_ParseSpriteInfoFrame(info); Z_Free(sprinfoToken); - if (spr2) - { - if (!foundskins) - I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition"); - for (i = 0; i < foundskins; i++) - { - size_t skinnum = skinnumbers[i]; - skin_t *skin = &skins[skinnum]; - spriteinfo_t *sprinfo = skin->sprinfo; - M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t)); - } - } - else - M_Memcpy(&spriteinfo[sprnum], info, sizeof(spriteinfo_t)); + R_ParseSpriteInfoFrame(&parser); } else { @@ -1636,7 +1665,7 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: Expected \"{\" for sprite \"%s\", got \"%s\"",newSpriteName,sprinfoToken); } Z_Free(sprinfoToken); - Z_Free(info); + Z_Free(parser.info); } // From b0f84e99fcfcfec243d128ae3e08b8740495b931 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 21 Sep 2022 13:20:30 -0700 Subject: [PATCH 3/6] Refactor Lua spriteinfo Fixes available not being set when pivot list is updated on its own. --- src/lua_infolib.c | 48 +++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 1aaa207de..45dcf9977 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -242,6 +242,11 @@ static int lib_spr2namelen(lua_State *L) // SPRITE INFO // ///////////////// +struct PivotFrame { + spriteinfo_t *sprinfo; + UINT8 frame; +}; + // spriteinfo[] static int lib_getSpriteInfo(lua_State *L) { @@ -441,7 +446,7 @@ static int spriteinfo_get(lua_State *L) { // bypass LUA_PushUserdata void **userdata = lua_newuserdata(L, sizeof(void *)); - *userdata = &sprinfo->pivot; + *userdata = sprinfo; luaL_getmetatable(L, META_PIVOTLIST); lua_setmetatable(L, -2); @@ -480,9 +485,8 @@ static int spriteinfo_set(lua_State *L) // pivot[] is userdata else if (lua_isuserdata(L, 1)) { - spriteframepivot_t *pivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); - memcpy(&sprinfo->pivot, pivot, sizeof(spriteframepivot_t)); - sprinfo->available = true; // Just in case? + spriteinfo_t *copyinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); + memcpy(sprinfo, copyinfo, sizeof(spriteinfo_t)); } } else @@ -505,8 +509,8 @@ static int spriteinfo_num(lua_State *L) // framepivot_t static int pivotlist_get(lua_State *L) { - void **userdata; - spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); + struct PivotFrame *container; + spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); const char *field = luaL_checkstring(L, 2); UINT8 frame; @@ -517,8 +521,9 @@ static int pivotlist_get(lua_State *L) luaL_error(L, "invalid frame %s", field); // bypass LUA_PushUserdata - userdata = lua_newuserdata(L, sizeof(void *)); - *userdata = &framepivot[frame]; + container = lua_newuserdata(L, sizeof *container); + container->sprinfo = sprinfo; + container->frame = frame; luaL_getmetatable(L, META_FRAMEPIVOT); lua_setmetatable(L, -2); @@ -528,11 +533,10 @@ static int pivotlist_get(lua_State *L) static int pivotlist_set(lua_State *L) { - // Because I already know it's a spriteframepivot_t anyway - spriteframepivot_t *pivotlist = *((spriteframepivot_t **)lua_touserdata(L, 1)); - //spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT)); + spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); const char *field = luaL_checkstring(L, 2); UINT8 frame; + int okcool = 0; if (!lua_lumploading) return luaL_error(L, "Do not alter spriteframepivot_t from within a hook or coroutine!"); @@ -549,14 +553,18 @@ static int pivotlist_set(lua_State *L) // pivot[] is a table if (lua_istable(L, 3)) - return PopPivotSubTable(pivotlist, L, 3, frame); + okcool = PopPivotSubTable(sprinfo->pivot, L, 3, frame); // pivot[] is userdata else if (lua_isuserdata(L, 3)) { - spriteframepivot_t *copypivot = *((spriteframepivot_t **)luaL_checkudata(L, 3, META_FRAMEPIVOT)); - memcpy(&pivotlist[frame], copypivot, sizeof(spriteframepivot_t)); + struct PivotFrame *container = luaL_checkudata(L, 3, META_FRAMEPIVOT); + memcpy(&sprinfo->pivot[frame], &container->sprinfo->pivot[container->frame], sizeof(spriteframepivot_t)); + okcool = 1; } + if (okcool) + sprinfo->available = true; + return 0; } @@ -568,7 +576,8 @@ static int pivotlist_num(lua_State *L) static int framepivot_get(lua_State *L) { - spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT)); + struct PivotFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT); + spriteframepivot_t *framepivot = &container->sprinfo->pivot[container->frame]; const char *field = luaL_checkstring(L, 2); I_Assert(framepivot != NULL); @@ -585,7 +594,8 @@ static int framepivot_get(lua_State *L) static int framepivot_set(lua_State *L) { - spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT)); + struct PivotFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT); + spriteframepivot_t *framepivot = &container->sprinfo->pivot[container->frame]; const char *field = luaL_checkstring(L, 2); if (!lua_lumploading) @@ -598,9 +608,15 @@ static int framepivot_set(lua_State *L) I_Assert(framepivot != NULL); if (fastcmp("x", field)) + { framepivot->x = luaL_checkinteger(L, 3); + container->sprinfo->available = true; + } else if (fastcmp("y", field)) + { framepivot->y = luaL_checkinteger(L, 3); + container->sprinfo->available = true; + } else return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field)); From 5a631b302dcbc7ae405711cc4fc039d4d8db8b1a Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 21 Sep 2022 12:31:32 -0700 Subject: [PATCH 4/6] Add SPRINFO_DEFAULT_PIVOT, change spriteinfo_t.available to bit array Default is used if the bit is not set for a particular frame. --- src/r_patchrotation.c | 7 ++++++- src/r_picformats.h | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index ab6c0de97..e2506baa5 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -141,11 +141,16 @@ patch_t *Patch_GetRotatedSprite( patch = W_CachePatchNum(lump, PU_SPRITE); - if (sprinfo->available) + if (in_bit_array(sprinfo->available, frame)) { xpivot = sprinfo->pivot[frame].x; ypivot = sprinfo->pivot[frame].y; } + else if (in_bit_array(sprinfo->available, SPRINFO_DEFAULT_PIVOT)) + { + xpivot = sprinfo->pivot[SPRINFO_DEFAULT_PIVOT].x; + ypivot = sprinfo->pivot[SPRINFO_DEFAULT_PIVOT].y; + } else { xpivot = patch->leftoffset; diff --git a/src/r_picformats.h b/src/r_picformats.h index 0a822cc48..700424814 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -100,8 +100,9 @@ typedef struct typedef struct { - spriteframepivot_t pivot[64]; - boolean available; + spriteframepivot_t pivot[64 + 1]; +#define SPRINFO_DEFAULT_PIVOT (64) + UINT8 available[BIT_ARRAY_SIZE(64 + 1)]; // 1 extra for default_pivot } spriteinfo_t; // Portable Network Graphics From 0912ebaaa3c5a05e7c554eebd3e3ebe016c28c7f Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 21 Sep 2022 12:32:06 -0700 Subject: [PATCH 5/6] Update and extend R_ParseSpriteInfo for default pivot - Set default pivot with DEFAULT block - Use wildcard star (*) with Sprite/Sprite2Info/Skin to iterate over all sprites and/or skins --- src/r_picformats.c | 144 +++++++++++++++++++++++++++++++++------------ 1 file changed, 106 insertions(+), 38 deletions(-) diff --git a/src/r_picformats.c b/src/r_picformats.c index deb2bcfde..1f39ae42c 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1401,10 +1401,14 @@ struct ParseSpriteInfoState { spriteinfo_t *info; spritenum_t sprnum; playersprite_t spr2num; + boolean any; INT32 skinnumbers[MAXSKINS]; INT32 foundskins; }; +#define PARSER_FRAME (false) +#define PARSER_DEFAULT (true) + static void R_ParseSpriteInfoSkin(struct ParseSpriteInfoState *parser) { char *sprinfoToken; @@ -1420,19 +1424,26 @@ static void R_ParseSpriteInfoSkin(struct ParseSpriteInfoState *parser) I_Error("Error parsing SPRTINFO lump: Unexpected end of file where skin frame should be"); } - // copy skin name yada yada - sprinfoTokenLength = strlen(sprinfoToken); - skinName = (char *)Z_Malloc((sprinfoTokenLength+1)*sizeof(char),PU_STATIC,NULL); - M_Memcpy(skinName,sprinfoToken,sprinfoTokenLength*sizeof(char)); - skinName[sprinfoTokenLength] = '\0'; - strlwr(skinName); + if (strcmp(sprinfoToken, "*")==0) // All skins + { + parser->foundskins = -1; + } + else + { + // copy skin name yada yada + sprinfoTokenLength = strlen(sprinfoToken); + skinName = (char *)Z_Malloc((sprinfoTokenLength+1)*sizeof(char),PU_STATIC,NULL); + M_Memcpy(skinName,sprinfoToken,sprinfoTokenLength*sizeof(char)); + skinName[sprinfoTokenLength] = '\0'; + strlwr(skinName); - skinnum = R_SkinAvailable(skinName); - if (skinnum == -1) - I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); + skinnum = R_SkinAvailable(skinName); + if (skinnum == -1) + I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); - parser->skinnumbers[parser->foundskins] = skinnum; - parser->foundskins++; + parser->skinnumbers[parser->foundskins] = skinnum; + parser->foundskins++; + } Z_Free(sprinfoToken); } @@ -1442,10 +1453,22 @@ static void copy_to_skin (struct ParseSpriteInfoState *parser, INT32 skinnum) skin_t *skin = &skins[skinnum]; spriteinfo_t *sprinfo = skin->sprinfo; - M_Memcpy(&sprinfo[parser->spr2num], parser->info, sizeof(spriteinfo_t)); + if (parser->any) + { + playersprite_t spr2num; + + for (spr2num = 0; spr2num < NUMPLAYERSPRITES; ++spr2num) + { + M_Memcpy(&sprinfo[spr2num], parser->info, sizeof(spriteinfo_t)); + } + } + else + { + M_Memcpy(&sprinfo[parser->spr2num], parser->info, sizeof(spriteinfo_t)); + } } -static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser) +static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean all) { char *sprinfoToken; size_t sprinfoTokenLength; @@ -1455,22 +1478,29 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser) INT16 frameYPivot = 0; rotaxis_t frameRotAxis = 0; - // Sprite identifier - sprinfoToken = M_GetToken(NULL); - if (sprinfoToken == NULL) + if (all) { - I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite frame should be"); - } - sprinfoTokenLength = strlen(sprinfoToken); - if (sprinfoTokenLength != 1) - { - I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",sprinfoToken); + frameFrame = SPRINFO_DEFAULT_PIVOT; } else - frameChar = sprinfoToken; + { + // Sprite identifier + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite frame should be"); + } + sprinfoTokenLength = strlen(sprinfoToken); + if (sprinfoTokenLength != 1) + { + I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",sprinfoToken); + } + else + frameChar = sprinfoToken; - frameFrame = R_Char2Frame(frameChar[0]); - Z_Free(sprinfoToken); + frameFrame = R_Char2Frame(frameChar[0]); + Z_Free(sprinfoToken); + } // Left Curly Brace sprinfoToken = M_GetToken(NULL); @@ -1528,6 +1558,8 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser) parser->info->pivot[frameFrame].y = frameYPivot; parser->info->pivot[frameFrame].rotaxis = frameRotAxis; + set_bit_array(parser->info->available, frameFrame); + if (parser->spr2) { INT32 i; @@ -1535,14 +1567,36 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser) if (!parser->foundskins) I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition"); - for (i = 0; i < parser->foundskins; i++) + if (parser->foundskins < 0) { - copy_to_skin(parser, parser->skinnumbers[i]); + for (i = 0; i < numskins; i++) + { + copy_to_skin(parser, i); + } + } + else + { + for (i = 0; i < parser->foundskins; i++) + { + copy_to_skin(parser, parser->skinnumbers[i]); + } } } else { - M_Memcpy(&spriteinfo[parser->sprnum], parser->info, sizeof(spriteinfo_t)); + if (parser->any) + { + spritenum_t sprnum; + + for (sprnum = 0; sprnum < NUMSPRITES; ++sprnum) + { + M_Memcpy(&spriteinfo[sprnum], parser->info, sizeof(spriteinfo_t)); + } + } + else + { + M_Memcpy(&spriteinfo[parser->sprnum], parser->info, sizeof(spriteinfo_t)); + } } } @@ -1561,6 +1615,7 @@ static void R_ParseSpriteInfo(boolean spr2) .spr2 = spr2, .sprnum = NUMSPRITES, .spr2num = NUMPLAYERSPRITES, + .any = false, .foundskins = 0, }; @@ -1573,22 +1628,31 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite name should be"); } - sprinfoTokenLength = strlen(sprinfoToken); - if (sprinfoTokenLength != 4) + if (!strcmp(sprinfoToken, "*")) // All sprites { - I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" isn't 4 characters long",sprinfoToken); + parser.any = true; } else { - memset(&newSpriteName, 0, 5); - M_Memcpy(newSpriteName, sprinfoToken, sprinfoTokenLength); - // ^^ we've confirmed that the token is == 4 characters so it will never overflow a 5 byte char buffer - strupr(newSpriteName); // Just do this now so we don't have to worry about it + sprinfoTokenLength = strlen(sprinfoToken); + if (sprinfoTokenLength != 4) + { + I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" isn't 4 characters long",sprinfoToken); + } + else + { + memset(&newSpriteName, 0, 5); + M_Memcpy(newSpriteName, sprinfoToken, sprinfoTokenLength); + // ^^ we've confirmed that the token is == 4 characters so it will never overflow a 5 byte char buffer + strupr(newSpriteName); // Just do this now so we don't have to worry about it + } } Z_Free(sprinfoToken); - if (!spr2) + if (parser.any) + ; + else if (!spr2) { for (i = 0; i <= NUMSPRITES; i++) { @@ -1617,7 +1681,6 @@ static void R_ParseSpriteInfo(boolean spr2) // allocate a spriteinfo parser.info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); - parser.info->available = true; // Left Curly Brace sprinfoToken = M_GetToken(NULL); @@ -1646,7 +1709,12 @@ static void R_ParseSpriteInfo(boolean spr2) else if (stricmp(sprinfoToken, "FRAME")==0) { Z_Free(sprinfoToken); - R_ParseSpriteInfoFrame(&parser); + R_ParseSpriteInfoFrame(&parser, PARSER_FRAME); + } + else if (stricmp(sprinfoToken, "DEFAULT")==0) + { + Z_Free(sprinfoToken); + R_ParseSpriteInfoFrame(&parser, PARSER_DEFAULT); } else { From 43984aebd456e7a19ec4b907c8df51643d6557e7 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 21 Sep 2022 14:14:39 -0700 Subject: [PATCH 6/6] Lua spriteinfo default pivot support --- src/lua_infolib.c | 49 +++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 45dcf9977..0b8359065 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -247,6 +247,25 @@ struct PivotFrame { UINT8 frame; }; +static UINT8 GetPivotFrame(lua_State *L, int idx) +{ + const char *field = luaL_checkstring(L, idx); + UINT8 frame; + + if (fastcmp("default", field)) + { + frame = SPRINFO_DEFAULT_PIVOT; + } + else + { + frame = R_Char2Frame(field[0]); + if (frame == 255) + luaL_error(L, "invalid frame %s", field); + } + + return frame; +} + // spriteinfo[] static int lib_getSpriteInfo(lua_State *L) { @@ -354,24 +373,23 @@ static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk) while (lua_next(L, stk)) { int idx = 0; - const char *framestr = NULL; switch (lua_type(L, stk+1)) { case LUA_TSTRING: - framestr = lua_tostring(L, stk+1); - idx = R_Char2Frame(framestr[0]); + idx = GetPivotFrame(L, stk+1); break; case LUA_TNUMBER: idx = lua_tonumber(L, stk+1); + + if ((idx < 0) || (idx >= 64)) + return luaL_error(L, "pivot frame %d out of range (0 - %d)", idx, 63); break; default: TYPEERROR("pivot frame", LUA_TNUMBER, lua_type(L, stk+1)); } - if ((idx < 0) || (idx >= 64)) - return luaL_error(L, "pivot frame %d out of range (0 - %d)", idx, 63); // the values in pivot[] are also tables if (PopPivotSubTable(info->pivot, L, stk+2, idx)) - info->available = true; + set_bit_array(info->available, idx); lua_pop(L, 1); } @@ -511,15 +529,10 @@ static int pivotlist_get(lua_State *L) { struct PivotFrame *container; spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); - const char *field = luaL_checkstring(L, 2); - UINT8 frame; + UINT8 frame = GetPivotFrame(L, 2); I_Assert(framepivot != NULL); - frame = R_Char2Frame(field[0]); - if (frame == 255) - luaL_error(L, "invalid frame %s", field); - // bypass LUA_PushUserdata container = lua_newuserdata(L, sizeof *container); container->sprinfo = sprinfo; @@ -534,7 +547,6 @@ static int pivotlist_get(lua_State *L) static int pivotlist_set(lua_State *L) { spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); - const char *field = luaL_checkstring(L, 2); UINT8 frame; int okcool = 0; @@ -547,9 +559,7 @@ static int pivotlist_set(lua_State *L) I_Assert(pivotlist != NULL); - frame = R_Char2Frame(field[0]); - if (frame == 255) - luaL_error(L, "invalid frame %s", field); + frame = GetPivotFrame(L, 2); // pivot[] is a table if (lua_istable(L, 3)) @@ -563,7 +573,7 @@ static int pivotlist_set(lua_State *L) } if (okcool) - sprinfo->available = true; + set_bit_array(sprinfo->available, frame); return 0; } @@ -596,6 +606,7 @@ static int framepivot_set(lua_State *L) { struct PivotFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT); spriteframepivot_t *framepivot = &container->sprinfo->pivot[container->frame]; + UINT8 *available = container->sprinfo->available; const char *field = luaL_checkstring(L, 2); if (!lua_lumploading) @@ -610,12 +621,12 @@ static int framepivot_set(lua_State *L) if (fastcmp("x", field)) { framepivot->x = luaL_checkinteger(L, 3); - container->sprinfo->available = true; + set_bit_array(available, container->frame); } else if (fastcmp("y", field)) { framepivot->y = luaL_checkinteger(L, 3); - container->sprinfo->available = true; + set_bit_array(available, container->frame); } else return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field));