mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
Merge large parts of nakeee's "Soap" branch into trunk, after fixing a few crash bugs in FileUtil.cpp.
Not really anything interesting, just some better comments, some slightly more portable/cleaner code in places. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2459 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -34,6 +34,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
template <class T>
|
||||
struct LinkedListItem : public T
|
||||
@ -41,15 +42,11 @@ struct LinkedListItem : public T
|
||||
LinkedListItem<T> *next;
|
||||
};
|
||||
|
||||
|
||||
// Wrapper class
|
||||
class PointerWrap
|
||||
{
|
||||
public:
|
||||
/* READ is when we read from the save state file, WRITE is when we write to the
|
||||
save state file. This enumareted list is also defined in pluginspecs.h. Didn't
|
||||
want to couple them. */
|
||||
enum Mode
|
||||
{
|
||||
enum Mode {
|
||||
MODE_READ = 1,
|
||||
MODE_WRITE,
|
||||
MODE_MEASURE,
|
||||
@ -68,8 +65,7 @@ public:
|
||||
|
||||
void DoVoid(void *data, int size)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case MODE_READ: memcpy(data, *ptr, size); break;
|
||||
case MODE_WRITE: memcpy(*ptr, data, size); break;
|
||||
case MODE_MEASURE: break; // MODE_MEASURE - don't need to do anything
|
||||
@ -84,22 +80,21 @@ public:
|
||||
// TODO
|
||||
PanicAlert("Do(map<>) does not yet work.");
|
||||
}
|
||||
|
||||
|
||||
// Store vectors.
|
||||
template<class T>
|
||||
void Do(std::vector<T> &x) {
|
||||
// TODO
|
||||
PanicAlert("Do(vector<>) does not yet work.");
|
||||
}
|
||||
|
||||
|
||||
// Store strings.
|
||||
void Do(std::string &x)
|
||||
{
|
||||
int stringLen = (int)x.length() + 1;
|
||||
Do(stringLen);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
|
||||
switch (mode) {
|
||||
case MODE_READ: x = (char*)*ptr; break;
|
||||
case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
|
||||
case MODE_MEASURE: break;
|
||||
@ -110,33 +105,29 @@ public:
|
||||
void DoBuffer(u8** pBuffer, u32& _Size)
|
||||
{
|
||||
Do(_Size);
|
||||
|
||||
if (_Size > 0)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
|
||||
if (_Size > 0) {
|
||||
switch (mode) {
|
||||
case MODE_READ: *pBuffer = new u8[_Size]; memcpy(*pBuffer, *ptr, _Size); break;
|
||||
case MODE_WRITE: memcpy(*ptr, *pBuffer, _Size); break;
|
||||
case MODE_MEASURE: break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
*pBuffer = NULL;
|
||||
}
|
||||
(*ptr) += _Size;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void DoArray(T *x, int count) {
|
||||
void DoArray(T *x, int count) {
|
||||
DoVoid((void *)x, sizeof(T) * count);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Do(T &x) {
|
||||
DoVoid((void *)&x, sizeof(x));
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void DoLinkedList(LinkedListItem<T> **list_start) {
|
||||
// TODO
|
||||
@ -148,85 +139,129 @@ public:
|
||||
class CChunkFileReader
|
||||
{
|
||||
public:
|
||||
// Load file template
|
||||
template<class T>
|
||||
static bool Load(const std::string& _rFilename, int _Revision, T& _class)
|
||||
static bool Load(const std::string& _rFilename, int _Revision, T& _class)
|
||||
{
|
||||
FILE* pFile = fopen(_rFilename.c_str(), "rb");
|
||||
if (pFile)
|
||||
{
|
||||
// get size
|
||||
fseek(pFile, 0, SEEK_END);
|
||||
size_t FileSize = ftell(pFile);
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
|
||||
INFO_LOG(COMMON, "ChunkReader: Loading %s" , _rFilename.c_str());
|
||||
|
||||
if (FileSize < sizeof(SChunkHeader))
|
||||
{
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// read the header
|
||||
SChunkHeader Header;
|
||||
fread(&Header, sizeof(SChunkHeader), 1, pFile);
|
||||
if (Header.Revision != _Revision)
|
||||
{
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get size
|
||||
int sz = (int)(FileSize - sizeof(SChunkHeader));
|
||||
if (Header.ExpectedSize != sz)
|
||||
{
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// read the state
|
||||
u8* buffer = new u8[sz];
|
||||
fread(buffer, 1, sz, pFile);
|
||||
fclose(pFile);
|
||||
|
||||
u8 *ptr = buffer;
|
||||
PointerWrap p(&ptr, PointerWrap::MODE_READ);
|
||||
_class.DoState(p);
|
||||
delete [] buffer;
|
||||
|
||||
return true;
|
||||
if (! File::Exists(_rFilename.c_str()))
|
||||
return false;
|
||||
|
||||
// Check file size
|
||||
u64 fileSize = File::GetSize(_rFilename.c_str());
|
||||
u64 headerSize = sizeof(SChunkHeader);
|
||||
if (fileSize < headerSize) {
|
||||
ERROR_LOG(COMMON,"ChunkReader: File too small");
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
FILE* pFile;
|
||||
if (! (pFile = fopen(_rFilename.c_str(), "rb"))) {
|
||||
ERROR_LOG(COMMON,"ChunkReader: Can't open file for reading");
|
||||
return false;
|
||||
}
|
||||
|
||||
// read the header
|
||||
SChunkHeader header;
|
||||
if (fread(&header, 1, headerSize, pFile) != headerSize) {
|
||||
fclose(pFile);
|
||||
ERROR_LOG(COMMON,"ChunkReader: Bad header size");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check revision
|
||||
if (header.Revision != _Revision) {
|
||||
fclose(pFile);
|
||||
ERROR_LOG(COMMON,"ChunkReader: Wrong file revision, got %d expected %d",
|
||||
header.Revision, _Revision);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get size
|
||||
int sz = (int)(fileSize - headerSize);
|
||||
if (header.ExpectedSize != sz) {
|
||||
fclose(pFile);
|
||||
ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d",
|
||||
sz, header.ExpectedSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
// read the state
|
||||
u8* buffer = new u8[sz];
|
||||
if ((int)fread(buffer, 1, sz, pFile) != sz) {
|
||||
fclose(pFile);
|
||||
ERROR_LOG(COMMON,"ChunkReader: Error reading file");
|
||||
return false;
|
||||
}
|
||||
|
||||
// done reading
|
||||
if (fclose(pFile)) {
|
||||
ERROR_LOG(COMMON,"ChunkReader: Error closing file! might be corrupted!");
|
||||
// should never happen!
|
||||
return false;
|
||||
}
|
||||
|
||||
u8 *ptr = buffer;
|
||||
PointerWrap p(&ptr, PointerWrap::MODE_READ);
|
||||
_class.DoState(p);
|
||||
delete [] buffer;
|
||||
|
||||
INFO_LOG(COMMON, "ChunkReader: Done loading %s" , _rFilename.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Save file template
|
||||
template<class T>
|
||||
static bool Save(const std::string& _rFilename, int _Revision, T& _class)
|
||||
{
|
||||
FILE* pFile = fopen(_rFilename.c_str(), "wb");
|
||||
if (pFile)
|
||||
{
|
||||
u8 *ptr = 0;
|
||||
PointerWrap p(&ptr, PointerWrap::MODE_MEASURE);
|
||||
_class.DoState(p);
|
||||
size_t sz = (size_t)ptr;
|
||||
u8 *buffer = new u8[sz];
|
||||
ptr = buffer;
|
||||
p.SetMode(PointerWrap::MODE_WRITE);
|
||||
_class.DoState(p);
|
||||
FILE* pFile;
|
||||
|
||||
SChunkHeader Header;
|
||||
Header.Compress = 0;
|
||||
Header.Revision = _Revision;
|
||||
Header.ExpectedSize = (int)sz;
|
||||
|
||||
fwrite(&Header, sizeof(SChunkHeader), 1, pFile);
|
||||
fwrite(buffer, sz, 1, pFile);
|
||||
fclose(pFile);
|
||||
|
||||
return true;
|
||||
INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str());
|
||||
|
||||
if (! (pFile = fopen(_rFilename.c_str(), "wb"))) {
|
||||
ERROR_LOG(COMMON,"ChunkReader: Error opening file for write");
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
// Get data
|
||||
u8 *ptr = 0;
|
||||
PointerWrap p(&ptr, PointerWrap::MODE_MEASURE);
|
||||
_class.DoState(p);
|
||||
size_t sz = (size_t)ptr;
|
||||
u8 *buffer = new u8[sz];
|
||||
ptr = buffer;
|
||||
p.SetMode(PointerWrap::MODE_WRITE);
|
||||
_class.DoState(p);
|
||||
|
||||
// Create header
|
||||
SChunkHeader header;
|
||||
header.Compress = 0;
|
||||
header.Revision = _Revision;
|
||||
header.ExpectedSize = (int)sz;
|
||||
|
||||
// Write to file
|
||||
if (fwrite(&header, sizeof(SChunkHeader), 1, pFile) != 1) {
|
||||
ERROR_LOG(COMMON,"ChunkReader: Failed writing header");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fwrite(buffer, sz, 1, pFile) != 1) {
|
||||
ERROR_LOG(COMMON,"ChunkReader: Failed writing data");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fclose(pFile)) {
|
||||
ERROR_LOG(COMMON,"ChunkReader: Error closing file! might be corrupted!");
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(COMMON,"ChunkReader: Done writing %s",
|
||||
_rFilename.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
struct SChunkHeader
|
||||
{
|
||||
|
Reference in New Issue
Block a user