Fix case of map savegames name (save/bla/MAPNAME.sav/sv2)

introduced FS_GetFilenameForHandle(fileHandle_t) for this

this helps if a map has been started with "wrong" case, which doesn't
immediately fail if it has been loaded from a pack, but will result
in invalid savegame names that (with case-sensitive FSs) will fail to
load (when going back to a formerly played level)
This commit is contained in:
Daniel Gibson 2019-02-17 18:46:57 +01:00
parent 3296b7a1a2
commit d2d87025fa
4 changed files with 57 additions and 3 deletions

View file

@ -70,7 +70,7 @@ struct {
/*
* The GOG version of Quake2 has the music tracks in music/TrackXX.ogg
* That music/ dir is next to baseq/ (not in it) and contains Track02.ogg to Track21.ogg
* That music/ dir is next to baseq2/ (not in it) and contains Track02.ogg to Track21.ogg
* There
* - Track02 to Track11 correspond to Quake2 (baseq2) CD tracks 2-11
* - Track12 to Track21 correspond to the Ground Zero (rogue) addon's CD tracks 2-11

View file

@ -414,6 +414,11 @@ FS_FOpenFile(const char *name, fileHandle_t *f, qboolean gamedir_only)
handle->name, pack->name);
}
// save the name with *correct case* in the handle
// (relevant for savegames, when starting map with wrong case but it's still found
// because it's from pak, but save/bla/MAPname.sav/sv2 will have wrong case and can't be found then)
Q_strlcpy(handle->name, pack->files[i].name, sizeof(handle->name));
if (pack->pak)
{
/* PAK */
@ -1654,6 +1659,18 @@ FS_BuildGameSpecificSearchPath(char *dir)
#endif
}
// returns the filename used to open f, but (if opened from pack) in correct case
// returns NULL if f is no valid handle
const char* FS_GetFilenameForHandle(fileHandle_t f)
{
fsHandle_t* fsh = FS_GetFileByHandle(f);
if(fsh)
{
return fsh->name;
}
return NULL;
}
// --------
void FS_AddDirToRawPath (const char *dir, qboolean create) {

View file

@ -663,6 +663,11 @@ int FS_FOpenFile(const char *name, fileHandle_t *f, qboolean gamedir_only);
void FS_FCloseFile(fileHandle_t f);
int FS_Read(void *buffer, int size, fileHandle_t f);
int FS_FRead(void *buffer, int size, int count, fileHandle_t f);
// returns the filename used to open f, but (if opened from pack) in correct case
// returns NULL if f is no valid handle
const char* FS_GetFilenameForHandle(fileHandle_t f);
char **FS_ListFiles(char *findname, int *numfiles,
unsigned musthave, unsigned canthave);
char **FS_ListFiles2(char *findname, int *numfiles,

View file

@ -226,11 +226,43 @@ SV_GameMap_f(void)
}
}
// it's possible to start a map with the wrong case, e.g. "/map BASE1"
// (even though the mapfile is maps/base1.bsp)
// however, that will screw up the corresponding savegame (for going back to last map)
// which will then be called baseq2/save/bla/BASE1.sav - because when going back to the
// map from base2 it will look for .../base1.sav
// so try to fix the mapname here
// NOTE: does not properly handle all variations like base2$base1 and whatever else we forgot
// but so far we haven't run into problems with that anyway
char mapPath[MAX_QPATH];
{
qboolean haveStar = (map[0] == '*');
snprintf(mapPath, sizeof(mapPath), "maps/%s.bsp", haveStar ? map+1 : map);
fileHandle_t f = -1;
if(FS_FOpenFile(mapPath, &f, false) >= 0)
{
const char* realMapPath = FS_GetFilenameForHandle(f);
// now mapPath contains the fixed path
Q_strlcpy(mapPath, realMapPath, sizeof(mapPath));
FS_FCloseFile(f);
map = mapPath + 4; // skip "maps"
if(haveStar)
map[0] = '*'; // restore it (=> replace '/' by '*')
else
++map; // skip '/'
map[strlen(map)-4] = '\0'; // cut off ".bsp"
}
}
/* start up the next map */
SV_Map(false, Cmd_Argv(1), false);
SV_Map(false, map, false);
/* archive server state */
Q_strlcpy(svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd));
Q_strlcpy(svs.mapcmd, map, sizeof(svs.mapcmd));
/* copy off the level to the autosave slot */
if (!dedicated->value)