mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 07:12:16 +00:00
- use std::unique_ptr to manage the resource file for loading a savegame because the try/catch handler to ensure its deletion was causing some problems.
This commit is contained in:
parent
f9ef935840
commit
f15b051327
1 changed files with 135 additions and 153 deletions
288
src/g_game.cpp
288
src/g_game.cpp
|
@ -1891,168 +1891,150 @@ void G_DoLoadGame ()
|
||||||
hidecon = gameaction == ga_loadgamehidecon;
|
hidecon = gameaction == ga_loadgamehidecon;
|
||||||
gameaction = ga_nothing;
|
gameaction = ga_nothing;
|
||||||
|
|
||||||
FResourceFile *resfile = FResourceFile::OpenResourceFile(savename.GetChars(), nullptr, true, true);
|
std::unique_ptr<FResourceFile> resfile(FResourceFile::OpenResourceFile(savename.GetChars(), nullptr, true, true));
|
||||||
if (resfile == nullptr)
|
if (resfile == nullptr)
|
||||||
{
|
{
|
||||||
Printf ("Could not read savegame '%s'\n", savename.GetChars());
|
Printf ("Could not read savegame '%s'\n", savename.GetChars());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try
|
FResourceLump *info = resfile->FindLump("info.json");
|
||||||
|
if (info == nullptr)
|
||||||
{
|
{
|
||||||
FResourceLump *info = resfile->FindLump("info.json");
|
Printf("'%s' is not a valid savegame: Missing 'info.json'.\n", savename.GetChars());
|
||||||
if (info == nullptr)
|
return;
|
||||||
{
|
|
||||||
delete resfile;
|
|
||||||
Printf("'%s' is not a valid savegame: Missing 'info.json'.\n", savename.GetChars());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SaveVersion = 0;
|
|
||||||
|
|
||||||
void *data = info->CacheLump();
|
|
||||||
FSerializer arc;
|
|
||||||
if (!arc.OpenReader((const char *)data, info->LumpSize))
|
|
||||||
{
|
|
||||||
Printf("Failed to access savegame info\n");
|
|
||||||
delete resfile;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether this savegame actually has been created by a compatible engine.
|
|
||||||
// Since there are ZDoom derivates using the exact same savegame format but
|
|
||||||
// with mutual incompatibilities this check simplifies things significantly.
|
|
||||||
FString savever, engine, map;
|
|
||||||
arc("Save Version", SaveVersion);
|
|
||||||
arc("Engine", engine);
|
|
||||||
arc("Current Map", map);
|
|
||||||
|
|
||||||
if (engine.CompareNoCase(GAMESIG) != 0)
|
|
||||||
{
|
|
||||||
// Make a special case for the message printed for old savegames that don't
|
|
||||||
// have this information.
|
|
||||||
if (engine.IsEmpty())
|
|
||||||
{
|
|
||||||
Printf("Savegame is from an incompatible version\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Printf("Savegame is from another ZDoom-based engine: %s\n", engine.GetChars());
|
|
||||||
}
|
|
||||||
delete resfile;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SaveVersion < MINSAVEVER || SaveVersion > SAVEVER)
|
|
||||||
{
|
|
||||||
delete resfile;
|
|
||||||
Printf("Savegame is from an incompatible version");
|
|
||||||
if (SaveVersion < MINSAVEVER)
|
|
||||||
{
|
|
||||||
Printf(": %d (%d is the oldest supported)", SaveVersion, MINSAVEVER);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Printf(": %d (%d is the highest supported)", SaveVersion, SAVEVER);
|
|
||||||
}
|
|
||||||
Printf("\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!G_CheckSaveGameWads(arc, true))
|
|
||||||
{
|
|
||||||
delete resfile;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map.IsEmpty())
|
|
||||||
{
|
|
||||||
Printf("Savegame is missing the current map\n");
|
|
||||||
delete resfile;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that it looks like we can load this save, hide the fullscreen console if it was up
|
|
||||||
// when the game was selected from the menu.
|
|
||||||
if (hidecon && gamestate == GS_FULLCONSOLE)
|
|
||||||
{
|
|
||||||
gamestate = GS_HIDECONSOLE;
|
|
||||||
}
|
|
||||||
// we are done with info.json.
|
|
||||||
arc.Close();
|
|
||||||
|
|
||||||
info = resfile->FindLump("globals.json");
|
|
||||||
if (info == nullptr)
|
|
||||||
{
|
|
||||||
delete resfile;
|
|
||||||
Printf("'%s' is not a valid savegame: Missing 'globals.json'.\n", savename.GetChars());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = info->CacheLump();
|
|
||||||
if (!arc.OpenReader((const char *)data, info->LumpSize))
|
|
||||||
{
|
|
||||||
Printf("Failed to access savegame info\n");
|
|
||||||
delete resfile;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Read intermission data for hubs
|
|
||||||
G_SerializeHub(arc);
|
|
||||||
|
|
||||||
bglobal.RemoveAllBots(true);
|
|
||||||
|
|
||||||
FString cvar;
|
|
||||||
arc("importantcvars", cvar);
|
|
||||||
if (!cvar.IsEmpty())
|
|
||||||
{
|
|
||||||
BYTE *vars_p = (BYTE *)cvar.GetChars();
|
|
||||||
C_ReadCVars(&vars_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD time[2] = { 1,0 };
|
|
||||||
|
|
||||||
arc("ticrate", time[0])
|
|
||||||
("leveltime", time[1]);
|
|
||||||
// dearchive all the modifications
|
|
||||||
level.time = Scale(time[1], TICRATE, time[0]);
|
|
||||||
|
|
||||||
G_ReadSnapshots(resfile);
|
|
||||||
delete resfile; // we no longer need the resource file below this point
|
|
||||||
resfile = nullptr;
|
|
||||||
G_ReadVisited(arc);
|
|
||||||
|
|
||||||
// load a base level
|
|
||||||
savegamerestore = true; // Use the player actors in the savegame
|
|
||||||
bool demoplaybacksave = demoplayback;
|
|
||||||
G_InitNew(map, false);
|
|
||||||
demoplayback = demoplaybacksave;
|
|
||||||
savegamerestore = false;
|
|
||||||
|
|
||||||
STAT_Serialize(arc);
|
|
||||||
FRandom::StaticReadRNGState(arc);
|
|
||||||
P_ReadACSDefereds(arc);
|
|
||||||
P_ReadACSVars(arc);
|
|
||||||
|
|
||||||
NextSkill = -1;
|
|
||||||
arc("nextskill", NextSkill);
|
|
||||||
|
|
||||||
if (level.info != nullptr)
|
|
||||||
level.info->Snapshot.Clean();
|
|
||||||
|
|
||||||
BackupSaveName = savename;
|
|
||||||
|
|
||||||
// At this point, the GC threshold is likely a lot higher than the
|
|
||||||
// amount of memory in use, so bring it down now by starting a
|
|
||||||
// collection.
|
|
||||||
GC::StartCollection();
|
|
||||||
}
|
}
|
||||||
catch (...)
|
|
||||||
|
SaveVersion = 0;
|
||||||
|
|
||||||
|
void *data = info->CacheLump();
|
||||||
|
FSerializer arc;
|
||||||
|
if (!arc.OpenReader((const char *)data, info->LumpSize))
|
||||||
{
|
{
|
||||||
// delete the resource file if anything goes wrong in here.
|
Printf("Failed to access savegame info\n");
|
||||||
if (resfile != nullptr) delete resfile;
|
return;
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check whether this savegame actually has been created by a compatible engine.
|
||||||
|
// Since there are ZDoom derivates using the exact same savegame format but
|
||||||
|
// with mutual incompatibilities this check simplifies things significantly.
|
||||||
|
FString savever, engine, map;
|
||||||
|
arc("Save Version", SaveVersion);
|
||||||
|
arc("Engine", engine);
|
||||||
|
arc("Current Map", map);
|
||||||
|
|
||||||
|
if (engine.CompareNoCase(GAMESIG) != 0)
|
||||||
|
{
|
||||||
|
// Make a special case for the message printed for old savegames that don't
|
||||||
|
// have this information.
|
||||||
|
if (engine.IsEmpty())
|
||||||
|
{
|
||||||
|
Printf("Savegame is from an incompatible version\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Printf("Savegame is from another ZDoom-based engine: %s\n", engine.GetChars());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SaveVersion < MINSAVEVER || SaveVersion > SAVEVER)
|
||||||
|
{
|
||||||
|
Printf("Savegame is from an incompatible version");
|
||||||
|
if (SaveVersion < MINSAVEVER)
|
||||||
|
{
|
||||||
|
Printf(": %d (%d is the oldest supported)", SaveVersion, MINSAVEVER);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Printf(": %d (%d is the highest supported)", SaveVersion, SAVEVER);
|
||||||
|
}
|
||||||
|
Printf("\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!G_CheckSaveGameWads(arc, true))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map.IsEmpty())
|
||||||
|
{
|
||||||
|
Printf("Savegame is missing the current map\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that it looks like we can load this save, hide the fullscreen console if it was up
|
||||||
|
// when the game was selected from the menu.
|
||||||
|
if (hidecon && gamestate == GS_FULLCONSOLE)
|
||||||
|
{
|
||||||
|
gamestate = GS_HIDECONSOLE;
|
||||||
|
}
|
||||||
|
// we are done with info.json.
|
||||||
|
arc.Close();
|
||||||
|
|
||||||
|
info = resfile->FindLump("globals.json");
|
||||||
|
if (info == nullptr)
|
||||||
|
{
|
||||||
|
Printf("'%s' is not a valid savegame: Missing 'globals.json'.\n", savename.GetChars());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = info->CacheLump();
|
||||||
|
if (!arc.OpenReader((const char *)data, info->LumpSize))
|
||||||
|
{
|
||||||
|
Printf("Failed to access savegame info\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read intermission data for hubs
|
||||||
|
G_SerializeHub(arc);
|
||||||
|
|
||||||
|
bglobal.RemoveAllBots(true);
|
||||||
|
|
||||||
|
FString cvar;
|
||||||
|
arc("importantcvars", cvar);
|
||||||
|
if (!cvar.IsEmpty())
|
||||||
|
{
|
||||||
|
BYTE *vars_p = (BYTE *)cvar.GetChars();
|
||||||
|
C_ReadCVars(&vars_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD time[2] = { 1,0 };
|
||||||
|
|
||||||
|
arc("ticrate", time[0])
|
||||||
|
("leveltime", time[1]);
|
||||||
|
// dearchive all the modifications
|
||||||
|
level.time = Scale(time[1], TICRATE, time[0]);
|
||||||
|
|
||||||
|
G_ReadSnapshots(resfile.get());
|
||||||
|
resfile.reset(nullptr); // we no longer need the resource file below this point
|
||||||
|
G_ReadVisited(arc);
|
||||||
|
|
||||||
|
// load a base level
|
||||||
|
savegamerestore = true; // Use the player actors in the savegame
|
||||||
|
bool demoplaybacksave = demoplayback;
|
||||||
|
G_InitNew(map, false);
|
||||||
|
demoplayback = demoplaybacksave;
|
||||||
|
savegamerestore = false;
|
||||||
|
|
||||||
|
STAT_Serialize(arc);
|
||||||
|
FRandom::StaticReadRNGState(arc);
|
||||||
|
P_ReadACSDefereds(arc);
|
||||||
|
P_ReadACSVars(arc);
|
||||||
|
|
||||||
|
NextSkill = -1;
|
||||||
|
arc("nextskill", NextSkill);
|
||||||
|
|
||||||
|
if (level.info != nullptr)
|
||||||
|
level.info->Snapshot.Clean();
|
||||||
|
|
||||||
|
BackupSaveName = savename;
|
||||||
|
|
||||||
|
// At this point, the GC threshold is likely a lot higher than the
|
||||||
|
// amount of memory in use, so bring it down now by starting a
|
||||||
|
// collection.
|
||||||
|
GC::StartCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue