- converted the basic savegame loader so that all remnant of FArchive have been removed now.

This commit is contained in:
Christoph Oelckers 2016-09-22 00:18:31 +02:00
parent 88c27e2cc0
commit 1c9dbc3c36
11 changed files with 187 additions and 239 deletions

View file

@ -14,7 +14,6 @@
#include "a_specialspot.h"
#include "templates.h"
#include "m_bbox.h"
#include "farchive.h"
#include "portal.h"
#include "d_player.h"
#include "p_maputl.h"

View file

@ -1830,10 +1830,6 @@ bool G_CheckSaveGameWads (FSerializer &arc, bool printwarn)
void G_DoLoadGame ()
{
#if 0 // SAVEGAME
char sigcheck[20];
char *text = NULL;
char *map;
bool hidecon;
if (gameaction != ga_autoloadgame)
@ -1843,76 +1839,82 @@ void G_DoLoadGame ()
hidecon = gameaction == ga_loadgamehidecon;
gameaction = ga_nothing;
FILE *stdfile = fopen (savename.GetChars(), "rb");
if (stdfile == NULL)
FResourceFile *resfile = FResourceFile::OpenResourceFile(savename.GetChars(), nullptr, true, true);
if (resfile == nullptr)
{
Printf ("Could not read savegame '%s'\n", savename.GetChars());
return;
}
PNGHandle *png = M_VerifyPNG (stdfile);
if (png == NULL)
FResourceLump *info = resfile->FindLump("info.json");
if (info == nullptr)
{
fclose (stdfile);
Printf ("'%s' is not a valid (PNG) savegame\n", savename.GetChars());
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, true))
{
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.
char *engine = M_GetPNGText (png, "Engine");
if (engine == NULL || 0 != strcmp (engine, GAMESIG))
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 == NULL)
if (engine.IsEmpty())
{
Printf ("Savegame is from an incompatible version\n");
}
else
{
Printf ("Savegame is from another ZDoom-based engine: %s\n", engine);
delete[] engine;
}
delete png;
fclose (stdfile);
delete resfile;
return;
}
if (engine != NULL)
{
delete[] engine;
}
SaveVersion = 0;
if (!M_GetPNGText (png, "ZDoom Save Version", sigcheck, 20) ||
0 != strncmp (sigcheck, "SAVEVER", 9) || // ZDOOMSAVE is the first 9 chars
(SaveVersion = atoi (sigcheck+9)) < MINSAVEVER)
if (SaveVersion < MINSAVEVER || SaveVersion > SAVEVER)
{
delete png;
fclose (stdfile);
delete resfile;
Printf ("Savegame is from an incompatible version");
if (SaveVersion != 0)
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 (png, true))
if (!G_CheckSaveGameWads (arc, true))
{
fclose (stdfile);
delete resfile;
return;
}
map = M_GetPNGText (png, "Current Map");
if (map == NULL)
if (map.IsEmpty())
{
Printf ("Savegame is missing the current map\n");
fclose (stdfile);
delete resfile;
return;
}
@ -1922,35 +1924,46 @@ void G_DoLoadGame ()
{
gamestate = GS_HIDECONSOLE;
}
// we are done with info.json.
arc.Close();
info = resfile->FindLump("global.json");
if (info == nullptr)
{
delete resfile;
Printf("'%s' is not a valid savegame: Missing 'global.json'.\n", savename.GetChars());
return;
}
data = info->CacheLump();
if (!arc.OpenReader((const char *)data, info->LumpSize, true))
{
Printf("Failed to access savegame info\n");
delete resfile;
return;
}
// Read intermission data for hubs
G_ReadHubInfo(png);
G_SerializeHub(arc);
bglobal.RemoveAllBots (true);
text = M_GetPNGText (png, "Important CVARs");
if (text != NULL)
arc("importantcvars", map);
if (!map.IsEmpty())
{
BYTE *vars_p = (BYTE *)text;
BYTE *vars_p = (BYTE *)map.GetChars();
C_ReadCVars (&vars_p);
delete[] text;
}
DWORD time[2] = { 0,1 };
arc("ticrate", time[0])
("leveltime", time[1]);
// dearchive all the modifications
if (M_FindPNGChunk (png, MAKE_ID('p','t','I','c')) == 8)
{
DWORD time[2];
fread (&time, 8, 1, stdfile);
time[0] = BigLong((unsigned int)time[0]);
time[1] = BigLong((unsigned int)time[1]);
level.time = Scale (time[1], TICRATE, time[0]);
}
else
{ // No ptIc chunk so we don't know how long the user was playing
level.time = 0;
}
level.time = Scale (time[1], TICRATE, time[0]);
G_ReadSnapshots (png);
//G_ReadSnapshots(png);
// load a base level
savegamerestore = true; // Use the player actors in the savegame
@ -1960,31 +1973,24 @@ void G_DoLoadGame ()
delete[] map;
savegamerestore = false;
STAT_Read(png);
FRandom::StaticReadRNGState(png);
P_ReadACSDefereds(png);
P_ReadACSVars(png);
STAT_Serialize(arc);
FRandom::StaticReadRNGState(arc);
P_ReadACSDefereds(arc);
P_ReadACSVars(arc);
NextSkill = -1;
if (M_FindPNGChunk (png, MAKE_ID('s','n','X','t')) == 1)
{
BYTE next;
fread (&next, 1, 1, stdfile);
NextSkill = next;
}
arc("nextskill", NextSkill);
level.info->Snapshot.Clean();
BackupSaveName = savename;
delete png;
fclose (stdfile);
delete resfile;
// 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();
#endif
}

