mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-22 20:21:26 +00:00
- implemented saving of new format savegames as zips. The code for that was adapted from zipdir.c.
This commit is contained in:
parent
810ef8f775
commit
ac3c00883d
15 changed files with 253 additions and 104 deletions
|
@ -2580,7 +2580,7 @@ void D_DoomMain (void)
|
|||
{
|
||||
FString file(v);
|
||||
FixPathSeperator (file);
|
||||
DefaultExtension (file, ".zds" SAVEGAME_EXT);
|
||||
DefaultExtension (file, "." SAVEGAME_EXT);
|
||||
G_LoadGame (file);
|
||||
}
|
||||
|
||||
|
|
|
@ -962,32 +962,6 @@ PClass *FArchive::ReadStoredClass (const PClass *wanttype)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -152,7 +152,6 @@ virtual void Read (void *mem, unsigned int len);
|
|||
void WriteCount (DWORD count);
|
||||
DWORD ReadCount ();
|
||||
|
||||
void UserWriteClass (PClass *info);
|
||||
void UserReadClass (PClass *&info);
|
||||
template<typename T> void UserReadClass(T *&info)
|
||||
{
|
||||
|
|
|
@ -85,6 +85,8 @@
|
|||
#include "p_spec.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "serializer.h"
|
||||
#include "w_zip.h"
|
||||
#include "resourcefiles/resourcefile.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
|
@ -112,6 +114,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
|
|||
void G_DoAutoSave ();
|
||||
|
||||
void STAT_Serialize(FSerializer &file);
|
||||
bool WriteZip(const char *filename, TArray<FString> &filenames, TArray<FCompressedBuffer> &content);
|
||||
|
||||
FIntCVar gameskill ("skill", 2, CVAR_SERVERINFO|CVAR_LATCH);
|
||||
CVAR (Int, deathmatch, 0, CVAR_SERVERINFO|CVAR_LATCH);
|
||||
|
@ -1886,7 +1889,7 @@ void G_DoLoadGame ()
|
|||
|
||||
SaveVersion = 0;
|
||||
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)
|
||||
{
|
||||
delete png;
|
||||
|
@ -2045,7 +2048,7 @@ FString G_BuildSaveName (const char *prefix, int slot)
|
|||
name << prefix;
|
||||
if (slot >= 0)
|
||||
{
|
||||
name.AppendFormat("%d.zds" SAVEGAME_EXT, slot);
|
||||
name.AppendFormat("%d." SAVEGAME_EXT, slot);
|
||||
}
|
||||
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)
|
||||
{
|
||||
TArray<FCompressedBuffer> savegame_content;
|
||||
TArray<FString> savegame_filenames;
|
||||
|
||||
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_FinishPNG(&savepic);
|
||||
|
||||
int ver = SAVEVER;
|
||||
savegameinfo.AddString("Software", buf)
|
||||
.AddString("Engine", GAMESIG)
|
||||
.AddString("Save Version", SAVESIG)
|
||||
("Save Version", ver)
|
||||
.AddString("Title", description)
|
||||
.AddString("Current Map", level.MapName);
|
||||
|
||||
|
@ -2232,17 +2237,36 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
|
|||
FRandom::StaticWriteRNGState(savegameglobals);
|
||||
P_WriteACSDefereds(savegameglobals);
|
||||
P_WriteACSVars(savegameglobals);
|
||||
G_WriteVisited(savegameglobals);
|
||||
|
||||
|
||||
if (NextSkill != -1)
|
||||
{
|
||||
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);
|
||||
|
||||
// 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)
|
||||
bool success = true;
|
||||
if (success)
|
||||
|
@ -2252,6 +2276,8 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
|
|||
}
|
||||
else Printf(PRINT_HIGH, "Save failed\n");
|
||||
|
||||
FResourceFile *test = FResourceFile::OpenResourceFile(filename, nullptr);
|
||||
|
||||
BackupSaveName = filename;
|
||||
|
||||
// We don't need the snapshot any longer.
|
||||
|
|
|
@ -1487,8 +1487,6 @@ void G_SnapshotLevel ()
|
|||
|
||||
if (level.info->isValid())
|
||||
{
|
||||
level.info->snapshotVer = SAVEVER;
|
||||
|
||||
FSerializer arc;
|
||||
|
||||
if (arc.OpenWriter())
|
||||
|
@ -1514,7 +1512,6 @@ void G_UnSnapshotLevel (bool hubLoad)
|
|||
|
||||
if (level.info->isValid())
|
||||
{
|
||||
SaveVersion = level.info->snapshotVer;
|
||||
FSerializer arc;
|
||||
if (!arc.OpenReader(&level.info->Snapshot)) return;
|
||||
|
||||
|
@ -1563,10 +1560,28 @@ 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);
|
||||
unsigned int i;
|
||||
FString filename;
|
||||
|
||||
for (i = 0; i < wadlevelinfos.Size(); i++)
|
||||
{
|
||||
if (wadlevelinfos[i].Snapshot.mCompressedSize > 0)
|
||||
{
|
||||
filename << wadlevelinfos[i].MapName << ".json";
|
||||
filename.ToLower();
|
||||
filenames.Push(filename);
|
||||
buffers.Push(wadlevelinfos[i].Snapshot);
|
||||
}
|
||||
}
|
||||
if (TheDefaultLevelInfo.Snapshot.mCompressedSize > 0)
|
||||
{
|
||||
filename << TheDefaultLevelInfo.MapName << ".json";
|
||||
filename.ToLower();
|
||||
filenames.Push(filename);
|
||||
buffers.Push(TheDefaultLevelInfo.Snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1574,72 +1589,39 @@ static void writeSnapShot (FArchive &arc, level_info_t *i)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void G_WriteSnapshots (FILE *file)
|
||||
void G_WriteVisited(FSerializer &arc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < wadlevelinfos.Size(); i++)
|
||||
if (arc.BeginArray("visited"))
|
||||
{
|
||||
if (wadlevelinfos[i].snapshot)
|
||||
// Write out which levels have been visited
|
||||
for (auto & wi : wadlevelinfos)
|
||||
{
|
||||
FPNGChunkArchive arc (file, SNAP_ID);
|
||||
writeSnapShot (arc, (level_info_t *)&wadlevelinfos[i]);
|
||||
}
|
||||
}
|
||||
if (TheDefaultLevelInfo.snapshot != NULL)
|
||||
{
|
||||
FPNGChunkArchive arc (file, DSNP_ID);
|
||||
writeSnapShot(arc, &TheDefaultLevelInfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
FPNGChunkArchive *arc = NULL;
|
||||
|
||||
// Write out which levels have been visited
|
||||
for (i = 0; i < wadlevelinfos.Size(); ++i)
|
||||
{
|
||||
if (wadlevelinfos[i].flags & LEVEL_VISITED)
|
||||
{
|
||||
if (arc == NULL)
|
||||
if (wi.flags & LEVEL_VISITED)
|
||||
{
|
||||
arc = new FPNGChunkArchive (file, VIST_ID);
|
||||
arc.AddString(nullptr, wi.MapName);
|
||||
}
|
||||
(*arc) << wadlevelinfos[i].MapName;
|
||||
}
|
||||
}
|
||||
|
||||
if (arc != NULL)
|
||||
{
|
||||
FString empty = "";
|
||||
(*arc) << empty;
|
||||
delete arc;
|
||||
arc.EndArray();
|
||||
}
|
||||
|
||||
// Store player classes to be used when spawning a random class
|
||||
if (multiplayer)
|
||||
{
|
||||
FPNGChunkArchive arc2 (file, RCLS_ID);
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
SBYTE cnum = SinglePlayerClass[i];
|
||||
arc2 << cnum;
|
||||
}
|
||||
arc.Array("randomclasses", SinglePlayerClass, MAXPLAYERS);
|
||||
}
|
||||
|
||||
// Store player classes that are currently in use
|
||||
FPNGChunkArchive arc3 (file, PCLS_ID);
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
if (arc.BeginObject("playerclasses"))
|
||||
{
|
||||
BYTE pnum;
|
||||
if (playeringame[i])
|
||||
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
pnum = i;
|
||||
arc3 << pnum;
|
||||
arc3.UserWriteClass (players[i].cls);
|
||||
if (playeringame[i])
|
||||
{
|
||||
FString key;
|
||||
key.Format("%d", i);
|
||||
arc(key, players[i].cls);
|
||||
}
|
||||
}
|
||||
pnum = 255;
|
||||
arc3 << pnum;
|
||||
arc.EndObject();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1665,7 +1647,6 @@ void G_ReadSnapshots (PNGHandle *png)
|
|||
arc << snapver;
|
||||
arc << MapName;
|
||||
i = FindLevelInfo (MapName);
|
||||
i->snapshotVer = snapver;
|
||||
#if 0
|
||||
i->snapshot = new FCompressedMemFile;
|
||||
i->snapshot->Serialize (arc);
|
||||
|
@ -1681,7 +1662,6 @@ void G_ReadSnapshots (PNGHandle *png)
|
|||
|
||||
arc << snapver;
|
||||
arc << MapName;
|
||||
TheDefaultLevelInfo.snapshotVer = snapver;
|
||||
#if 0
|
||||
TheDefaultLevelInfo.snapshot = new FCompressedMemFile;
|
||||
TheDefaultLevelInfo.snapshot->Serialize (arc);
|
||||
|
|
|
@ -295,7 +295,6 @@ struct level_info_t
|
|||
SBYTE WallVertLight, WallHorizLight;
|
||||
int musicorder;
|
||||
FCompressedBuffer Snapshot;
|
||||
DWORD snapshotVer;
|
||||
TArray<acsdefered_t> deferred;
|
||||
float skyspeed1;
|
||||
float skyspeed2;
|
||||
|
@ -535,7 +534,8 @@ void G_SnapshotLevel (void);
|
|||
void G_UnSnapshotLevel (bool keepPlayers);
|
||||
struct PNGHandle;
|
||||
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();
|
||||
|
||||
enum ESkillProperty
|
||||
|
|
|
@ -248,8 +248,7 @@ void level_info_t::Reset()
|
|||
WallVertLight = +8;
|
||||
F1Pic = "";
|
||||
musicorder = 0;
|
||||
Snapshot = { 0,0,0,0,nullptr };
|
||||
snapshotVer = 0;
|
||||
Snapshot = { 0,0,0,0,0,nullptr };
|
||||
deferred.Clear();
|
||||
skyspeed1 = skyspeed2 = 0.f;
|
||||
fadeto = 0;
|
||||
|
|
|
@ -241,7 +241,7 @@ void DLoadSaveMenu::ReadSaveStrings ()
|
|||
|
||||
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 *engine = M_GetPNGText (png, "Engine");
|
||||
|
@ -251,7 +251,7 @@ void DLoadSaveMenu::ReadSaveStrings ()
|
|||
{
|
||||
strncpy (title, I_FindName(&c_file), SAVESTRINGSIZE);
|
||||
}
|
||||
if (strncmp (ver, SAVESIG, 9) == 0 &&
|
||||
if (strncmp (ver, "SAVESIG", 9) == 0 &&
|
||||
atoi (ver+9) >= MINSAVEVER &&
|
||||
engine != NULL)
|
||||
{
|
||||
|
|
|
@ -898,6 +898,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
|
|||
I_Error("Savegame is from a different level");
|
||||
}
|
||||
}
|
||||
arc("saveversion", SaveVersion);
|
||||
|
||||
Renderer->StartSerialize(arc);
|
||||
if (arc.isReading())
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
**
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include "file_zip.h"
|
||||
#include "cmdlib.h"
|
||||
#include "templates.h"
|
||||
|
@ -265,6 +266,7 @@ bool FZipFile::Open(bool quiet)
|
|||
lump_p->Flags = LUMPF_ZIPFILE | LUMPFZIP_NEEDFILESTART;
|
||||
lump_p->Method = BYTE(zip_fh->Method);
|
||||
lump_p->GPFlags = zip_fh->Flags;
|
||||
lump_p->CRC32 = zip_fh->CRC32;
|
||||
lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize);
|
||||
lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset);
|
||||
lump_p->CheckEmbedded();
|
||||
|
@ -308,10 +310,11 @@ FCompressedBuffer FZipFile::GetRawLump(int lumpnum)
|
|||
{
|
||||
if ((unsigned)lumpnum >= NumLumps)
|
||||
{
|
||||
return{ 0,0,0,0,nullptr };
|
||||
return{ 0,0,0,0,0,nullptr };
|
||||
}
|
||||
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->Read(cbuf.mBuffer, lmp->CompressedSize);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ struct FCompressedBuffer
|
|||
unsigned mCompressedSize;
|
||||
int mMethod;
|
||||
int mZipFlags;
|
||||
unsigned mCRC32;
|
||||
char *mBuffer;
|
||||
|
||||
bool Decompress(char *destbuffer);
|
||||
|
@ -41,6 +42,7 @@ struct FZipLump : public FResourceLump
|
|||
BYTE Method;
|
||||
int CompressedSize;
|
||||
int Position;
|
||||
unsigned CRC32;
|
||||
|
||||
virtual FileReader *GetReader();
|
||||
virtual int FillCache();
|
||||
|
|
|
@ -690,11 +690,12 @@ const char *FSerializer::GetOutput(unsigned *len)
|
|||
|
||||
FCompressedBuffer FSerializer::GetCompressedOutput()
|
||||
{
|
||||
if (isReading()) return{ 0,0,0,0,nullptr };
|
||||
if (isReading()) return{ 0,0,0,0,0,nullptr };
|
||||
FCompressedBuffer buff;
|
||||
EndObject();
|
||||
buff.mSize = (unsigned)w->mOutString.GetSize();
|
||||
buff.mZipFlags = 0;
|
||||
buff.mCRC32 = crc32(0, (const Bytef*)w->mOutString.GetString(), buff.mSize);
|
||||
|
||||
uint8_t *compressbuf = new uint8_t[buff.mSize+1];
|
||||
|
||||
|
@ -731,6 +732,7 @@ FCompressedBuffer FSerializer::GetCompressedOutput()
|
|||
buff.mMethod = METHOD_DEFLATE;
|
||||
memcpy(buff.mBuffer, compressbuf, buff.mCompressedSize);
|
||||
delete[] compressbuf;
|
||||
return buff;
|
||||
}
|
||||
|
||||
error:
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
{
|
||||
Close();
|
||||
}
|
||||
bool OpenWriter();
|
||||
bool OpenWriter(bool randomaccess = true);
|
||||
bool OpenReader(const char *buffer, size_t length);
|
||||
bool OpenReader(FCompressedBuffer *input);
|
||||
void Close();
|
||||
|
|
|
@ -527,6 +527,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, OneLevel &l, OneLevel
|
|||
("levelname", l.Levelname)
|
||||
.EndObject();
|
||||
}
|
||||
return arc;
|
||||
}
|
||||
|
||||
void STAT_Serialize(FSerializer &arc)
|
||||
|
|
|
@ -81,10 +81,6 @@ const char *GetVersionString();
|
|||
// SVN revision ever got.
|
||||
#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
|
||||
#define GAMESIG "ZDOOM"
|
||||
#define BASEWAD "zdoom.pk3"
|
||||
|
|
Loading…
Reference in a new issue