From 32ec9fd4e9dfead6babb6d47f4f5b6b88fba7c0a Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 10 Oct 2022 16:26:20 +0100 Subject: [PATCH 1/4] WADNAME map definition lump special case - For .wad resources, if a map is called WADNAME: - Everything up to the first full stop in the file name is substituted as the long lumpname (so WADNAME in RR_GREENHILLS.beta3.wad replaces map RR_GREENHILLS) - Has (hacky) support for Zone Builder temporary files on Windows - If WADNAME is passed to `-warp` (but NOT `-map` or `+map`) go to the most recent loaded WADNAME - Requires everyone to customise their testing parameters to disable MSDOS 8.3 filenames - For all resources: - Jart added lumpname hashes for the first 8 characters. Use these in W_CheckNumForLongNamePwad and the map equivalent --- src/d_main.c | 18 ++++++-- src/p_setup.c | 6 +++ src/p_setup.h | 3 ++ src/w_wad.c | 112 ++++++++++++++++++++++++++++++++++++++++---------- src/w_wad.h | 2 +- 5 files changed, 115 insertions(+), 26 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index f0f016ca7..a98eba963 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1622,11 +1622,21 @@ void D_SRB2Main(void) { const char *word = M_GetNextParm(); - pstartmap = G_FindMapByNameOrCode(word, 0); - - if (! pstartmap) - I_Error("Cannot find a map remotely named '%s'\n", word); + if (WADNAMECHECK(word)) + { + if (!(pstartmap = wadnamemap)) + I_Error("Bad '%s' level warp.\n" +#if defined (_WIN32) + "Are you using MSDOS 8.3 filenames in Zone Builder?\n" +#endif + , word); + } else + { + if (!(pstartmap = G_FindMapByNameOrCode(word, 0))) + I_Error("Cannot find a map remotely named '%s'\n", word); + } + { if (!M_CheckParm("-server")) { diff --git a/src/p_setup.c b/src/p_setup.c index a4f21ee76..424479493 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4452,6 +4452,9 @@ static lumpinfo_t* FindFolder(const char *folName, UINT16 *start, UINT16 *end, l return lumpinfo; } +lumpnum_t wadnamelump = LUMPERROR; +INT16 wadnamemap = 0; // gamemap based + // Initialising map data (and catching replacements)... UINT8 P_InitMapData(INT32 numexistingmapheaders) { @@ -4499,6 +4502,9 @@ UINT8 P_InitMapData(INT32 numexistingmapheaders) mapheaderinfo[i]->lumpnum = maplump; + if (maplump == wadnamelump) + wadnamemap = i+1; + // Get map thumbnail and minimap virtmap = vres_GetMap(mapheaderinfo[i]->lumpnum); thumbnailPic = vres_Find(virtmap, "PICTURE"); diff --git a/src/p_setup.h b/src/p_setup.h index 3db26a7ba..2af3345fd 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -109,6 +109,9 @@ boolean P_AddWadFile(const char *wadfilename); #define MAPRET_ADDED (1) #define MAPRET_CURRENTREPLACED (1<<1) UINT8 P_InitMapData(INT32 numexistingmapheaders); +extern lumpnum_t wadnamelump; +extern INT16 wadnamemap; +#define WADNAMECHECK(name) (!strncmp(name, "WADNAME", 7)) boolean P_RunSOC(const char *socfilename); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); diff --git a/src/w_wad.c b/src/w_wad.c index 099ce0ded..2808a2ff9 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -435,19 +435,64 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen } else 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); - strncpy(lump_p->longname, fileinfo->name, 8); - lump_p->longname[8] = '\0'; + if (WADNAMECHECK(fileinfo->name)) + { + size_t namelen; + const char *trimname, *dotpos; - // Allocate the lump's full name. - lump_p->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); - strncpy(lump_p->fullname, fileinfo->name, 8); - lump_p->fullname[8] = '\0'; + trimname = strrchr(filename, PATHSEP[0]); +#if defined (_WIN32) + // For Zone Builder support, work around temporary filenames. + if (trimname != 0) + { + const char *temp = trimname-1; + while (temp >= filename+5 && *temp != PATHSEP[0]) + temp--; + + if (temp-filename >= 5 && !strncmp(temp-5, PATHSEP"Temp", 5)) + { + filename = wadfiles[numwadfiles-1]->filename; + trimname = strrchr(filename, PATHSEP[0]); + } + } +#endif + + // Strip away file address + if (trimname != 0) + trimname++; + else + trimname = filename; // Care taken for root files. + + // First stop, not last, to permit RR_GREENHILLS.beta3.wad + if ((dotpos = strchr(trimname, '.')) != 0) + namelen = (dotpos + 1 - trimname); + else + namelen = strlen(trimname); + + // Allocate the lump's long and full name (save on memory). + lump_p->longname = lump_p->fullname = Z_Calloc(namelen * sizeof(char), PU_STATIC, NULL); + strncpy(lump_p->longname, trimname, namelen); + lump_p->longname[namelen-1] = '\0'; + + // Grab the hash from the first part + lump_p->hash = quickncasehash(lump_p->longname, 8); + + wadnamelump = i | (numwadfiles << 16); + } + else + { + // Set up true hash + lump_p->hash = quickncasehash(lump_p->name, 8); + + // Allocate the lump's long and full name (save on memory). + lump_p->longname = lump_p->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + strncpy(lump_p->longname, fileinfo->name, 8); + lump_p->longname[8] = '\0'; + } } free(fileinfov); *nlmp = numlumps; @@ -957,8 +1002,8 @@ UINT16 W_FindNextEmptyInPwad(UINT16 wad, UINT16 startlump) return INT16_MAX; } -// Get a map marker for WADs, and a standalone WAD file lump inside PK3s. -UINT16 W_CheckNumForMapPwad(const char *name, UINT16 wad, UINT16 startlump) +// Get a map marker for WADs, and a standalone WAD file lump inside PK3s. Takes uppercase names only +UINT16 W_CheckNumForMapPwad(const char *name, UINT32 hash, UINT16 wad, UINT16 startlump) { UINT16 i, end; @@ -966,8 +1011,12 @@ UINT16 W_CheckNumForMapPwad(const char *name, UINT16 wad, UINT16 startlump) { for (i = startlump; i < wadfiles[wad]->numlumps; i++) { - // Not the name? - if (strcasecmp(name, (wadfiles[wad]->lumpinfo + i)->name)) + // Not the hash? + if ((wadfiles[wad]->lumpinfo + i)->hash != hash) + continue; + + // Not the name? (always use longname, even in wads, to accomodate WADNAME) + if (strcasecmp(name, (wadfiles[wad]->lumpinfo + i)->longname)) continue; // Not a header? @@ -988,6 +1037,10 @@ UINT16 W_CheckNumForMapPwad(const char *name, UINT16 wad, UINT16 startlump) // Now look for the specified map. for (; i < end; i++) { + // Not the hash? + if ((wadfiles[wad]->lumpinfo + i)->hash != hash) + continue; + // Not the name? if (strcasecmp(name, (wadfiles[wad]->lumpinfo + i)->longname)) continue; @@ -1033,8 +1086,13 @@ 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 (lump_p->hash == hash && !strncmp(lump_p->name, uname, sizeof(uname) - 1)) - return i; + { + if (lump_p->hash != hash) + continue; + if (strncmp(lump_p->name, uname, sizeof(uname) - 1)) + continue; + return i; + } } // not found. @@ -1051,12 +1109,14 @@ UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump) { UINT16 i; static char uname[256 + 1]; + UINT32 hash; if (!TestValidLump(wad,0)) return INT16_MAX; strlcpy(uname, name, sizeof uname); strupr(uname); + hash = quickncasehash(uname, 8); // Not a mistake, legacy system for short lumpnames // // scan forward @@ -1067,8 +1127,13 @@ UINT16 W_CheckNumForLongNamePwad(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 (!strcmp(lump_p->longname, uname)) - return i; + { + if (lump_p->hash != hash) + continue; + if (strcmp(lump_p->longname, uname)) + continue; + return i; + } } // not found. @@ -1254,7 +1319,7 @@ lumpnum_t W_CheckNumForLongName(const char *name) lumpnum_t W_CheckNumForMap(const char *name) { lumpnum_t check = INT16_MAX; - UINT32 hash = quickncasehash(name, LUMPNUMCACHENAME); + UINT32 uhash, hash = quickncasehash(name, LUMPNUMCACHENAME); INT32 i; // Check the lumpnumcache first. Loop backwards so that we check @@ -1269,9 +1334,11 @@ lumpnum_t W_CheckNumForMap(const char *name) } } + uhash = quickncasehash(name, 8); // Not a mistake, legacy system for short lumpnames + for (i = numwadfiles - 1; i >= 0; i--) { - check = W_CheckNumForMapPwad(name, (UINT16)i, 0); + check = W_CheckNumForMapPwad(name, uhash, (UINT16)i, 0); if (check != INT16_MAX) break; // found it @@ -1371,8 +1438,11 @@ UINT8 W_LumpExists(const char *name) { lumpinfo_t *lump_p = wadfiles[i]->lumpinfo; for (j = 0; j < wadfiles[i]->numlumps; ++j, ++lump_p) - if (fastcmp(lump_p->longname, name)) - return true; + { + if (!fastcmp(lump_p->longname, name)) + continue; + return true; + } } return false; } diff --git a/src/w_wad.h b/src/w_wad.h index 5e23ff0a7..361ee4e50 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -155,7 +155,7 @@ const char *W_CheckNameForNum(lumpnum_t lumpnum); UINT16 W_FindNextEmptyInPwad(UINT16 wad, UINT16 startlump); // checks only in one pwad -UINT16 W_CheckNumForMapPwad(const char *name, UINT16 wad, UINT16 startlump); +UINT16 W_CheckNumForMapPwad(const char *name, UINT32 hash, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump); // checks only in one pwad UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump); From e004633fe690e1df995147601bca65100cf19621 Mon Sep 17 00:00:00 2001 From: SteelT Date: Thu, 13 Oct 2022 13:15:06 -0400 Subject: [PATCH 2/4] Fix double-free in W_Shutdown --- src/w_wad.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/w_wad.c b/src/w_wad.c index 2808a2ff9..8edbe74b6 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -124,7 +124,10 @@ void W_Shutdown(void) while (wad->numlumps--) { Z_Free(wad->lumpinfo[wad->numlumps].longname); - Z_Free(wad->lumpinfo[wad->numlumps].fullname); + if (wad->lumpinfo[wad->numlumps].fullname != wad->lumpinfo[wad->numlumps].longname) + { + Z_Free(wad->lumpinfo[wad->numlumps].fullname); + } } Z_Free(wad->lumpinfo); From 01faa52162fb1de4ff290dd363da7435cc95664a Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 13 Oct 2022 16:32:07 -0700 Subject: [PATCH 3/4] Clean up instances of malloc replay file path - Fix allocating only enough for "MAPXX". - Fix memory leak in M_StartTimeAttack. - Use va instead of malloc + sprintf, strdup where needed. Some of these pass gpath to va anyway so that should be enough room. --- src/g_game.c | 11 ++++++----- src/k_menufunc.c | 6 ++---- src/p_setup.c | 10 +++------- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 0363373f4..fb3bda9ec 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -516,7 +516,6 @@ tic_t G_GetBestLap(INT16 map) // static void G_UpdateRecordReplays(void) { - const size_t glen = strlen(srb2home)+1+strlen("media")+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; char *gpath; char lastdemo[256], bestdemo[256]; UINT8 earnedEmblems; @@ -556,12 +555,13 @@ static void G_UpdateRecordReplays(void) srb2home, timeattackfolder); M_MkdirEach(gpath, M_PathParts(gpath) - 3, 0755); - if ((gpath = malloc(glen)) == NULL) - I_Error("Out of memory for replay filepath\n"); + strcat(gpath, PATHSEP); + strcat(gpath, G_BuildMapName(gamemap)); - sprintf(gpath,"%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, cv_chooseskin.string); + gpath = Z_StrDup(gpath); + if (FIL_FileExists(lastdemo)) { UINT8 *buf; @@ -592,7 +592,8 @@ static void G_UpdateRecordReplays(void) Z_Free(buf); } - free(gpath); + + Z_Free(gpath); // Check emblems when level data is updated if ((earnedEmblems = M_CheckLevelEmblems())) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 1f015a907..f02aa2ade 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -3670,7 +3670,6 @@ void M_SetGuestReplay(INT32 choice) void M_StartTimeAttack(INT32 choice) { char *gpath; - const size_t glen = strlen("media")+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; char nameofdemo[256]; (void)choice; @@ -3713,10 +3712,9 @@ void M_StartTimeAttack(INT32 choice) srb2home, timeattackfolder); M_MkdirEach(gpath, M_PathParts(gpath) - 3, 0755); - if ((gpath = malloc(glen)) == NULL) - I_Error("Out of memory for replay filepath\n"); + strcat(gpath, PATHSEP); + strcat(gpath, G_BuildMapName(levellist.choosemap+1)); - sprintf(gpath,"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", timeattackfolder, G_BuildMapName(levellist.choosemap+1)); snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, cv_skin[0].string); if (!cv_autorecord.value) diff --git a/src/p_setup.c b/src/p_setup.c index f2951b182..c007f116f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3701,14 +3701,10 @@ static void P_ResetSpawnpoints(void) static void P_LoadRecordGhosts(void) { // see also k_menu.c's Nextmap_OnChange - const size_t glen = strlen(srb2home)+1+strlen("media")+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; - char *gpath = malloc(glen); + char *gpath; INT32 i; - if (!gpath) - return; - - sprintf(gpath,"%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); + gpath = Z_StrDup(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap))); // Best Time ghost if (cv_ghost_besttime.value) @@ -3771,7 +3767,7 @@ static void P_LoadRecordGhosts(void) } #endif //#ifdef STAFFGHOSTS - free(gpath); + Z_Free(gpath); } static void P_SetupCamera(UINT8 pnum, camera_t *cam) From b686137d12d8adb5920210b9cf9085738267a51b Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 22 Oct 2022 19:56:13 +0100 Subject: [PATCH 4/4] Correctly NULL thumbnailPic and minimapPic when map lumpnum changes Fixes the core part of Chengi's graphical issue --- src/p_setup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index 0901d2156..518683816 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4506,11 +4506,13 @@ UINT8 P_InitMapData(INT32 numexistingmapheaders) if (mapheaderinfo[i]->thumbnailPic) { Patch_Free(mapheaderinfo[i]->thumbnailPic); + mapheaderinfo[i]->thumbnailPic = NULL; } if (mapheaderinfo[i]->minimapPic) { Patch_Free(mapheaderinfo[i]->minimapPic); + mapheaderinfo[i]->minimapPic = NULL; } // Now apply the new ones!