Level and cup header information: Hashing for referencing by name

Foundational assistive work.
Also guarantees a consistent cup name length in memory, as some places read/wrote 15 bytes, and some places read/wrote 16 bytes. We settle on the latter (including null terminator) for the broadest backwards compatibility.

G: partial merge, missing lots of cup stuff
This commit is contained in:
toaster 2023-05-23 17:41:32 +01:00 committed by GenericHeroGuy
parent 2c3fc38f27
commit 4e559aed87
4 changed files with 51 additions and 28 deletions

View file

@ -1109,6 +1109,7 @@ void readlevelheader(MYFILE *f, char * name)
if (mapheaderinfo[num]->lumpname == NULL)
{
mapheaderinfo[num]->lumpname = Z_StrDup(name);
mapheaderinfo[num]->lumpnamehash = quickncasehash(mapheaderinfo[num]->lumpname, MAXMAPLUMPNAME);
}
do

View file

@ -513,39 +513,51 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
//
else if (fastcmp(word, "CUP"))
{
cupheader_t *cup = kartcupheaders;
cupheader_t *prev = NULL;
while (cup)
size_t len = strlen(word2);
if (len <= MAXCUPNAME-1)
{
if (fastcmp(cup->name, word2))
cupheader_t *cup = kartcupheaders;
cupheader_t *prev = NULL;
UINT32 hash = quickncasehash(word2, MAXCUPNAME);
while (cup)
{
// Only a major mod if editing stuff that isn't your own!
G_SetGameModified(multiplayer, true);
break;
if (hash == cup->namehash && fastcmp(cup->name, word2))
{
// Only a major mod if editing stuff that isn't your own!
G_SetGameModified(multiplayer, true);
break;
}
prev = cup;
cup = cup->next;
}
prev = cup;
cup = cup->next;
}
// Nothing found, add to the end.
if (!cup)
{
cup = Z_Calloc(sizeof (cupheader_t), PU_STATIC, NULL);
cup->id = numkartcupheaders;
cup->monitor = 1;
deh_strlcpy(cup->name, word2,
sizeof(cup->name), va("Cup header %s: name", word2));
cup->namehash = hash;
if (prev != NULL)
prev->next = cup;
if (kartcupheaders == NULL)
kartcupheaders = cup;
numkartcupheaders++;
CONS_Printf("Added cup %d ('%s')\n", cup->id, cup->name);
}
// Nothing found, add to the end.
if (!cup)
readcupheader(f, cup);
}
else
{
cup = Z_Calloc(sizeof (cupheader_t), PU_STATIC, NULL);
cup->id = numkartcupheaders;
cup->monitor = 1;
deh_strlcpy(cup->name, word2,
sizeof(cup->name), va("Cup header %s: name", word2));
if (prev != NULL)
prev->next = cup;
if (kartcupheaders == NULL)
kartcupheaders = cup;
numkartcupheaders++;
CONS_Printf("Added cup %d ('%s')\n", cup->id, cup->name);
deh_warning("Cup header's name %s is too long (%s characters VS %d max)", word2, sizeu1(len), (MAXCUPNAME-1));
ignorelines(f);
}
readcupheader(f, cup);
}
else if (fastcmp(word, "WEATHER") || fastcmp(word, "PRECIP") || fastcmp(word, "PRECIPITATION"))
{

View file

@ -354,11 +354,16 @@ struct mapheader_lighting_t
#define CUPCACHE_SPECIAL MAXLEVELLIST+1
#define CUPCACHE_MAX CUPCACHE_SPECIAL+1
#define MAXCUPNAME 16 // includes \0, for cleaner savedata
struct cupheader_t
{
UINT16 id; ///< Cup ID
UINT8 monitor; ///< Monitor graphic 1-9 or A-Z
char name[15]; ///< Cup title (14 chars)
char name[MAXCUPNAME]; ///< Cup title
UINT32 namehash; ///< Cup title hash
char icon[9]; ///< Name of the icon patch
char *levellist[CUPCACHE_MAX]; ///< List of levels that belong to this cup
INT16 cachedlevels[CUPCACHE_MAX]; ///< IDs in levellist, bonusgame, and specialstage
@ -379,6 +384,7 @@ struct mapheader_t
{
// Core game information, not user-modifiable directly
char *lumpname; ///< Lump name can be really long
UINT32 lumpnamehash; ///< quickncasehash(->lumpname, MAXMAPLUMPNAME)
lumpnum_t lumpnum; ///< Lump number for the map, used by vres_GetMap
void *thumbnailPic; ///< Lump data for the level select thumbnail.

View file

@ -723,9 +723,13 @@ INT32 G_MapNumber(const char * name)
#endif
{
INT32 map;
UINT32 hash = quickncasehash(name, MAXMAPLUMPNAME);
for (map = 0; map < nummapheaders; ++map)
{
if (hash != mapheaderinfo[map]->lumpnamehash)
continue;
if (strcasecmp(mapheaderinfo[map]->lumpname, name) != 0)
continue;
@ -4388,7 +4392,7 @@ void G_LoadGameData(void)
{
// Since it's not worth declaring the entire gamedata
// corrupt over extra maps, we report and move on.
CONS_Alert(CONS_WARNING, "Map with lumpname %s does not exist, time record data will be discarded", mapname);
CONS_Alert(CONS_WARNING, "Map with lumpname %s does not exist, time record data will be discarded\n", mapname);
}
}