From 2aec4501eb4c742ba7830c2cce16bd64db7ac55d Mon Sep 17 00:00:00 2001 From: James R <justsomejames2@gmail.com> Date: Thu, 16 Dec 2021 22:10:36 -0800 Subject: [PATCH] Hash name lookup for textures and lumps --- src/doomdef.h | 16 ++++++++++++++++ src/r_textures.c | 12 ++++++++++-- src/r_textures.h | 1 + src/w_wad.c | 19 ++++++++++++++++--- src/w_wad.h | 1 + 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 7e7e35599..e1a7a247a 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -530,6 +530,22 @@ extern boolean capslock; // i_system.c, replace getchar() once the keyboard has been appropriated INT32 I_GetKey(void); +/* http://www.cse.yorku.ca/~oz/hash.html */ +static inline +UINT32 quickncasehash (const char *p, size_t n) +{ + size_t i = 0; + UINT32 x = 5381; + + while (i < n && p[i]) + { + x = (x * 33) ^ tolower(p[i]); + i++; + } + + return x; +} + #ifndef min // Double-Check with WATTCP-32's cdefs.h #define min(x, y) (((x) < (y)) ? (x) : (y)) #endif diff --git a/src/r_textures.c b/src/r_textures.c index a53c2e738..645a57b9b 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -59,6 +59,7 @@ INT32 *texturetranslation; // Painfully simple texture id cacheing to make maps load faster. :3 static struct { char name[9]; + UINT32 hash; INT32 id; } *tidcache = NULL; static INT32 tidcachelen = 0; @@ -788,6 +789,7 @@ Rloadflats (INT32 i, INT32 w) // Set texture properties. M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + texture->hash = quickncasehash(texture->name, 8); #ifndef NO_PNG_LUMPS if (Picture_IsLumpPNG(header, lumplength)) @@ -886,6 +888,7 @@ Rloadtextures (INT32 i, INT32 w) // Set texture properties. M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + texture->hash = quickncasehash(texture->name, 8); #ifndef NO_PNG_LUMPS if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength)) @@ -1401,6 +1404,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) // Allocate memory for a zero-patch texture. Obviously, we'll be adding patches momentarily. resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t),PU_STATIC,NULL); M_Memcpy(resultTexture->name, newTextureName, 8); + resultTexture->hash = quickncasehash(newTextureName, 8); resultTexture->width = newTextureWidth; resultTexture->height = newTextureHeight; resultTexture->type = TEXTURETYPE_COMPOSITE; @@ -1627,19 +1631,22 @@ void R_ClearTextureNumCache(boolean btell) INT32 R_CheckTextureNumForName(const char *name) { INT32 i; + UINT32 hash; // "NoTexture" marker. if (name[0] == '-') return 0; + hash = quickncasehash(name, 8); + for (i = 0; i < tidcachelen; i++) - if (!strncasecmp(tidcache[i].name, name, 8)) + if (tidcache[i].hash == hash && !strncasecmp(tidcache[i].name, name, 8)) return tidcache[i].id; // Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier //for (i = 0; i < numtextures; i++) <- old for (i = (numtextures - 1); i >= 0; i--) // <- new - if (!strncasecmp(textures[i]->name, name, 8)) + if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8)) { tidcachelen++; Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache); @@ -1648,6 +1655,7 @@ INT32 R_CheckTextureNumForName(const char *name) #ifndef ZDEBUG CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name); #endif + tidcache[tidcachelen-1].hash = hash; tidcache[tidcachelen-1].id = i; return i; } diff --git a/src/r_textures.h b/src/r_textures.h index 95796d89c..69b59426a 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -54,6 +54,7 @@ typedef struct { // Keep name for switch changing, etc. char name[8]; + UINT32 hash; UINT8 type; // TEXTURETYPE_ INT16 width, height; boolean holes; diff --git a/src/w_wad.c b/src/w_wad.c index e49e0ce82..9c631da65 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -361,6 +361,7 @@ static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const lumpinfo->size = ftell(handle); fseek(handle, 0, SEEK_SET); strcpy(lumpinfo->name, lumpname); + lumpinfo->hash = quickncasehash(lumpname, 8); // Allocate the lump's long name. lumpinfo->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); @@ -459,6 +460,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen lump_p->compression = CM_NOCOMPRESSION; memset(lump_p->name, 0x00, 9); strncpy(lump_p->name, fileinfo->name, 8); + lump_p->hash = quickncasehash(lump_p->name, 8); // Allocate the lump's long name. lump_p->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); @@ -634,6 +636,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary? strncpy(lump_p->name, trimname, min(8, dotpos - trimname)); + lump_p->hash = quickncasehash(lump_p->name, 8); lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL); strlcpy(lump_p->longname, trimname, dotpos - trimname + 1); @@ -1225,12 +1228,14 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump) { UINT16 i; static char uname[8 + 1]; + UINT32 hash; if (!TestValidLump(wad,0)) return INT16_MAX; strlcpy(uname, name, sizeof uname); strupr(uname); + hash = quickncasehash(uname, 8); // // scan forward @@ -1241,7 +1246,7 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump) { lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) - if (!strncmp(lump_p->name, uname, sizeof(uname) - 1)) + if (lump_p->hash == hash && !strncmp(lump_p->name, uname, sizeof(uname) - 1)) return i; } @@ -1444,15 +1449,20 @@ lumpnum_t W_CheckNumForLongName(const char *name) // TODO: Make it search through cache first, maybe...? lumpnum_t W_CheckNumForMap(const char *name) { + UINT32 hash = quickncasehash(name, 8); UINT16 lumpNum, end; UINT32 i; + lumpinfo_t *p; for (i = numwadfiles - 1; i < numwadfiles; i--) { if (wadfiles[i]->type == RET_WAD) { for (lumpNum = 0; lumpNum < wadfiles[i]->numlumps; lumpNum++) - if (!strncmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8)) + { + p = wadfiles[i]->lumpinfo + lumpNum; + if (p->hash == hash && !strncmp(name, p->name, 8)) return (i<<16) + lumpNum; + } } else if (W_FileHasFolders(wadfiles[i])) { @@ -1463,8 +1473,11 @@ lumpnum_t W_CheckNumForMap(const char *name) continue; // Now look for the specified map. for (; lumpNum < end; lumpNum++) - if (!strnicmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8)) + { + p = wadfiles[i]->lumpinfo + lumpNum; + if (p->hash == hash && !strnicmp(name, p->name, 8)) return (i<<16) + lumpNum; + } } } return LUMPERROR; diff --git a/src/w_wad.h b/src/w_wad.h index a41ba1724..9b8a66aa7 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -67,6 +67,7 @@ typedef struct unsigned long position; // filelump_t filepos unsigned long disksize; // filelump_t size char name[9]; // filelump_t name[] e.g. "LongEntr" + UINT32 hash; char *longname; // e.g. "LongEntryName" char *fullname; // e.g. "Folder/Subfolder/LongEntryName.extension" char *diskpath; // path to the file e.g. "/usr/games/srb2/Addon/Folder/Subfolder/LongEntryName.extension"