From 8d9b42e49b6fda035379599b5304fa6c0c50a869 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 27 May 2023 19:08:14 +0100 Subject: [PATCH] Skin name search-assistive hashing More opportunities for early rejection in table-wide searches, in anticipation of future work. - Many circumstances independently implemented string name comparisons. Most of these have been converted to use R_SkinAvailable, with one exception. - M_CharacterSelectInit already needs to iterate over the characters, so produce the skin hash independently. --- src/acs/call-funcs.cpp | 14 +++++--------- src/hardware/hw_md2.c | 18 ++++++++---------- src/lua_hudlib.c | 6 ++---- src/lua_mobjlib.c | 21 ++++++++++----------- src/lua_skinlib.c | 12 ++++++------ src/menus/play-char-select.c | 14 +++++++++++++- src/r_skins.c | 13 ++++++++++--- src/r_skins.h | 3 ++- 8 files changed, 56 insertions(+), 45 deletions(-) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index 4bfca2960..c5e07f025 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -264,16 +264,12 @@ static bool ACS_GetStateFromString(const char *word, statenum_t *type) --------------------------------------------------*/ static bool ACS_GetSkinFromString(const char *word, INT32 *type) { - for (int i = 0; i < numskins; i++) - { - if (fastcmp(word, skins[i].name)) - { - *type = i; - return true; - } - } + INT32 skin = R_SkinAvailable(word); + if (skin == -1) + return false; - return false; + *type = skin; + return true; } /*-------------------------------------------------- diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 26d342b1b..8772e152a 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -570,17 +570,15 @@ void HWR_InitModels(void) addskinmodel: // add player model - for (s = 0; s < MAXSKINS; s++) + s = R_SkinAvailable(skinname); + if (s != -1) { - if (stricmp(skinname, skins[s].name) == 0) - { - md2_playermodels[s].skin = s; - md2_playermodels[s].scale = scale; - md2_playermodels[s].offset = offset; - md2_playermodels[s].notfound = false; - strcpy(md2_playermodels[s].filename, filename); - goto modelfound; - } + md2_playermodels[s].skin = s; + md2_playermodels[s].scale = scale; + md2_playermodels[s].offset = offset; + md2_playermodels[s].notfound = false; + strcpy(md2_playermodels[s].filename, filename); + goto modelfound; } // no sprite/player skin name found?!?D diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index aab85e26c..f99f33f6b 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -386,10 +386,8 @@ static int libd_getSprite2Patch(lua_State *L) else // find skin by name { const char *name = luaL_checkstring(L, 1); - for (i = 0; i < numskins; i++) - if (fastcmp(skins[i].name, name)) - break; - if (i >= numskins) + i = R_SkinAvailable(name); + if (i == -1) return 0; } diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 835e2bb4d..1ae7a6a78 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -662,17 +662,16 @@ static int mobj_set(lua_State *L) break; case mobj_skin: // set skin by name { - INT32 i; - char skin[SKINNAMESIZE+1]; // all skin names are limited to this length - strlcpy(skin, luaL_checkstring(L, 3), sizeof skin); - strlwr(skin); // all skin names are lowercase - for (i = 0; i < numskins; i++) - if (fastcmp(skins[i].name, skin)) - { - if (!mo->player || R_SkinUsable(mo->player-players, i, false)) - mo->skin = &skins[i]; - return 0; - } + const char *name = luaL_checkstring(L, 3); + INT32 skin = R_SkinAvailable(name); + + if (skin != -1) + { + if (!mo->player || R_SkinUsable(mo->player-players, skin, false)) + mo->skin = &skins[skin]; + + return 0; + } return luaL_error(L, "mobj.skin '%s' not found!", skin); } case mobj_color: diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 6c4089de2..2950af461 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -196,12 +196,12 @@ static int lib_getSkin(lua_State *L) } // find skin by name - for (i = 0; i < numskins; i++) - if (fastcmp(skins[i].name, field)) - { - LUA_PushUserdata(L, &skins[i], META_SKIN); - return 1; - } + i = R_SkinAvailable(field); + if (i != -1) + { + LUA_PushUserdata(L, &skins[i], META_SKIN); + return 1; + } return 0; } diff --git a/src/menus/play-char-select.c b/src/menus/play-char-select.c index c21990ba4..0110870d9 100644 --- a/src/menus/play-char-select.c +++ b/src/menus/play-char-select.c @@ -404,6 +404,8 @@ void M_CharacterSelectInit(void) memset(setup_explosions, 0, sizeof(setup_explosions)); setup_animcounter = 0; + UINT32 localskinhash[MAXSPLITSCREENPLAYERS]; + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { // Default to no follower / match colour. @@ -414,6 +416,9 @@ void M_CharacterSelectInit(void) // Set default selected profile to the last used profile for each player: // (Make sure we don't overshoot it somehow if we deleted profiles or whatnot) setup_player[i].profilen = min(cv_lastprofile[i].value, PR_GetNumProfiles()); + + // Assistant for comparisons. + localskinhash[i] = quickncasehash(cv_skin[i].string, SKINNAMESIZE); } for (i = 0; i < numskins; i++) @@ -436,7 +441,14 @@ void M_CharacterSelectInit(void) for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) { - if (!strcmp(cv_skin[j].string, skins[i].name)) + // See also R_SkinAvailable + + if (localskinhash[j] != skins[i].namehash) + continue; + + if (!stricmp(cv_skin[j].string, skins[i].name)) + continue; + { setup_player[j].gridx = x; setup_player[j].gridy = y; diff --git a/src/r_skins.c b/src/r_skins.c index 1bdba8132..432052db1 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -314,12 +314,17 @@ UINT32 R_GetLocalRandomSkin(void) INT32 R_SkinAvailable(const char *name) { INT32 i; + UINT32 hash = quickncasehash(name, SKINNAMESIZE); for (i = 0; i < numskins; i++) { - // search in the skin list - if (stricmp(skins[i].name,name)==0) - return i; + if (skins[i].namehash != hash) + continue; + + if (stricmp(skins[i].name,name)!=0) + continue; + + return i; } return -1; } @@ -954,6 +959,8 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile) Z_Free(value2); } + skin->namehash = quickncasehash(skin->name, SKINNAMESIZE); + // copy to hudname and fullname as a default. if (!realname) { diff --git a/src/r_skins.h b/src/r_skins.h index 2770846f1..73d8b609e 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -37,7 +37,8 @@ extern "C" { /// The skin_t struct struct skin_t { - char name[SKINNAMESIZE+1]; // INT16 descriptive name of the skin + char name[SKINNAMESIZE+1]; // descriptive name of the skin + UINT32 namehash; // quickncasehash(->name, SKINNAMESIZE) UINT16 wadnum; skinflags_t flags;