mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-25 00:04:49 +02:00
Save states using gzip, load either way.
Could implement an option to save states uncompressed. There's a small performance hit. Test files were 8% - 14% the size, but these are just from menus/etc.
This commit is contained in:
+7
-7
@@ -369,7 +369,7 @@ public:
|
||||
if (!File::Exists(_rFilename))
|
||||
return false;
|
||||
|
||||
// Check file size
|
||||
// Check file size - most probably it can't compress THAT well.
|
||||
const u64 fileSize = File::GetSize(_rFilename);
|
||||
static const u64 headerSize = sizeof(SChunkHeader);
|
||||
if (fileSize < headerSize)
|
||||
@@ -378,7 +378,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
File::IOFile pFile(_rFilename, "rb");
|
||||
File::IOFile pFile(_rFilename, "rb", File::METHOD_GZIP);
|
||||
if (!pFile)
|
||||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Can't open file for reading");
|
||||
@@ -402,11 +402,11 @@ public:
|
||||
}
|
||||
|
||||
// get size
|
||||
const int sz = (int)(fileSize - headerSize);
|
||||
if (header.ExpectedSize != sz)
|
||||
const int sz = header.ExpectedSize;
|
||||
if (sz > 128 * 1024 * 1024)
|
||||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d",
|
||||
sz, header.ExpectedSize);
|
||||
ERROR_LOG(COMMON,"ChunkReader: File too large, got %d bytes",
|
||||
header.ExpectedSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -432,7 +432,7 @@ public:
|
||||
static bool Save(const std::string& _rFilename, int _Revision, T& _class)
|
||||
{
|
||||
INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str());
|
||||
File::IOFile pFile(_rFilename, "wb");
|
||||
File::IOFile pFile(_rFilename, "wb9", File::METHOD_GZIP);
|
||||
if (!pFile)
|
||||
{
|
||||
ERROR_LOG(COMMON,"ChunkReader: Error opening file for write");
|
||||
|
||||
+63
-14
@@ -767,17 +767,17 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str)
|
||||
}
|
||||
|
||||
IOFile::IOFile()
|
||||
: m_file(NULL), m_good(true)
|
||||
: m_file(NULL), m_zFile(NULL), m_good(true)
|
||||
{}
|
||||
|
||||
IOFile::IOFile(std::FILE* file)
|
||||
: m_file(file), m_good(true)
|
||||
: m_file(file), m_zFile(NULL), m_good(true)
|
||||
{}
|
||||
|
||||
IOFile::IOFile(const std::string& filename, const char openmode[])
|
||||
: m_file(NULL), m_good(true)
|
||||
IOFile::IOFile(const std::string& filename, const char openmode[], IOFileMethod method)
|
||||
: m_file(NULL), m_zFile(NULL), m_good(true), m_method(method)
|
||||
{
|
||||
Open(filename, openmode);
|
||||
Open(filename, openmode, method);
|
||||
}
|
||||
|
||||
IOFile::~IOFile()
|
||||
@@ -785,14 +785,21 @@ IOFile::~IOFile()
|
||||
Close();
|
||||
}
|
||||
|
||||
bool IOFile::Open(const std::string& filename, const char openmode[])
|
||||
bool IOFile::Open(const std::string& filename, const char openmode[], IOFileMethod method)
|
||||
{
|
||||
Close();
|
||||
|
||||
m_method = method;
|
||||
if (0 != (m_method & METHOD_GZIP))
|
||||
m_zFile = gzopen(filename.c_str(), openmode);
|
||||
else
|
||||
{
|
||||
#ifdef _WIN32
|
||||
fopen_s(&m_file, filename.c_str(), openmode);
|
||||
fopen_s(&m_file, filename.c_str(), openmode);
|
||||
#else
|
||||
m_file = fopen(filename.c_str(), openmode);
|
||||
m_file = fopen(filename.c_str(), openmode);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_good = IsOpen();
|
||||
return m_good;
|
||||
@@ -800,10 +807,19 @@ bool IOFile::Open(const std::string& filename, const char openmode[])
|
||||
|
||||
bool IOFile::Close()
|
||||
{
|
||||
if (!IsOpen() || 0 != std::fclose(m_file))
|
||||
m_good = false;
|
||||
if (0 != (m_method & METHOD_GZIP))
|
||||
{
|
||||
if (Z_OK != gzclose(m_zFile))
|
||||
m_good = false;
|
||||
m_zFile = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsOpen() || 0 != std::fclose(m_file))
|
||||
m_good = false;
|
||||
m_file = NULL;
|
||||
}
|
||||
|
||||
m_file = NULL;
|
||||
return m_good;
|
||||
}
|
||||
|
||||
@@ -819,19 +835,32 @@ void IOFile::SetHandle(std::FILE* file)
|
||||
Close();
|
||||
Clear();
|
||||
m_file = file;
|
||||
m_method = METHOD_STANDARD;
|
||||
}
|
||||
|
||||
u64 IOFile::GetSize()
|
||||
{
|
||||
if (IsOpen())
|
||||
{
|
||||
// Not supported.
|
||||
if (0 != (m_method & METHOD_GZIP))
|
||||
return 0;
|
||||
return File::GetSize(m_file);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool IOFile::Seek(s64 off, int origin)
|
||||
{
|
||||
if (!IsOpen() || 0 != fseeko(m_file, off, origin))
|
||||
if (!IsOpen())
|
||||
m_good = false;
|
||||
else if (0 != (m_method & METHOD_GZIP))
|
||||
{
|
||||
if (-1 == gzseek(m_zFile, (z_off_t) off, origin))
|
||||
m_good = false;
|
||||
}
|
||||
else if (0 != fseeko(m_file, off, origin))
|
||||
m_good = false;
|
||||
|
||||
return m_good;
|
||||
@@ -840,14 +869,26 @@ bool IOFile::Seek(s64 off, int origin)
|
||||
u64 IOFile::Tell()
|
||||
{
|
||||
if (IsOpen())
|
||||
{
|
||||
if (0 != (m_method & METHOD_GZIP))
|
||||
return gztell(m_zFile);
|
||||
|
||||
return ftello(m_file);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool IOFile::Flush()
|
||||
{
|
||||
if (!IsOpen() || 0 != std::fflush(m_file))
|
||||
if (!IsOpen())
|
||||
m_good = false;
|
||||
else if (0 != (m_method & METHOD_GZIP))
|
||||
{
|
||||
if (-1 == gzflush(m_zFile, Z_PARTIAL_FLUSH))
|
||||
m_good = false;
|
||||
}
|
||||
else if (0 != std::fflush(m_file))
|
||||
m_good = false;
|
||||
|
||||
return m_good;
|
||||
@@ -855,7 +896,15 @@ bool IOFile::Flush()
|
||||
|
||||
bool IOFile::Resize(u64 size)
|
||||
{
|
||||
if (!IsOpen() || 0 !=
|
||||
if (!IsOpen())
|
||||
m_good = false;
|
||||
else if (0 != (m_method & METHOD_GZIP))
|
||||
{
|
||||
// gzseek() adds nulls to the seeked location.
|
||||
if (-1 == gzseek(m_zFile, (z_off_t) size, SEEK_SET))
|
||||
m_good = false;
|
||||
}
|
||||
else if (0 !=
|
||||
#ifdef _WIN32
|
||||
// ector: _chsize sucks, not 64-bit safe
|
||||
// F|RES: changed to _chsize_s. i think it is 64-bit safe
|
||||
|
||||
+34
-7
@@ -25,6 +25,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "../ext/zlib/zlib.h"
|
||||
|
||||
// User directory indices for GetUserPath
|
||||
enum {
|
||||
@@ -124,6 +125,13 @@ std::string &GetExeDirectory();
|
||||
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename);
|
||||
bool ReadFileToString(bool text_file, const char *filename, std::string &str);
|
||||
|
||||
enum IOFileMethod
|
||||
{
|
||||
METHOD_STANDARD = 0x00,
|
||||
// Warning: may not be 64-bit safe.
|
||||
METHOD_GZIP = 0x01,
|
||||
};
|
||||
|
||||
// simple wrapper for cstdlib file functions to
|
||||
// hopefully will make error checking easier
|
||||
// and make forgetting an fclose() harder
|
||||
@@ -132,17 +140,24 @@ class IOFile : NonCopyable
|
||||
public:
|
||||
IOFile();
|
||||
IOFile(std::FILE* file);
|
||||
IOFile(const std::string& filename, const char openmode[]);
|
||||
IOFile(const std::string& filename, const char openmode[], IOFileMethod method = METHOD_STANDARD);
|
||||
|
||||
~IOFile();
|
||||
|
||||
bool Open(const std::string& filename, const char openmode[]);
|
||||
bool Open(const std::string& filename, const char openmode[], IOFileMethod method = METHOD_STANDARD);
|
||||
bool Close();
|
||||
|
||||
template <typename T>
|
||||
bool ReadArray(T* data, size_t length)
|
||||
{
|
||||
if (!IsOpen() || length != std::fread(data, sizeof(T), length, m_file))
|
||||
if (!IsOpen())
|
||||
m_good = false;
|
||||
else if (0 != (m_method & METHOD_GZIP))
|
||||
{
|
||||
if (sizeof(T) * length != gzread(m_zFile, data, sizeof(T) * length))
|
||||
m_good = false;
|
||||
}
|
||||
else if (length != std::fread(data, sizeof(T), length, m_file))
|
||||
m_good = false;
|
||||
|
||||
return m_good;
|
||||
@@ -151,7 +166,14 @@ public:
|
||||
template <typename T>
|
||||
bool WriteArray(const T* data, size_t length)
|
||||
{
|
||||
if (!IsOpen() || length != std::fwrite(data, sizeof(T), length, m_file))
|
||||
if (!IsOpen())
|
||||
m_good = false;
|
||||
else if (0 != (m_method & METHOD_GZIP))
|
||||
{
|
||||
if (sizeof(T) * length != gzwrite(m_zFile, data, sizeof(T) * length))
|
||||
m_good = false;
|
||||
}
|
||||
else if (length != std::fwrite(data, sizeof(T), length, m_file))
|
||||
m_good = false;
|
||||
|
||||
return m_good;
|
||||
@@ -167,11 +189,11 @@ public:
|
||||
return WriteArray(reinterpret_cast<const char*>(data), length);
|
||||
}
|
||||
|
||||
bool IsOpen() { return NULL != m_file; }
|
||||
bool IsOpen() { return NULL != m_file || NULL != m_zFile; }
|
||||
|
||||
// m_good is set to false when a read, write or other function fails
|
||||
bool IsGood() { return m_good; }
|
||||
operator void*() { return m_good ? m_file : NULL; }
|
||||
operator void*() { return m_good ? (NULL != m_file ? m_file : m_zFile) : NULL; }
|
||||
|
||||
std::FILE* ReleaseHandle();
|
||||
|
||||
@@ -189,13 +211,18 @@ public:
|
||||
void Clear() {
|
||||
m_good = true;
|
||||
#undef clearerr
|
||||
std::clearerr(m_file);
|
||||
if (NULL != m_file)
|
||||
std::clearerr(m_file);
|
||||
if (NULL != m_zFile)
|
||||
gzclearerr(m_zFile);
|
||||
}
|
||||
|
||||
private:
|
||||
IOFile& operator=(const IOFile&) /*= delete*/;
|
||||
|
||||
std::FILE* m_file;
|
||||
gzFile m_zFile;
|
||||
IOFileMethod m_method;
|
||||
bool m_good;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user