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);