- implemented saving of new format savegames as zips. The code for that was adapted from zipdir.c.

This commit is contained in:
Christoph Oelckers 2016-09-21 17:37:56 +02:00
parent 810ef8f775
commit ac3c00883d
15 changed files with 253 additions and 104 deletions

View file

@ -2580,7 +2580,7 @@ void D_DoomMain (void)
{ {
FString file(v); FString file(v);
FixPathSeperator (file); FixPathSeperator (file);
DefaultExtension (file, ".zds" SAVEGAME_EXT); DefaultExtension (file, "." SAVEGAME_EXT);
G_LoadGame (file); G_LoadGame (file);
} }

View file

@ -962,32 +962,6 @@ PClass *FArchive::ReadStoredClass (const PClass *wanttype)
return type; return type;
} }
void FArchive::UserWriteClass (PClass *type)
{
BYTE id;
if (type == NULL)
{
id = 2;
Write (&id, 1);
}
else
{
DWORD *arcid;
if (NULL == (arcid = ClassToArchive.CheckKey(type)))
{
id = 1;
Write (&id, 1);
WriteClass (type);
}
else
{
id = 0;
Write (&id, 1);
WriteCount (*arcid);
}
}
}
void FArchive::UserReadClass (PClass *&type) void FArchive::UserReadClass (PClass *&type)
{ {

View file

@ -152,7 +152,6 @@ virtual void Read (void *mem, unsigned int len);
void WriteCount (DWORD count); void WriteCount (DWORD count);
DWORD ReadCount (); DWORD ReadCount ();
void UserWriteClass (PClass *info);
void UserReadClass (PClass *&info); void UserReadClass (PClass *&info);
template<typename T> void UserReadClass(T *&info) template<typename T> void UserReadClass(T *&info)
{ {

View file

@ -85,6 +85,8 @@
#include "p_spec.h" #include "p_spec.h"
#include "r_data/colormaps.h" #include "r_data/colormaps.h"
#include "serializer.h" #include "serializer.h"
#include "w_zip.h"
#include "resourcefiles/resourcefile.h"
#include <zlib.h> #include <zlib.h>
@ -112,6 +114,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
void G_DoAutoSave (); void G_DoAutoSave ();
void STAT_Serialize(FSerializer &file); void STAT_Serialize(FSerializer &file);
bool WriteZip(const char *filename, TArray<FString> &filenames, TArray<FCompressedBuffer> &content);
FIntCVar gameskill ("skill", 2, CVAR_SERVERINFO|CVAR_LATCH); FIntCVar gameskill ("skill", 2, CVAR_SERVERINFO|CVAR_LATCH);
CVAR (Int, deathmatch, 0, CVAR_SERVERINFO|CVAR_LATCH); CVAR (Int, deathmatch, 0, CVAR_SERVERINFO|CVAR_LATCH);
@ -1886,7 +1889,7 @@ void G_DoLoadGame ()
SaveVersion = 0; SaveVersion = 0;
if (!M_GetPNGText (png, "ZDoom Save Version", sigcheck, 20) || if (!M_GetPNGText (png, "ZDoom Save Version", sigcheck, 20) ||
0 != strncmp (sigcheck, SAVESIG, 9) || // ZDOOMSAVE is the first 9 chars 0 != strncmp (sigcheck, "SAVEVER", 9) || // ZDOOMSAVE is the first 9 chars
(SaveVersion = atoi (sigcheck+9)) < MINSAVEVER) (SaveVersion = atoi (sigcheck+9)) < MINSAVEVER)
{ {
delete png; delete png;
@ -2045,7 +2048,7 @@ FString G_BuildSaveName (const char *prefix, int slot)
name << prefix; name << prefix;
if (slot >= 0) if (slot >= 0)
{ {
name.AppendFormat("%d.zds" SAVEGAME_EXT, slot); name.AppendFormat("%d." SAVEGAME_EXT, slot);
} }
return name; return name;
} }
@ -2166,6 +2169,7 @@ static void PutSavePic (FileWriter *file, int width, int height)
void G_DoSaveGame (bool okForQuicksave, FString filename, const char *description) void G_DoSaveGame (bool okForQuicksave, FString filename, const char *description)
{ {
TArray<FCompressedBuffer> savegame_content; TArray<FCompressedBuffer> savegame_content;
TArray<FString> savegame_filenames;
char buf[100]; char buf[100];
@ -2203,9 +2207,10 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
M_AppendPNGText(&savepic, "Current Map", level.MapName); M_AppendPNGText(&savepic, "Current Map", level.MapName);
M_FinishPNG(&savepic); M_FinishPNG(&savepic);
int ver = SAVEVER;
savegameinfo.AddString("Software", buf) savegameinfo.AddString("Software", buf)
.AddString("Engine", GAMESIG) .AddString("Engine", GAMESIG)
.AddString("Save Version", SAVESIG) ("Save Version", ver)
.AddString("Title", description) .AddString("Title", description)
.AddString("Current Map", level.MapName); .AddString("Current Map", level.MapName);
@ -2232,17 +2237,36 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
FRandom::StaticWriteRNGState(savegameglobals); FRandom::StaticWriteRNGState(savegameglobals);
P_WriteACSDefereds(savegameglobals); P_WriteACSDefereds(savegameglobals);
P_WriteACSVars(savegameglobals); P_WriteACSVars(savegameglobals);
G_WriteVisited(savegameglobals);
if (NextSkill != -1) if (NextSkill != -1)
{ {
savegameglobals("nextskill", NextSkill); savegameglobals("nextskill", NextSkill);
} }
//G_WriteSnapshots (stdfile); auto picdata = savepic.GetBuffer();
FCompressedBuffer bufpng = { picdata->Size(), picdata->Size(), METHOD_STORED, 0, crc32(0, &(*picdata)[0], picdata->Size()), (char*)&(*picdata)[0] };
savegame_content.Push(bufpng);
savegame_filenames.Push("savepic.png");
savegame_content.Push(savegameinfo.GetCompressedOutput());
savegame_filenames.Push("info.json");
savegame_content.Push(savegameglobals.GetCompressedOutput());
savegame_filenames.Push("globals.json");
G_WriteSnapshots (savegame_filenames, savegame_content);
WriteZip(filename, savegame_filenames, savegame_content);
M_NotifyNewSave (filename.GetChars(), description, okForQuicksave); M_NotifyNewSave (filename.GetChars(), description, okForQuicksave);
// delete the JSON buffers we created just above. Everything else will
// either still be needed or taken care of automatically.
delete[] savegame_content[1].mBuffer;
delete[] savegame_content[2].mBuffer;
// Check whether the file is ok. (todo when new format is ready) // Check whether the file is ok. (todo when new format is ready)
bool success = true; bool success = true;
if (success) if (success)
@ -2252,6 +2276,8 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
} }
else Printf(PRINT_HIGH, "Save failed\n"); else Printf(PRINT_HIGH, "Save failed\n");
FResourceFile *test = FResourceFile::OpenResourceFile(filename, nullptr);
BackupSaveName = filename; BackupSaveName = filename;
// We don't need the snapshot any longer. // We don't need the snapshot any longer.

View file

@ -1487,8 +1487,6 @@ void G_SnapshotLevel ()
if (level.info->isValid()) if (level.info->isValid())
{ {
level.info->snapshotVer = SAVEVER;
FSerializer arc; FSerializer arc;
if (arc.OpenWriter()) if (arc.OpenWriter())
@ -1514,7 +1512,6 @@ void G_UnSnapshotLevel (bool hubLoad)
if (level.info->isValid()) if (level.info->isValid())
{ {
SaveVersion = level.info->snapshotVer;
FSerializer arc; FSerializer arc;
if (!arc.OpenReader(&level.info->Snapshot)) return; if (!arc.OpenReader(&level.info->Snapshot)) return;
@ -1563,83 +1560,68 @@ void G_UnSnapshotLevel (bool hubLoad)
// //
//========================================================================== //==========================================================================
static void writeSnapShot (FArchive &arc, level_info_t *i) void G_WriteSnapshots(TArray<FString> &filenames, TArray<FCompressedBuffer> &buffers)
{
arc << i->snapshotVer << i->MapName;
//i->snapshot->Serialize (arc);
}
//==========================================================================
//
//
//==========================================================================
void G_WriteSnapshots (FILE *file)
{ {
unsigned int i; unsigned int i;
FString filename;
#if 0
for (i = 0; i < wadlevelinfos.Size(); i++) for (i = 0; i < wadlevelinfos.Size(); i++)
{ {
if (wadlevelinfos[i].snapshot) if (wadlevelinfos[i].Snapshot.mCompressedSize > 0)
{ {
FPNGChunkArchive arc (file, SNAP_ID); filename << wadlevelinfos[i].MapName << ".json";
writeSnapShot (arc, (level_info_t *)&wadlevelinfos[i]); filename.ToLower();
filenames.Push(filename);
buffers.Push(wadlevelinfos[i].Snapshot);
} }
} }
if (TheDefaultLevelInfo.snapshot != NULL) if (TheDefaultLevelInfo.Snapshot.mCompressedSize > 0)
{ {
FPNGChunkArchive arc (file, DSNP_ID); filename << TheDefaultLevelInfo.MapName << ".json";
writeSnapShot(arc, &TheDefaultLevelInfo); filename.ToLower();
filenames.Push(filename);
buffers.Push(TheDefaultLevelInfo.Snapshot);
}
} }
#endif
FPNGChunkArchive *arc = NULL; //==========================================================================
//
//
//==========================================================================
void G_WriteVisited(FSerializer &arc)
{
if (arc.BeginArray("visited"))
{
// Write out which levels have been visited // Write out which levels have been visited
for (i = 0; i < wadlevelinfos.Size(); ++i) for (auto & wi : wadlevelinfos)
{ {
if (wadlevelinfos[i].flags & LEVEL_VISITED) if (wi.flags & LEVEL_VISITED)
{ {
if (arc == NULL) arc.AddString(nullptr, wi.MapName);
{
arc = new FPNGChunkArchive (file, VIST_ID);
}
(*arc) << wadlevelinfos[i].MapName;
} }
} }
arc.EndArray();
if (arc != NULL)
{
FString empty = "";
(*arc) << empty;
delete arc;
} }
// Store player classes to be used when spawning a random class // Store player classes to be used when spawning a random class
if (multiplayer) if (multiplayer)
{ {
FPNGChunkArchive arc2 (file, RCLS_ID); arc.Array("randomclasses", SinglePlayerClass, MAXPLAYERS);
for (i = 0; i < MAXPLAYERS; ++i)
{
SBYTE cnum = SinglePlayerClass[i];
arc2 << cnum;
}
} }
// Store player classes that are currently in use if (arc.BeginObject("playerclasses"))
FPNGChunkArchive arc3 (file, PCLS_ID); {
for (i = 0; i < MAXPLAYERS; ++i) for (int i = 0; i < MAXPLAYERS; ++i)
{ {
BYTE pnum;
if (playeringame[i]) if (playeringame[i])
{ {
pnum = i; FString key;
arc3 << pnum; key.Format("%d", i);
arc3.UserWriteClass (players[i].cls); arc(key, players[i].cls);
} }
pnum = 255; }
arc3 << pnum; arc.EndObject();
} }
} }
@ -1665,7 +1647,6 @@ void G_ReadSnapshots (PNGHandle *png)
arc << snapver; arc << snapver;
arc << MapName; arc << MapName;
i = FindLevelInfo (MapName); i = FindLevelInfo (MapName);
i->snapshotVer = snapver;
#if 0 #if 0
i->snapshot = new FCompressedMemFile; i->snapshot = new FCompressedMemFile;
i->snapshot->Serialize (arc); i->snapshot->Serialize (arc);
@ -1681,7 +1662,6 @@ void G_ReadSnapshots (PNGHandle *png)
arc << snapver; arc << snapver;
arc << MapName; arc << MapName;
TheDefaultLevelInfo.snapshotVer = snapver;
#if 0 #if 0
TheDefaultLevelInfo.snapshot = new FCompressedMemFile; TheDefaultLevelInfo.snapshot = new FCompressedMemFile;
TheDefaultLevelInfo.snapshot->Serialize (arc); TheDefaultLevelInfo.snapshot->Serialize (arc);

View file

@ -295,7 +295,6 @@ struct level_info_t
SBYTE WallVertLight, WallHorizLight; SBYTE WallVertLight, WallHorizLight;
int musicorder; int musicorder;
FCompressedBuffer Snapshot; FCompressedBuffer Snapshot;
DWORD snapshotVer;
TArray<acsdefered_t> deferred; TArray<acsdefered_t> deferred;
float skyspeed1; float skyspeed1;
float skyspeed2; float skyspeed2;
@ -535,7 +534,8 @@ void G_SnapshotLevel (void);
void G_UnSnapshotLevel (bool keepPlayers); void G_UnSnapshotLevel (bool keepPlayers);
struct PNGHandle; struct PNGHandle;
void G_ReadSnapshots (PNGHandle *png); void G_ReadSnapshots (PNGHandle *png);
void G_WriteSnapshots (FILE *file); void G_WriteSnapshots (TArray<FString> &, TArray<FCompressedBuffer> &);
void G_WriteVisited(FSerializer &arc);
void G_ClearHubInfo(); void G_ClearHubInfo();
enum ESkillProperty enum ESkillProperty

View file

@ -248,8 +248,7 @@ void level_info_t::Reset()
WallVertLight = +8; WallVertLight = +8;
F1Pic = ""; F1Pic = "";
musicorder = 0; musicorder = 0;
Snapshot = { 0,0,0,0,nullptr }; Snapshot = { 0,0,0,0,0,nullptr };
snapshotVer = 0;
deferred.Clear(); deferred.Clear();
skyspeed1 = skyspeed2 = 0.f; skyspeed1 = skyspeed2 = 0.f;
fadeto = 0; fadeto = 0;

View file

@ -241,7 +241,7 @@ void DLoadSaveMenu::ReadSaveStrings ()
title[SAVESTRINGSIZE] = 0; title[SAVESTRINGSIZE] = 0;
if (NULL != (png = M_VerifyPNG (file))) if (false)//NULL != (png = M_VerifyPNG (file)))
{ {
char *ver = M_GetPNGText (png, "ZDoom Save Version"); char *ver = M_GetPNGText (png, "ZDoom Save Version");
char *engine = M_GetPNGText (png, "Engine"); char *engine = M_GetPNGText (png, "Engine");
@ -251,7 +251,7 @@ void DLoadSaveMenu::ReadSaveStrings ()
{ {
strncpy (title, I_FindName(&c_file), SAVESTRINGSIZE); strncpy (title, I_FindName(&c_file), SAVESTRINGSIZE);
} }
if (strncmp (ver, SAVESIG, 9) == 0 && if (strncmp (ver, "SAVESIG", 9) == 0 &&
atoi (ver+9) >= MINSAVEVER && atoi (ver+9) >= MINSAVEVER &&
engine != NULL) engine != NULL)
{ {

View file

@ -898,6 +898,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
I_Error("Savegame is from a different level"); I_Error("Savegame is from a different level");
} }
} }
arc("saveversion", SaveVersion);
Renderer->StartSerialize(arc); Renderer->StartSerialize(arc);
if (arc.isReading()) if (arc.isReading())

View file

@ -33,6 +33,7 @@
** **
*/ */
#include <time.h>
#include "file_zip.h" #include "file_zip.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "templates.h" #include "templates.h"
@ -265,6 +266,7 @@ bool FZipFile::Open(bool quiet)
lump_p->Flags = LUMPF_ZIPFILE | LUMPFZIP_NEEDFILESTART; lump_p->Flags = LUMPF_ZIPFILE | LUMPFZIP_NEEDFILESTART;
lump_p->Method = BYTE(zip_fh->Method); lump_p->Method = BYTE(zip_fh->Method);
lump_p->GPFlags = zip_fh->Flags; lump_p->GPFlags = zip_fh->Flags;
lump_p->CRC32 = zip_fh->CRC32;
lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize); lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize);
lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset); lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset);
lump_p->CheckEmbedded(); lump_p->CheckEmbedded();
@ -308,10 +310,11 @@ FCompressedBuffer FZipFile::GetRawLump(int lumpnum)
{ {
if ((unsigned)lumpnum >= NumLumps) if ((unsigned)lumpnum >= NumLumps)
{ {
return{ 0,0,0,0,nullptr }; return{ 0,0,0,0,0,nullptr };
} }
FZipLump *lmp = &Lumps[lumpnum]; FZipLump *lmp = &Lumps[lumpnum];
FCompressedBuffer cbuf = { (unsigned)lmp->LumpSize, (unsigned)lmp->CompressedSize, lmp->Method, lmp->GPFlags, new char[lmp->CompressedSize] };
FCompressedBuffer cbuf = { (unsigned)lmp->LumpSize, (unsigned)lmp->CompressedSize, lmp->Method, lmp->GPFlags, lmp->CRC32, new char[lmp->CompressedSize] };
Reader->Seek(lmp->Position, SEEK_SET); Reader->Seek(lmp->Position, SEEK_SET);
Reader->Read(cbuf.mBuffer, lmp->CompressedSize); Reader->Read(cbuf.mBuffer, lmp->CompressedSize);
return cbuf; return cbuf;
@ -426,3 +429,169 @@ FResourceFile *CheckZip(const char *filename, FileReader *file, bool quiet)
//==========================================================================
//
// time_to_dos
//
// Converts time from struct tm to the DOS format used by zip files.
//
//==========================================================================
static void time_to_dos(struct tm *time, unsigned short *dosdate, unsigned short *dostime)
{
if (time == NULL || time->tm_year < 80)
{
*dosdate = *dostime = 0;
}
else
{
*dosdate = LittleShort((time->tm_year - 80) * 512 + (time->tm_mon + 1) * 32 + time->tm_mday);
*dostime = LittleShort(time->tm_hour * 2048 + time->tm_min * 32 + time->tm_sec / 2);
}
}
//==========================================================================
//
// append_to_zip
//
// Write a given file to the zipFile.
//
// zipfile: zip object to be written to
//
// returns: position = success, -1 = error
//
//==========================================================================
int AppendToZip(FILE *zip_file, const char *filename, FCompressedBuffer &content, uint16_t date, uint16_t time)
{
FZipLocalFileHeader local;
int position;
local.Magic = ZIP_LOCALFILE;
local.VersionToExtract[0] = 20;
local.VersionToExtract[1] = 0;
local.Flags = content.mMethod == METHOD_DEFLATE ? LittleShort(2) : LittleShort((uint16_t)content.mZipFlags);
local.Method = LittleShort(content.mMethod);
local.ModDate = date;
local.ModTime = time;
local.CRC32 = content.mCRC32;
local.UncompressedSize = LittleLong(content.mSize);
local.CompressedSize = LittleLong(content.mCompressedSize);
local.NameLength = LittleShort((unsigned short)strlen(filename));
local.ExtraLength = 0;
// Fill in local directory header.
position = (int)ftell(zip_file);
// Write out the header, file name, and file data.
if (fwrite(&local, sizeof(local), 1, zip_file) != 1 ||
fwrite(filename, strlen(filename), 1, zip_file) != 1 ||
fwrite(content.mBuffer, 1, content.mCompressedSize, zip_file) != content.mCompressedSize)
{
return -1;
}
return position;
}
//==========================================================================
//
// write_central_dir
//
// Writes the central directory entry for a file.
//
//==========================================================================
int AppendCentralDirectory(FILE *zip_file, const char *filename, FCompressedBuffer &content, uint16_t date, uint16_t time, int position)
{
FZipCentralDirectoryInfo dir;
dir.Magic = ZIP_CENTRALFILE;
dir.VersionMadeBy[0] = 20;
dir.VersionMadeBy[1] = 0;
dir.VersionToExtract[0] = 20;
dir.VersionToExtract[1] = 0;
dir.Flags = content.mMethod == METHOD_DEFLATE ? LittleShort(2) : LittleShort((uint16_t)content.mZipFlags);
dir.Method = LittleShort(content.mMethod);
dir.ModTime = time;
dir.ModDate = date;
dir.CRC32 = content.mCRC32;
dir.CompressedSize = LittleLong(content.mCompressedSize);
dir.UncompressedSize = LittleLong(content.mSize);
dir.NameLength = LittleShort((unsigned short)strlen(filename));
dir.ExtraLength = 0;
dir.CommentLength = 0;
dir.StartingDiskNumber = 0;
dir.InternalAttributes = 0;
dir.ExternalAttributes = 0;
dir.LocalHeaderOffset = LittleLong(position);
if (fwrite(&dir, sizeof(dir), 1, zip_file) != 1 ||
fwrite(filename, strlen(filename), 1, zip_file) != 1)
{
return -1;
}
return 0;
}
bool WriteZip(const char *filename, TArray<FString> &filenames, TArray<FCompressedBuffer> &content)
{
// try to determine local time
struct tm *ltime;
time_t ttime;
uint16_t mydate, mytime;
ttime = time(nullptr);
ltime = localtime(&ttime);
time_to_dos(ltime, &mydate, &mytime);
TArray<int> positions;
if (filenames.Size() != content.Size()) return false;
FILE *f = fopen(filename, "wb");
if (f != nullptr)
{
for (unsigned i = 0; i < filenames.Size(); i++)
{
int pos = AppendToZip(f, filenames[i], content[i], mydate, mytime);
if (pos == -1)
{
fclose(f);
remove(filename);
return false;
}
positions.Push(pos);
}
int dirofs = (int)ftell(f);
for (unsigned i = 0; i < filenames.Size(); i++)
{
if (AppendCentralDirectory(f, filenames[i], content[i], mydate, mytime, positions[i]) < 0)
{
fclose(f);
remove(filename);
return false;
}
}
// Write the directory terminator.
FZipEndOfCentralDirectory dirend;
dirend.Magic = ZIP_ENDOFDIR;
dirend.DiskNumber = 0;
dirend.FirstDisk = 0;
dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort(filenames.Size());
dirend.DirectoryOffset = dirofs;
dirend.DirectorySize = LittleLong(ftell(f) - dirofs);
dirend.ZipCommentLength = 0;
if (fwrite(&dirend, sizeof(dirend), 1, f) != 1)
{
fclose(f);
remove(filename);
return false;
}
fclose(f);
return true;
}
return false;
}

View file

@ -10,6 +10,7 @@ struct FCompressedBuffer
unsigned mCompressedSize; unsigned mCompressedSize;
int mMethod; int mMethod;
int mZipFlags; int mZipFlags;
unsigned mCRC32;
char *mBuffer; char *mBuffer;
bool Decompress(char *destbuffer); bool Decompress(char *destbuffer);
@ -41,6 +42,7 @@ struct FZipLump : public FResourceLump
BYTE Method; BYTE Method;
int CompressedSize; int CompressedSize;
int Position; int Position;
unsigned CRC32;
virtual FileReader *GetReader(); virtual FileReader *GetReader();
virtual int FillCache(); virtual int FillCache();

View file

@ -690,11 +690,12 @@ const char *FSerializer::GetOutput(unsigned *len)
FCompressedBuffer FSerializer::GetCompressedOutput() FCompressedBuffer FSerializer::GetCompressedOutput()
{ {
if (isReading()) return{ 0,0,0,0,nullptr }; if (isReading()) return{ 0,0,0,0,0,nullptr };
FCompressedBuffer buff; FCompressedBuffer buff;
EndObject(); EndObject();
buff.mSize = (unsigned)w->mOutString.GetSize(); buff.mSize = (unsigned)w->mOutString.GetSize();
buff.mZipFlags = 0; buff.mZipFlags = 0;
buff.mCRC32 = crc32(0, (const Bytef*)w->mOutString.GetString(), buff.mSize);
uint8_t *compressbuf = new uint8_t[buff.mSize+1]; uint8_t *compressbuf = new uint8_t[buff.mSize+1];
@ -731,6 +732,7 @@ FCompressedBuffer FSerializer::GetCompressedOutput()
buff.mMethod = METHOD_DEFLATE; buff.mMethod = METHOD_DEFLATE;
memcpy(buff.mBuffer, compressbuf, buff.mCompressedSize); memcpy(buff.mBuffer, compressbuf, buff.mCompressedSize);
delete[] compressbuf; delete[] compressbuf;
return buff;
} }
error: error:

View file

@ -58,7 +58,7 @@ public:
{ {
Close(); Close();
} }
bool OpenWriter(); bool OpenWriter(bool randomaccess = true);
bool OpenReader(const char *buffer, size_t length); bool OpenReader(const char *buffer, size_t length);
bool OpenReader(FCompressedBuffer *input); bool OpenReader(FCompressedBuffer *input);
void Close(); void Close();

View file

@ -527,6 +527,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, OneLevel &l, OneLevel
("levelname", l.Levelname) ("levelname", l.Levelname)
.EndObject(); .EndObject();
} }
return arc;
} }
void STAT_Serialize(FSerializer &arc) void STAT_Serialize(FSerializer &arc)

View file

@ -81,10 +81,6 @@ const char *GetVersionString();
// SVN revision ever got. // SVN revision ever got.
#define SAVEVER 4550 #define SAVEVER 4550
#define SAVEVERSTRINGIFY2(x) #x
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
#define SAVESIG "ZDOOMSAVE" SAVEVERSTRINGIFY(SAVEVER)
// This is so that derivates can use the same savegame versions without worrying about engine compatibility // This is so that derivates can use the same savegame versions without worrying about engine compatibility
#define GAMESIG "ZDOOM" #define GAMESIG "ZDOOM"
#define BASEWAD "zdoom.pk3" #define BASEWAD "zdoom.pk3"