diff --git a/Source/Core/Common/Src/ChunkFile.h b/Source/Core/Common/Src/ChunkFile.h index 38e1b2176c..3c0a58f678 100644 --- a/Source/Core/Common/Src/ChunkFile.h +++ b/Source/Core/Common/Src/ChunkFile.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -45,7 +46,8 @@ struct LinkedListItem : public T class PointerWrap { public: - enum Mode { + enum Mode + { MODE_READ = 1, // load MODE_WRITE, // save MODE_MEASURE, // calculate size @@ -57,124 +59,95 @@ public: public: PointerWrap(u8 **ptr_, Mode mode_) : ptr(ptr_), mode(mode_) {} - PointerWrap(unsigned char **ptr_, int mode_) : ptr((u8**)ptr_), mode((Mode)mode_) {} - void SetMode(Mode mode_) {mode = mode_;} - Mode GetMode() const {return mode;} - u8 **GetPPtr() {return ptr;} + void SetMode(Mode mode_) { mode = mode_; } + Mode GetMode() const { return mode; } + u8** GetPPtr() { return ptr; } - void DoVoid(void *data, int size) + template + void Do(std::map& x) { - 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 - case MODE_VERIFY: for(int i = 0; i < size; i++) _dbg_assert_msg_(COMMON, ((u8*)data)[i] == (*ptr)[i], "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n", ((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i], &(*ptr)[i]); break; - default: break; // throw an error? - } - (*ptr) += size; - } - - template - void Do(std::map &x) - { - unsigned int number = (unsigned int)x.size(); - Do(number); - switch (mode) { + u32 count = (u32)x.size(); + Do(count); + + switch (mode) + { case MODE_READ: + for (x.clear(); count != 0; --count) { - x.clear(); - while (number > 0) - { - unsigned int first = 0; - Do(first); - T second; - Do(second); - x[first] = second; - --number; - } + std::pair pair; + Do(pair.first); + Do(pair.second); + x.insert(pair); } break; + case MODE_WRITE: case MODE_MEASURE: case MODE_VERIFY: + for (auto itr = x.begin(); itr != x.end(); ++itr) { - typename std::map::iterator itr = x.begin(); - while (number > 0) - { - Do(itr->first); - Do(itr->second); - --number; - ++itr; - } + Do(itr->first); + Do(itr->second); } break; } } - - // Store vectors. - template - void Do(std::vector &x) - { - u32 vec_size = (u32)x.size(); - Do(vec_size); - x.resize(vec_size); - DoArray(&x[0], vec_size); - } - // Store deques. - template - void Do(std::deque &x) + template + void DoContainer(T& x) { - u32 deq_size = (u32)x.size(); - Do(deq_size); - x.resize(deq_size); - u32 i; - for(i = 0; i < deq_size; i++) - DoVoid(&x[i],sizeof(T)); - } - - // Store strings. - void Do(std::string &x) - { - int stringLen = (int)x.length() + 1; - Do(stringLen); + u32 size = (u32)x.size(); + Do(size); + x.resize(size); - switch (mode) { - case MODE_READ: x = (char*)*ptr; break; - case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break; - case MODE_MEASURE: break; - case MODE_VERIFY: _dbg_assert_msg_(COMMON, !strcmp(x.c_str(), (char*)*ptr), "Savestate verification failure: \"%s\" != \"%s\" (at %p).\n", x.c_str(), (char*)*ptr, ptr); break; - } - (*ptr) += stringLen; + for (auto itr = x.begin(); itr != x.end(); ++itr) + Do(*itr); } - void Do(std::wstring &x) + template + void Do(std::vector& x) { - int stringLen = sizeof(wchar_t)*((int)x.length() + 1); - Do(stringLen); - - switch (mode) { - case MODE_READ: x.assign((wchar_t*)*ptr, (stringLen / sizeof(wchar_t)) - 1); break; - case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break; - case MODE_MEASURE: break; - case MODE_VERIFY: _dbg_assert_msg_(COMMON, x == (wchar_t*)*ptr, "Savestate verification failure: \"%ls\" != \"%ls\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); break; - } - (*ptr) += stringLen; + DoContainer(x); + } + + template + void Do(std::list& x) + { + DoContainer(x); + } + + template + void Do(std::deque& x) + { + DoContainer(x); + } + + template + void Do(std::basic_string& x) + { + DoContainer(x); } - template - void DoArray(T *x, int count) { - DoVoid((void *)x, sizeof(T) * count); + template + void DoArray(T* x, u32 count) + { + for (u32 i = 0; i != count; ++i) + Do(x[i]); } - template - void Do(T &x) { - DoVoid((void *)&x, sizeof(x)); + template + void Do(T& x) + { + // TODO: Bad, Do(some_non_POD) will compile and fail at runtime + // type_traits are not fully supported everywhere yet + + DoVoid((void*)&x, sizeof(x)); } - template - void DoPointer(T* &x, T*const base) { + template + void DoPointer(T*& x, T* const base) + { // pointers can be more than 2^31 apart, but you're using this function wrong if you need that much range s32 offset = x - base; Do(offset); @@ -182,7 +155,8 @@ public: x = base + offset; } - template* (*TNew)(), void (*TFree)(LinkedListItem*), void (*TDo)(PointerWrap&, T*)> + // Let's pretend std::list doesn't exist! + template * (*TNew)(), void (*TFree)(LinkedListItem*), void (*TDo)(PointerWrap&, T*)> void DoLinkedList(LinkedListItem*& list_start, LinkedListItem** list_end=0) { LinkedListItem* list_cur = list_start; @@ -242,25 +216,61 @@ public: } } - void DoMarker(const char* prevName, u32 arbitraryNumber=0x42) + void DoMarker(const char* prevName, u32 arbitraryNumber = 0x42) { u32 cookie = arbitraryNumber; Do(cookie); - if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber) + + if (mode == PointerWrap::MODE_READ && cookie != arbitraryNumber) { - PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber); + PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", + prevName, cookie, cookie, arbitraryNumber, arbitraryNumber); mode = PointerWrap::MODE_MEASURE; } } + +private: + __forceinline void DoByte(u8& x) + { + switch (mode) + { + case MODE_READ: + x = **ptr; + break; + + case MODE_WRITE: + **ptr = x; + break; + + case MODE_MEASURE: + break; + + case MODE_VERIFY: + _dbg_assert_msg_(COMMON, (x == *ptr), + "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n", + x, x, &x, *ptr, *ptr, &*ptr); + break; + + default: + break; + } + + ++(*ptr); + } + + void DoVoid(void *data, u32 size) + { + for(u32 i = 0; i != size; ++i) + DoByte(reinterpret_cast(data)[i]); + } }; - class CChunkFileReader { public: // Load file template template - static bool Load(const std::string& _rFilename, int _Revision, T& _class) + static bool Load(const std::string& _rFilename, u32 _Revision, T& _class) { INFO_LOG(COMMON, "ChunkReader: Loading %s" , _rFilename.c_str()); @@ -300,7 +310,7 @@ public: } // get size - const int sz = (int)(fileSize - headerSize); + const u32 sz = (u32)(fileSize - headerSize); if (header.ExpectedSize != sz) { ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d", @@ -309,17 +319,16 @@ public: } // read the state - u8* buffer = new u8[sz]; - if (!pFile.ReadBytes(buffer, sz)) + std::vector buffer(sz); + if (!pFile.ReadArray(&buffer[0], sz)) { ERROR_LOG(COMMON,"ChunkReader: Error reading file"); return false; } - u8 *ptr = buffer; + u8* ptr = &buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_READ); _class.DoState(p); - delete[] buffer; INFO_LOG(COMMON, "ChunkReader: Done loading %s" , _rFilename.c_str()); return true; @@ -327,7 +336,7 @@ public: // Save file template template - static bool Save(const std::string& _rFilename, int _Revision, T& _class) + static bool Save(const std::string& _rFilename, u32 _Revision, T& _class) { INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str()); File::IOFile pFile(_rFilename, "wb"); @@ -349,9 +358,8 @@ public: // Create header SChunkHeader header; - header.Compress = 0; header.Revision = _Revision; - header.ExpectedSize = (int)sz; + header.ExpectedSize = (u32)sz; // Write to file if (!pFile.WriteArray(&header, 1)) @@ -360,23 +368,21 @@ public: return false; } - if (!pFile.WriteBytes(&buffer[0], sz)) + if (!pFile.WriteArray(&buffer[0], sz)) { ERROR_LOG(COMMON,"ChunkReader: Failed writing data"); return false; } - INFO_LOG(COMMON,"ChunkReader: Done writing %s", - _rFilename.c_str()); + INFO_LOG(COMMON,"ChunkReader: Done writing %s", _rFilename.c_str()); return true; } private: struct SChunkHeader { - int Revision; - int Compress; - int ExpectedSize; + u32 Revision; + u32 ExpectedSize; }; }; diff --git a/Source/Core/Core/Src/HW/Wiimote.cpp b/Source/Core/Core/Src/HW/Wiimote.cpp index 59fe8b7fa5..e45856f5f5 100644 --- a/Source/Core/Core/Src/HW/Wiimote.cpp +++ b/Source/Core/Core/Src/HW/Wiimote.cpp @@ -133,7 +133,7 @@ unsigned int GetAttached() // input/output: ptr // input: mode // -void DoState(unsigned char **ptr, int mode) +void DoState(u8 **ptr, PointerWrap::Mode mode) { // TODO: diff --git a/Source/Core/Core/Src/HW/Wiimote.h b/Source/Core/Core/Src/HW/Wiimote.h index dd0e6df389..6b758abb5a 100644 --- a/Source/Core/Core/Src/HW/Wiimote.h +++ b/Source/Core/Core/Src/HW/Wiimote.h @@ -3,6 +3,7 @@ #define _WIIMOTE_H_ #include "../../InputCommon/Src/InputConfig.h" +#include "ChunkFile.h" #define MAX_WIIMOTES 4 @@ -25,7 +26,7 @@ void Shutdown(); void Initialize(void* const hwnd); unsigned int GetAttached(); -void DoState(unsigned char **ptr, int mode); +void DoState(u8 **ptr, PointerWrap::Mode mode); void EmuStateChange(EMUSTATE_CHANGE newState); InputPlugin *GetPlugin(); diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index 773d757337..e0a9ab7858 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 15; +static const u32 STATE_VERSION = 16; struct StateHeader { diff --git a/Source/Core/DolphinWX/Src/ISOFile.cpp b/Source/Core/DolphinWX/Src/ISOFile.cpp index 833268ad63..496a6304d4 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.cpp +++ b/Source/Core/DolphinWX/Src/ISOFile.cpp @@ -36,7 +36,7 @@ #include "ChunkFile.h" #include "ConfigManager.h" -#define CACHE_REVISION 0x10F +#define CACHE_REVISION 0x110 #define DVD_BANNER_WIDTH 96 #define DVD_BANNER_HEIGHT 32