From 88bf0561767cfd070b964abca200e41ec43d6dce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 6 Nov 2019 12:29:08 +0100 Subject: [PATCH] - added a class for cleaner savegame writing --- source/common/compositesaveame.h | 19 ++++ source/common/compositesavegame.cpp | 131 ++++++++++++++++++++++++++++ source/duke3d/src/gamevars.cpp | 2 + source/duke3d/src/savegame.cpp | 11 --- source/duke3d/src/savegame.h | 1 + 5 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 source/common/compositesaveame.h create mode 100644 source/common/compositesavegame.cpp diff --git a/source/common/compositesaveame.h b/source/common/compositesaveame.h new file mode 100644 index 000000000..c76e59273 --- /dev/null +++ b/source/common/compositesaveame.h @@ -0,0 +1,19 @@ +#pragma once + +#include "files.h" +#include "zstring.h" +#include "tarray.h" + +class CompositeSavegameWriter +{ + TDeletingArray subfiles; + TArray subfilenames; + TArray isCompressed; + + FCompressedBuffer CompressElement(BufferWriter *element, bool compress); +public: + + FileWriter &NewEleemnt(const char *filename, bool compress = true); + bool WriteToFile(const char *filename); +}; + diff --git a/source/common/compositesavegame.cpp b/source/common/compositesavegame.cpp new file mode 100644 index 000000000..b306466b3 --- /dev/null +++ b/source/common/compositesavegame.cpp @@ -0,0 +1,131 @@ + +/* +** compositesavegame.cpp +** Container for savegame files with multiple sub-content +** +**--------------------------------------------------------------------------- +** Copyright 2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OFf +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include "compositesavegame.h" +#include "file_zip.h" +#include "resourcefiles.h" + + +bool WriteZip(const char *filename, TArray &filenames, TArray &content); + + +FileWriter &CompositeSavegameWriter::NewEleemnt(const char *filename, bool compress) +{ + subfilenames.Push(filename); + isCompressed.Push(compress); + auto bwr = new BufferWriter; + subfiles.Push(bwr); + return *bwr; +} + +FCompressedBuffer CompositeSavegameWriter::CompressElement(BufferWriter *bw, bool compress) +{ + FCompressedBuffer buff; + auto buffer =bw->GetBuffer(); + buff.mSize = buffer->Size(); + buff.mZipFlags = 0; + buff.mCRC32 = crc32(0, (const Bytef*)buffer->Data(), buffer->Size()); + + uint8_t *compressbuf = new uint8_t[buff.mSize+1]; + + z_stream stream; + int err; + + stream.next_in = (Bytef *)buffer->Data(); + stream.avail_in = buff.mSize; + stream.next_out = (Bytef*)compressbuf; + stream.avail_out = buff.mSize; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + if (!compress) goto error; + + // create output in zip-compatible form as required by FCompressedBuffer + err = deflateInit2(&stream, 8, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY); + if (err != Z_OK) + { + goto error; + } + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) + { + deflateEnd(&stream); + goto error; + } + buff.mCompressedSize = stream.total_out; + + err = deflateEnd(&stream); + if (err == Z_OK) + { + buff.mBuffer = new char[buff.mCompressedSize]; + buff.mMethod = METHOD_DEFLATE; + memcpy(buff.mBuffer, compressbuf, buff.mCompressedSize); + delete[] compressbuf; + return buff; + } + +error: + memcpy(compressbuf, buffer->Data(), buff.mSize + 1); + buff.mCompressedSize = buff.mSize; + buff.mMethod = METHOD_STORED; + return buff; + +} + +bool CompositeSavegameWriter::WriteToFile(const char *filename) +{ + TArray compressed(subfiles.Size(), 1); + for (unsigned i = 0; i < subfiles.Size(); i++) + { + compressed[i] = CompressElement(subfiles[i], isCompressed[i]); + } + + if (WriteZip(filename, subfilenames, compressed)) + { + // Check whether the file is ok by trying to open it. + FResourceFile *test = FResourceFile::OpenResourceFile(filename, true); + if (test != nullptr) + { + delete test; + return true; + } + } + + return false; +} + diff --git a/source/duke3d/src/gamevars.cpp b/source/duke3d/src/gamevars.cpp index 32986dbb7..2903cd639 100644 --- a/source/duke3d/src/gamevars.cpp +++ b/source/duke3d/src/gamevars.cpp @@ -114,6 +114,7 @@ void Gv_Clear(void) hash_free(i); } +// Note that this entire function is totally architecture dependent and needs to be fixed (which won't be easy...) int Gv_ReadSave(FileReader &kFile) { char tbuf[12]; @@ -234,6 +235,7 @@ corrupt: return -7; } +// Note that this entire function is totally architecture dependent and needs to be fixed (which won't be easy...) void Gv_WriteSave(buildvfs_FILE fil) { // AddLog("Saving Game Vars to File"); diff --git a/source/duke3d/src/savegame.cpp b/source/duke3d/src/savegame.cpp index b8569a323..8a3876140 100644 --- a/source/duke3d/src/savegame.cpp +++ b/source/duke3d/src/savegame.cpp @@ -313,17 +313,6 @@ int32_t G_LoadSaveHeaderNew(char const *fn, savehead_t *saveh) OSD_Printf("G_LoadSaveHeaderNew(): failed reading screenshot in \"%s\"\n", fn); goto corrupt; } - -#if 0 - // debug code to dump the screenshot - char scrbuf[BMAX_PATH]; - if (G_ModDirSnprintf(scrbuf, sizeof(scrbuf), "%s.raw", fn) == 0) - { - buildvfs_FILE scrfil = buildvfs_fopen_write(scrbuf); - buildvfs_fwrite(tileData(TILE_LOADSHOT), 320, 200, scrfil); - buildvfs_fclose(scrfil); - } -#endif } else { diff --git a/source/duke3d/src/savegame.h b/source/duke3d/src/savegame.h index d9fc62985..4f5133572 100644 --- a/source/duke3d/src/savegame.h +++ b/source/duke3d/src/savegame.h @@ -154,6 +154,7 @@ enum void G_Util_PtrToIdx(void *ptr, int32_t count, const void *base, int32_t mode); void G_Util_PtrToIdx2(void *ptr, int32_t count, size_t stride, const void *base, int32_t mode); + END_DUKE_NS #endif