View file

@ -1630,83 +1630,71 @@ void G_WriteVisited(FSerializer &arc)
//
//==========================================================================
void G_ReadSnapshots (PNGHandle *png)
void G_ReadSnapshots(PNGHandle *png)
{
DWORD chunkLen;
FString MapName;
level_info_t *i;
G_ClearSnapshots ();
G_ClearSnapshots();
chunkLen = (DWORD)M_FindPNGChunk (png, SNAP_ID);
chunkLen = (DWORD)M_FindPNGChunk(png, SNAP_ID);
while (chunkLen != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), SNAP_ID, chunkLen);
#if 0
FPNGChunkArchive arc(png->File->GetFile(), SNAP_ID, chunkLen);
DWORD snapver;
arc << snapver;
arc << MapName;
i = FindLevelInfo (MapName);
#if 0
i = FindLevelInfo(MapName);
i->snapshot = new FCompressedMemFile;
i->snapshot->Serialize (arc);
i->snapshot->Serialize(arc);
chunkLen = (DWORD)M_NextPNGChunk(png, SNAP_ID);
#endif
chunkLen = (DWORD)M_NextPNGChunk (png, SNAP_ID);
}
chunkLen = (DWORD)M_FindPNGChunk (png, DSNP_ID);
chunkLen = (DWORD)M_FindPNGChunk(png, DSNP_ID);
if (chunkLen != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), DSNP_ID, chunkLen);
#if 0
FPNGChunkArchive arc(png->File->GetFile(), DSNP_ID, chunkLen);
DWORD snapver;
arc << snapver;
arc << MapName;
#if 0
TheDefaultLevelInfo.snapshot = new FCompressedMemFile;
TheDefaultLevelInfo.snapshot->Serialize (arc);
TheDefaultLevelInfo.snapshot->Serialize(arc);
#endif
}
}
chunkLen = (DWORD)M_FindPNGChunk (png, VIST_ID);
if (chunkLen != 0)
void G_ReadVisited(FSerializer &arc)
{
if (arc.BeginArray("visited"))
{
FPNGChunkArchive arc (png->File->GetFile(), VIST_ID, chunkLen);
while (arc << MapName, MapName.Len() > 0)
for (int s = arc.ArraySize(); s > 0; s--)
{
i = FindLevelInfo(MapName);
i->flags |= LEVEL_VISITED;
FString str;
arc(nullptr, str);
auto i = FindLevelInfo(str);
if (i != nullptr) i->flags |= LEVEL_VISITED;
}
arc.EndArray();
}
chunkLen = (DWORD)M_FindPNGChunk (png, RCLS_ID);
if (chunkLen != 0)
arc.Array("randomclasses", SinglePlayerClass, MAXPLAYERS);
if (arc.BeginObject("playerclasses"))
{
FPNGChunkArchive arc (png->File->GetFile(), PCLS_ID, chunkLen);
SBYTE cnum;
for (DWORD j = 0; j < chunkLen; ++j)
for (int i = 0; i < MAXPLAYERS; ++i)
{
arc << cnum;
SinglePlayerClass[j] = cnum;
FString key;
key.Format("%d", i);
arc(key, players[i].cls);
}
arc.EndObject();
}
chunkLen = (DWORD)M_FindPNGChunk (png, PCLS_ID);
if (chunkLen != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), RCLS_ID, chunkLen);
BYTE pnum;
arc << pnum;
while (pnum != 255)
{
arc.UserReadClass (players[pnum].cls);
arc << pnum;
}
}
png->File->ResetFilePtr();
}
//==========================================================================
@ -1749,8 +1737,7 @@ void P_WriteACSDefereds (FSerializer &arc)
{
if (wi.deferred.Size() > 0 && arc.BeginObject(nullptr))
{
arc(wi.MapName, wi.deferred)
.EndObject();
arc(wi.MapName, wi.deferred);
}
}
}
@ -1763,30 +1750,28 @@ void P_WriteACSDefereds (FSerializer &arc)
//
//==========================================================================
void P_ReadACSDefereds (PNGHandle *png)
void P_ReadACSDefereds (FSerializer &arc)
{
#if 0
FString MapName;
size_t chunklen;
P_RemoveDefereds ();
if ((chunklen = M_FindPNGChunk (png, ACSD_ID)) != 0)
if (arc.BeginObject("deferred"))
{
FPNGChunkArchive arc (png->File->GetFile(), ACSD_ID, chunklen);
const char *key;
while (arc << MapName, MapName.Len() > 0)
while ((key = arc.GetKey()))
{
level_info_t *i = FindLevelInfo(MapName);
level_info_t *i = FindLevelInfo(key);
if (i == NULL)
{
I_Error("Unknown map '%s' in savegame", MapName.GetChars());
I_Error("Unknown map '%s' in savegame", key);
}
arc << i->deferred;
arc(key, i->deferred);
}
arc.EndObject();
}
png->File->ResetFilePtr();
#endif
}

