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/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 743902d61..ee4cf32e4 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -6982,14 +6982,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) @@ -7052,7 +7048,7 @@ static void P_LoadRecordGhosts(void) } #endif //#ifdef STAFFGHOSTS - free(gpath); + Z_Free(gpath); } static void P_SetupCamera(UINT8 pnum, camera_t *cam) @@ -7733,6 +7729,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) { @@ -7780,6 +7779,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"); @@ -7789,11 +7791,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! diff --git a/src/p_setup.h b/src/p_setup.h index 6b4c34885..d5d3aa7d0 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..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); @@ -435,19 +438,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 +1005,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 +1014,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 +1040,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 +1089,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 +1112,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 +1130,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 +1322,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 +1337,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 +1441,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);