View file

@ -536,6 +536,7 @@ struct PNGHandle;
void G_ReadSnapshots (PNGHandle *png);
void G_WriteSnapshots (TArray<FString> &, TArray<FCompressedBuffer> &);
void G_WriteVisited(FSerializer &arc);
void G_ReadVisited(FSerializer &arc);
void G_ClearHubInfo();
enum ESkillProperty

View file

@ -326,54 +326,36 @@ void FRandom::StaticWriteRNGState (FSerializer &arc)
//
//==========================================================================
void FRandom::StaticReadRNGState (PNGHandle *png)
void FRandom::StaticReadRNGState(FSerializer &arc)
{
#if 0
FRandom *rng;
size_t len = M_FindPNGChunk (png, RAND_ID);
if (len != 0)
arc("rngseed", rng);
if (arc.BeginArray("rngs"))
{
const size_t sizeof_rng = sizeof(rng->NameCRC) + sizeof(rng->idx) + sizeof(rng->sfmt.u);
const int rngcount = (int)((len-4) / sizeof_rng);
int i;
DWORD crc;
int count = arc.ArraySize();
FPNGChunkArchive arc (png->File->GetFile(), RAND_ID, len);
arc << rngseed;
FRandom::StaticClearRandom ();
for (i = rngcount; i; --i)
for (int i = 0; i < count; i++)
{
arc << crc;
for (rng = FRandom::RNGList; rng != NULL; rng = rng->Next)
if (arc.BeginObject(nullptr))
{
if (rng->NameCRC == crc)
uint32_t crc;
arc("crc", crc);
for (rng = FRandom::RNGList; rng != NULL; rng = rng->Next)
{
arc << rng->idx;
for (int i = 0; i < SFMT::N32; ++i)
if (rng->NameCRC == crc)
{
arc << rng->sfmt.u[i];
arc("index", rng->idx)
.Array("u", rng->sfmt.u, SFMT::N32);
break;
}
break;
}
}
if (rng == NULL)
{ // The RNG was removed. Skip it.
int idx;
DWORD sfmt;
arc << idx;
for (int i = 0; i < SFMT::N32; ++i)
{
arc << sfmt;
}
arc.EndObject();
}
arc.EndArray();
}
png->File->ResetFilePtr();
}
#endif
}
//==========================================================================

View file

@ -175,7 +175,7 @@ public:
// Static interface
static void StaticClearRandom ();
static DWORD StaticSumSeeds ();
static void StaticReadRNGState (PNGHandle *png);
static void StaticReadRNGState (FSerializer &arc);
static void StaticWriteRNGState (FSerializer &file);
static FRandom *StaticFindRNG(const char *name);

View file

@ -722,47 +722,42 @@ void ACSStringPool::FindFirstFreeEntry(unsigned base)
//
//============================================================================
void ACSStringPool::ReadStrings(PNGHandle *png, DWORD id)
void ACSStringPool::ReadStrings(FSerializer &file, const char *key)
{
Clear();
size_t len = M_FindPNGChunk(png, id);
if (len != 0)
int32_t i, j, poolsize;
file("poolsize", poolsize);
Pool.Resize(poolsize);
for (auto &p : Pool)
{
FPNGChunkArchive arc(png->File->GetFile(), id, len);
int32_t i, j, poolsize;
unsigned int h, bucketnum;
char *str = NULL;
arc << poolsize;
Pool.Resize(poolsize);
i = 0;
j = arc.ReadCount();
while (j >= 0)
p.Next = FREE_ENTRY;
p.LockCount = 0;
}
if (file.BeginArray("pool"))
{
j = file.ArraySize();
for (int i = 0; i < j; i++)
{
// Mark skipped entries as free
for (; i < j; ++i)
if (file.BeginObject(nullptr))
{
Pool[i].Next = FREE_ENTRY;
Pool[i].LockCount = 0;
i = -1;
file("index", i);
if (i >= 0 && i < Pool.Size())
{
file("string", Pool[i].Str)
("lockcount", Pool[i].LockCount);
unsigned h = SuperFastHash(Pool[i].Str, Pool[i].Str.Len());
unsigned bucketnum = h % NUM_BUCKETS;
Pool[i].Hash = h;
Pool[i].Next = PoolBuckets[bucketnum];
PoolBuckets[bucketnum] = i;
}
file.EndObject();
}
arc << str;
h = SuperFastHash(str, strlen(str));
bucketnum = h % NUM_BUCKETS;
Pool[i].Str = str;
Pool[i].Hash = h;
Pool[i].LockCount = arc.ReadCount();
Pool[i].Next = PoolBuckets[bucketnum];
PoolBuckets[bucketnum] = i;
i++;
j = arc.ReadCount();
}
if (str != NULL)
{
delete[] str;
}
FindFirstFreeEntry(0);
}
}
@ -982,29 +977,10 @@ static void WriteVars (FSerializer &file, SDWORD *vars, size_t count, const char
//
//============================================================================
static void ReadVars (PNGHandle *png, SDWORD *vars, size_t count, DWORD id)
static void ReadVars (FSerializer &arc, SDWORD *vars, size_t count, const char *key)
{
size_t len = M_FindPNGChunk (png, id);
size_t used = 0;
if (len != 0)
{
DWORD var;
size_t i;
FPNGChunkArchive arc (png->File->GetFile(), id, len);
used = len / 4;
for (i = 0; i < used; ++i)
{
arc << var;
vars[i] = var;
}
png->File->ResetFilePtr();
}
if (used < count)
{
memset (&vars[used], 0, (count-used)*4);
}
memset(&vars[0], 0, count * 4);
arc.Array(key, vars, count);
}
//============================================================================
@ -1060,37 +1036,32 @@ static void WriteArrayVars (FSerializer &file, FWorldGlobalArray *vars, unsigned
//
//============================================================================
static void ReadArrayVars (PNGHandle *png, FWorldGlobalArray *vars, size_t count, DWORD id)
static void ReadArrayVars (FSerializer &file, FWorldGlobalArray *vars, size_t count, const char *key)
{
size_t len = M_FindPNGChunk (png, id);
unsigned int i, k;
for (i = 0; i < count; ++i)
{
vars[i].Clear ();
vars[i].Clear();
}
if (len != 0)
if (file.BeginObject(key))
{
DWORD max, size;
FPNGChunkArchive arc (png->File->GetFile(), id, len);
i = arc.ReadCount ();
max = arc.ReadCount ();
for (; i <= max; ++i)
const char *arraykey;
while ((arraykey = file.GetKey()))
{
size = arc.ReadCount ();
for (k = 0; k < size; ++k)
int i = (int)strtol(arraykey, nullptr, 10);
if (file.BeginObject(arraykey))
{
SDWORD key, val;
key = arc.ReadCount();
val = arc.ReadCount();
vars[i].Insert (key, val);
while ((arraykey = file.GetKey()))
{
int k = (int)strtol(arraykey, nullptr, 10);
int val;
file(arraykey, val);
vars[i].Insert(k, val);
}
file.EndObject();
}
}
png->File->ResetFilePtr();
file.EndObject();
}
}
@ -1100,13 +1071,13 @@ static void ReadArrayVars (PNGHandle *png, FWorldGlobalArray *vars, size_t count
//
//============================================================================
void P_ReadACSVars(PNGHandle *png)
void P_ReadACSVars(FSerializer &arc)
{
ReadVars (png, ACS_WorldVars, NUM_WORLDVARS, MAKE_ID('w','v','A','r'));
ReadVars (png, ACS_GlobalVars, NUM_GLOBALVARS, MAKE_ID('g','v','A','r'));
ReadArrayVars (png, ACS_WorldArrays, NUM_WORLDVARS, MAKE_ID('w','a','R','r'));
ReadArrayVars (png, ACS_GlobalArrays, NUM_GLOBALVARS, MAKE_ID('g','a','R','r'));
GlobalACSStrings.ReadStrings(png, MAKE_ID('a','s','T','r'));
ReadVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars");
ReadVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars");
ReadArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays");
ReadArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays");
GlobalACSStrings.ReadStrings(arc, "acsglobalstrings");
}
//============================================================================

View file

@ -96,7 +96,7 @@ public:
void PurgeStrings();
void Clear();
void Dump() const;
void ReadStrings(PNGHandle *png, DWORD id);
void ReadStrings(FSerializer &file, const char *key);
void WriteStrings(FSerializer &file, const char *key) const;
private:
@ -122,7 +122,7 @@ private:
extern ACSStringPool GlobalACSStrings;
void P_CollectACSGlobalStrings();
void P_ReadACSVars(PNGHandle *);
void P_ReadACSVars(FSerializer &);
void P_WriteACSVars(FSerializer &);
void P_ClearACSVars(bool);

View file

@ -42,7 +42,7 @@ class FSerializer;
// Also see farchive.(h|cpp)
void P_DestroyThinkers(bool hubLoad);
void P_ReadACSDefereds (PNGHandle *png);
void P_ReadACSDefereds (FSerializer &);
void P_WriteACSDefereds (FSerializer &);
void G_SerializeLevel(FSerializer &arc, bool hubLoad);

View file

@ -730,7 +730,7 @@ const char *FSerializer::GetKey()
void FSerializer::WriteObjects()
{
if (isWriting())
if (isWriting() && w->mDObjects.Size())
{
BeginArray("objects");
// we cannot use the C++11 shorthand syntax here because the array may grow while being processed.
@ -769,6 +769,7 @@ void FSerializer::WriteObjects()
const char *FSerializer::GetOutput(unsigned *len)
{
if (isReading()) return nullptr;
WriteObjects();
EndObject();
if (len != nullptr)
{
@ -787,6 +788,7 @@ FCompressedBuffer FSerializer::GetCompressedOutput()
{
if (isReading()) return{ 0,0,0,0,0,nullptr };
FCompressedBuffer buff;
WriteObjects();
EndObject();
buff.mSize = (unsigned)w->mOutString.GetSize();
buff.mZipFlags = 0;

View file

@ -111,6 +111,8 @@ public:
if (BeginArray(key))
{
int max = ArraySize();
if (max < count) count = max;
for (int i = 0; i < count; i++)
{
Serialize(*this, nullptr, obj[i], (T*)nullptr);