From 78d9f927e1ea051e30d808da965a2be2f14de5e3 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 17 Mar 2011 10:17:45 +0000 Subject: [PATCH] Eliminated memory leaks of the save state code and put it in a namespace. It is prettier than before, but it could be better (less global usage). Other minor stuff. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7366 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/Core.cpp | 5 +- Source/Core/Core/Src/HW/HW.cpp | 4 +- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 8 +- Source/Core/Core/Src/OnFrame.cpp | 2 +- Source/Core/Core/Src/State.cpp | 537 +++++++----------- Source/Core/Core/Src/State.h | 45 +- Source/Core/DolphinWX/Src/Frame.cpp | 10 +- Source/Core/DolphinWX/Src/FrameTools.cpp | 18 +- Source/Core/DolphinWX/Src/MainNoGUI.cpp | 10 +- Source/Core/DolphinWX/Src/VideoConfigDiag.cpp | 1 - Source/Plugins/Plugin_VideoDX11/Src/main.cpp | 1 - Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 1 - Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 1 - .../Plugin_VideoSoftware/Src/SWmain.cpp | 13 +- 14 files changed, 264 insertions(+), 392 deletions(-) diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 8e092231fb..906e42a44e 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -57,6 +57,7 @@ #include "DSPEmulator.h" #include "ConfigManager.h" #include "VideoBackendBase.h" +#include "OnScreenDisplay.h" #include "VolumeHandler.h" #include "FileMonitor.h" @@ -200,6 +201,8 @@ bool Init() return false; } + OSD::AddMessage(("Dolphin " + g_video_backend->GetName() + " Video Backend.").c_str(), 5000); + HW::Init(); if (!DSP::GetDSPEmulator()->Initialize(g_pWindowHandle, _CoreParameter.bWii, _CoreParameter.bDSPThread)) @@ -321,7 +324,7 @@ void CpuThread() EMM::InstallExceptionHandler(); // Let's run under memory watch if (!g_stateFileName.empty()) - State_LoadAs(g_stateFileName); + State::LoadAs(g_stateFileName); // Enter CPU run loop. When we leave it - we are done. CCPU::Run(); diff --git a/Source/Core/Core/Src/HW/HW.cpp b/Source/Core/Core/Src/HW/HW.cpp index 51ae87a341..ec8aa7063f 100644 --- a/Source/Core/Core/Src/HW/HW.cpp +++ b/Source/Core/Core/Src/HW/HW.cpp @@ -44,7 +44,7 @@ namespace HW { CoreTiming::Init(); - State_Init(); + State::Init(); // Init the whole Hardware AudioInterface::Init(); @@ -82,7 +82,7 @@ namespace HW WII_IPC_HLE_Interface::Shutdown(); } - State_Shutdown(); + State::Shutdown(); CoreTiming::Shutdown(); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 5a3db0d7ef..b149c45c8b 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -406,6 +407,9 @@ int UnPair() // negative number on failure int PairUp(bool unpair) { + // match strings like "Nintendo RVL-WBC-01", "Nintendo RVL-CNT-01" + const std::wregex wiimote_device_name(L"Nintendo RVL-\\w{3}-\\d{2}"); + int nPaired = 0; BLUETOOTH_DEVICE_SEARCH_PARAMS srch; @@ -451,9 +455,7 @@ int PairUp(bool unpair) DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ", btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered); - // TODO: Probably could just check for "Nintendo RVL" - if (0 == wcscmp(btdi.szName, L"Nintendo RVL-WBC-01") || - 0 == wcscmp(btdi.szName, L"Nintendo RVL-CNT-01")) + if (std::regex_match(btdi.szName, wiimote_device_name)) { if (unpair) { diff --git a/Source/Core/Core/Src/OnFrame.cpp b/Source/Core/Core/Src/OnFrame.cpp index efccaa5dca..9643079642 100644 --- a/Source/Core/Core/Src/OnFrame.cpp +++ b/Source/Core/Core/Src/OnFrame.cpp @@ -205,7 +205,7 @@ bool BeginRecordingInput(int controllers) const std::string stateFilename = g_recordFile + ".sav"; if(File::Exists(stateFilename)) File::Delete(stateFilename); - State_SaveAs(stateFilename.c_str()); + State::SaveAs(stateFilename.c_str()); g_bRecordingFromSaveState = true; } diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index c7a1e6c031..3f63b5a9f5 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -16,7 +16,6 @@ // http://code.google.com/p/dolphin-emu/ #include "Common.h" - #include "State.h" #include "Core.h" #include "ConfigManager.h" @@ -29,61 +28,64 @@ #include "HW/HW.h" #include "HW/CPU.h" #include "PowerPC/JitCommon/JitBase.h" - #include "VideoBackendBase.h" -#include - #include -// TODO: Move to namespace - -// TODO: Investigate a memory leak on save/load state +namespace State +{ #if defined(__LZO_STRICT_16BIT) -#define IN_LEN (8*1024u) +static const u32 IN_LEN = 8 * 1024u; #elif defined(LZO_ARCH_I086) && !defined(LZO_HAVE_MM_HUGE_ARRAY) -#define IN_LEN (60*1024u) +static const u32 IN_LEN = 60 * 1024u; #else -#define IN_LEN (128*1024ul) +static const u32 IN_LEN = 128 * 1024u; #endif -#define OUT_LEN (IN_LEN + IN_LEN / 16 + 64 + 3) -static unsigned char __LZO_MMODEL out [ OUT_LEN ]; +static const u32 OUT_LEN = IN_LEN + (IN_LEN / 16) + 64 + 3; -#define HEAP_ALLOC(var,size) \ - lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] +static unsigned char __LZO_MMODEL out[OUT_LEN]; -static HEAP_ALLOC(wrkmem,LZO1X_1_MEM_COMPRESS); +#define HEAP_ALLOC(var, size) \ + lzo_align_t __LZO_MMODEL var[((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t)] -static bool state_op_in_progress = false; +static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); -static int ev_Save, ev_BufferSave; -static int ev_Load, ev_BufferLoad; -static int ev_Verify, ev_BufferVerify; +static volatile bool g_op_in_progress = false; -static std::string cur_filename, lastFilename; -static u8 **cur_buffer = NULL; +static int ev_FileSave, ev_BufferSave, ev_FileLoad, ev_BufferLoad, ev_FileVerify, ev_BufferVerify; -// Temporary undo state buffers -static u8 *undoLoad = NULL; +static std::string g_current_filename, g_last_filename; -static bool const bCompressed = true; - -static std::thread saveThread; +// Temporary undo state buffer +static std::vector g_undo_load_buffer; +static std::vector g_current_buffer; +static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -#define STATE_VERSION 4 +static const int VERSION = 4; +struct StateHeader +{ + u8 gameID[6]; + size_t size; +}; + +static bool g_use_compression = true; + +void EnableCompression(bool compression) +{ + g_use_compression = compression; +} void DoState(PointerWrap &p) { - u32 cookie = 0xBAADBABE + STATE_VERSION; + u32 cookie = 0xBAADBABE + VERSION; p.Do(cookie); - if (cookie != 0xBAADBABE + STATE_VERSION) + if (cookie != 0xBAADBABE + VERSION) { - //PanicAlert("Savestate version mismatch !\nSorry, you can't load states from other revisions."); p.SetMode(PointerWrap::MODE_MEASURE); return; } @@ -105,115 +107,88 @@ void DoState(PointerWrap &p) void LoadBufferStateCallback(u64 userdata, int cyclesLate) { - if (!cur_buffer || !*cur_buffer) { - Core::DisplayMessage("State does not exist", 1000); - return; - } - - u8 *ptr = *cur_buffer; + u8* ptr = &g_current_buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_READ); DoState(p); Core::DisplayMessage("Loaded state", 2000); - state_op_in_progress = false; + + g_op_in_progress = false; } void SaveBufferStateCallback(u64 userdata, int cyclesLate) { - if (!cur_buffer) { - Core::DisplayMessage("Error saving state", 1000); - return; - } - - u8 *ptr = NULL; - + u8* ptr = NULL; PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); - if (!*cur_buffer) - { - // if we got passed an empty buffer, - // allocate it with new[] - // (and the caller is responsible for delete[]ing it later) - DoState(p); - size_t sz = (size_t)ptr; - *cur_buffer = new u8[sz]; - } - else - { - // otherwise the caller is telling us that they have already allocated it with enough space - } + DoState(p); + const size_t buffer_size = reinterpret_cast(ptr); + g_current_buffer.resize(buffer_size); - ptr = *cur_buffer; + ptr = &g_current_buffer[0]; p.SetMode(PointerWrap::MODE_WRITE); DoState(p); - state_op_in_progress = false; + g_op_in_progress = false; } void VerifyBufferStateCallback(u64 userdata, int cyclesLate) { - if (!cur_buffer || !*cur_buffer) { - Core::DisplayMessage("State does not exist", 1000); - return; - } - - u8 *ptr = *cur_buffer; + u8* ptr = &g_current_buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); DoState(p); Core::DisplayMessage("Verified state", 2000); - state_op_in_progress = false; + + g_op_in_progress = false; } -void CompressAndDumpState(saveStruct* saveArg) +void CompressAndDumpState(const std::vector* save_arg) { - u8 *buffer = saveArg->buffer; - size_t sz = saveArg->size; - lzo_uint out_len = 0; - state_header header; - std::string filename = cur_filename; - - delete saveArg; + const u8* const buffer_data = &(*save_arg)[0]; + const size_t buffer_size = save_arg->size(); // For easy debugging Common::SetCurrentThreadName("SaveState thread"); // Moving to last overwritten save-state - if (File::Exists(cur_filename)) + if (File::Exists(g_current_filename)) { if (File::Exists(File::GetUserPath(D_STATESAVES_IDX) + "lastState.sav")) File::Delete((File::GetUserPath(D_STATESAVES_IDX) + "lastState.sav")); - if (!File::Rename(cur_filename, File::GetUserPath(D_STATESAVES_IDX) + "lastState.sav")) + if (!File::Rename(g_current_filename, File::GetUserPath(D_STATESAVES_IDX) + "lastState.sav")) Core::DisplayMessage("Failed to move previous state to state undo backup", 1000); } - File::IOFile f(filename, "wb"); + File::IOFile f(g_current_filename, "wb"); if (!f) { Core::DisplayMessage("Could not save state", 2000); - delete[] buffer; return; } // Setting up the header + StateHeader header; memcpy(header.gameID, SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), 6); - header.sz = bCompressed ? sz : 0; + header.size = g_use_compression ? buffer_size : 0; f.WriteArray(&header, 1); - if (bCompressed) - { - lzo_uint cur_len = 0; - lzo_uint i = 0; - for (;;) + if (0 != header.size) // non-zero header size means the state is compressed + { + lzo_uint i = 0; + while (true) { - if ((i + IN_LEN) >= sz) - cur_len = sz - i; + lzo_uint cur_len = 0; + lzo_uint out_len = 0; + + if ((i + IN_LEN) >= buffer_size) + cur_len = buffer_size - i; else cur_len = IN_LEN; - if (lzo1x_1_compress((buffer + i), cur_len, out, &out_len, wrkmem) != LZO_E_OK) + if (lzo1x_1_compress(buffer_data + i, cur_len, out, &out_len, wrkmem) != LZO_E_OK) PanicAlertT("Internal LZO Error - compression failed"); // The size of the data to write is 'out_len' @@ -222,123 +197,83 @@ void CompressAndDumpState(saveStruct* saveArg) if (cur_len != IN_LEN) break; + i += cur_len; } } - else + else // uncompressed { - f.WriteBytes(buffer, sz); + f.WriteBytes(buffer_data, buffer_size); } - delete[] buffer; - Core::DisplayMessage(StringFromFormat("Saved State to %s", - filename.c_str()).c_str(), 2000); + g_current_filename.c_str()).c_str(), 2000); - state_op_in_progress = false; + g_op_in_progress = false; } -void SaveStateCallback(u64 userdata, int cyclesLate) +void SaveFileStateCallback(u64 userdata, int cyclesLate) { // Pause the core while we save the state CCPU::EnableStepping(true); // Wait for the other threaded sub-systems to stop too + // TODO: this is ugly SLEEP(100); - State_Flush(); + Flush(); // Measure the size of the buffer. - u8 *ptr = 0; + u8 *ptr = NULL; PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); DoState(p); - size_t sz = (size_t)ptr; + const size_t buffer_size = reinterpret_cast(ptr); // Then actually do the write. - u8 *buffer = new u8[sz]; - ptr = buffer; + g_current_buffer.resize(buffer_size); + ptr = &g_current_buffer[0]; p.SetMode(PointerWrap::MODE_WRITE); DoState(p); - - saveStruct *saveData = new saveStruct; - saveData->buffer = buffer; - saveData->size = sz; if ((Frame::IsRecordingInput() || Frame::IsPlayingInput()) && !Frame::IsRecordingInputFromSaveState()) - Frame::SaveRecording(StringFromFormat("%s.dtm", cur_filename.c_str()).c_str()); + Frame::SaveRecording(StringFromFormat("%s.dtm", g_current_filename.c_str()).c_str()); Core::DisplayMessage("Saving State...", 1000); - saveThread = std::thread(CompressAndDumpState, saveData); + g_save_thread = std::thread(CompressAndDumpState, &g_current_buffer); // Resume the core and disable stepping CCPU::EnableStepping(false); } -void LoadStateCallback(u64 userdata, int cyclesLate) +void LoadFileStateData(std::string& filename, std::vector& ret_data) { - bool bCompressedState; - - // Stop the core while we load the state - CCPU::EnableStepping(true); - - // Wait for the other threaded sub-systems to stop too - SLEEP(100); - - State_Flush(); - - // Save temp buffer for undo load state - // TODO: this should be controlled by a user option, - // because it slows down every savestate load to provide an often-unused feature. - { - delete[] undoLoad; - undoLoad = NULL; - cur_buffer = &undoLoad; - SaveBufferStateCallback(userdata, cyclesLate); - } - - File::IOFile f(cur_filename, "rb"); + File::IOFile f(filename, "rb"); if (!f) { Core::DisplayMessage("State not found", 2000); - // Resume the clock - CCPU::EnableStepping(false); return; } - u8 *buffer = NULL; - state_header header; - size_t sz; - + StateHeader header; f.ReadArray(&header, 1); if (memcmp(SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), header.gameID, 6)) { - char gameID[7] = {0}; - memcpy(gameID, header.gameID, 6); - Core::DisplayMessage(StringFromFormat("State belongs to a different game (ID %s)", - gameID), 2000); - - // Resume the clock - CCPU::EnableStepping(false); + Core::DisplayMessage(StringFromFormat("State belongs to a different game (ID %.*s)", + 6, header.gameID), 2000); return; } - sz = header.sz; - bCompressedState = (sz != 0); - if (bCompressedState) + std::vector buffer; + + if (0 != header.size) // non-zero size means the state is compressed { Core::DisplayMessage("Decompressing State...", 500); + buffer.resize(header.size); + lzo_uint i = 0; - buffer = new u8[sz]; - if (!buffer) - { - PanicAlertT("Error allocating buffer"); - // Resume the clock - CCPU::EnableStepping(false); - return; - } while (true) { lzo_uint cur_len = 0; // number of bytes to read @@ -348,143 +283,103 @@ void LoadStateCallback(u64 userdata, int cyclesLate) break; f.ReadBytes(out, cur_len); - int res = lzo1x_decompress(out, cur_len, (buffer + i), &new_len, NULL); + const int res = lzo1x_decompress(out, cur_len, &buffer[i], &new_len, NULL); if (res != LZO_E_OK) { // This doesn't seem to happen anymore. PanicAlertT("Internal LZO Error - decompression failed (%d) (%li, %li) \n" "Try loading the state again", res, i, new_len); - delete[] buffer; - // Resume the clock - CCPU::EnableStepping(false); return; } i += new_len; } } - else + else // uncompressed { - sz = (int)(f.GetSize() - sizeof(state_header)); - buffer = new u8[sz]; - if (!f.ReadBytes(buffer, sz)) - PanicAlert("wtf? reading bytes: %lu", (unsigned long)sz); + const size_t size = (size_t)(f.GetSize() - sizeof(StateHeader)); + buffer.resize(size); + + if (!f.ReadBytes(&buffer[0], size)) + { + PanicAlert("wtf? reading bytes: %i", (int)size); + return; + } } - f.Close(); + // all good + ret_data.swap(buffer); +} - u8 *ptr = buffer; - PointerWrap p(&ptr, PointerWrap::MODE_READ); - DoState(p); +void LoadFileStateCallback(u64 userdata, int cyclesLate) +{ + // Stop the core while we load the state + CCPU::EnableStepping(true); - if (p.GetMode() == PointerWrap::MODE_READ) - Core::DisplayMessage(StringFromFormat("Loaded state from %s", cur_filename.c_str()).c_str(), 2000); - else - Core::DisplayMessage("Unable to Load : Can't load state from other revisions !", 4000); + // Wait for the other threaded sub-systems to stop too + // TODO: uglyyy + SLEEP(100); - delete[] buffer; + Flush(); + + // Save temp buffer for undo load state + // TODO: this should be controlled by a user option, + // because it slows down every savestate load to provide an often-unused feature. + SaveBufferStateCallback(userdata, cyclesLate); + g_undo_load_buffer.swap(g_current_buffer); + + std::vector buffer; + LoadFileStateData(g_current_filename, buffer); + + if (!buffer.empty()) + { + u8 *ptr = &buffer[0]; + PointerWrap p(&ptr, PointerWrap::MODE_READ); + DoState(p); + + if (p.GetMode() == PointerWrap::MODE_READ) + Core::DisplayMessage(StringFromFormat("Loaded state from %s", g_current_filename.c_str()).c_str(), 2000); + else + Core::DisplayMessage("Unable to Load : Can't load state from other revisions !", 4000); - if (File::Exists(cur_filename + ".dtm")) - Frame::LoadInput((cur_filename + ".dtm").c_str()); - else if (!Frame::IsRecordingInputFromSaveState()) - Frame::EndPlayInput(false); + if (File::Exists(g_current_filename + ".dtm")) + Frame::LoadInput((g_current_filename + ".dtm").c_str()); + else if (!Frame::IsRecordingInputFromSaveState()) + Frame::EndPlayInput(false); + } - state_op_in_progress = false; + g_op_in_progress = false; - // Resume the clock + // resume dat core CCPU::EnableStepping(false); } -void VerifyStateCallback(u64 userdata, int cyclesLate) +void VerifyFileStateCallback(u64 userdata, int cyclesLate) { - bool bCompressedState; + Flush(); - State_Flush(); + std::vector buffer; + LoadFileStateData(g_current_filename, buffer); - File::IOFile f(cur_filename, "rb"); - if (!f) + if (!buffer.empty()) { - Core::DisplayMessage("State not found", 2000); - return; + u8 *ptr = &buffer[0]; + PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); + DoState(p); + + if (p.GetMode() == PointerWrap::MODE_READ) + Core::DisplayMessage(StringFromFormat("Verified state at %s", g_current_filename.c_str()).c_str(), 2000); + else + Core::DisplayMessage("Unable to Verify : Can't verify state from other revisions !", 4000); } - - u8 *buffer = NULL; - state_header header; - size_t sz; - - f.ReadArray(&header, 1); - - if (memcmp(SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), header.gameID, 6)) - { - char gameID[7] = {0}; - memcpy(gameID, header.gameID, 6); - Core::DisplayMessage(StringFromFormat("State belongs to a different game (ID %s)", - gameID), 2000); - - return; - } - - sz = header.sz; - bCompressedState = (sz != 0); - if (bCompressedState) - { - Core::DisplayMessage("Decompressing State...", 500); - - lzo_uint i = 0; - buffer = new u8[sz]; - if (!buffer) { - PanicAlertT("Error allocating buffer"); - return; - } - while (true) - { - lzo_uint cur_len = 0; - lzo_uint new_len = 0; - if (!f.ReadArray(&cur_len, 1)) - break; - - f.ReadBytes(out, cur_len); - int res = lzo1x_decompress(out, cur_len, (buffer + i), &new_len, NULL); - if (res != LZO_E_OK) - { - // This doesn't seem to happen anymore. - PanicAlertT("Internal LZO Error - decompression failed (%d) (%ld, %ld) \n" - "Try verifying the state again", res, i, new_len); - - delete [] buffer; - return; - } - - // The size of the data to read to our buffer is 'new_len' - i += new_len; - } - } - else - { - sz = (int)(f.GetSize() - sizeof(int)); - buffer = new u8[sz]; - - if (!f.ReadBytes(buffer, sz)) - PanicAlert("wtf? failed to read bytes: %lu", (unsigned long)sz); - } - - u8 *ptr = buffer; - PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); - DoState(p); - - if (p.GetMode() == PointerWrap::MODE_READ) - Core::DisplayMessage(StringFromFormat("Verified state at %s", cur_filename.c_str()).c_str(), 2000); - else - Core::DisplayMessage("Unable to Verify : Can't verify state from other revisions !", 4000); - - delete [] buffer; } -void State_Init() +void Init() { - ev_Load = CoreTiming::RegisterEvent("LoadState", &LoadStateCallback); - ev_Save = CoreTiming::RegisterEvent("SaveState", &SaveStateCallback); - ev_Verify = CoreTiming::RegisterEvent("VerifyState", &VerifyStateCallback); + ev_FileLoad = CoreTiming::RegisterEvent("LoadState", &LoadFileStateCallback); + ev_FileSave = CoreTiming::RegisterEvent("SaveState", &SaveFileStateCallback); + ev_FileVerify = CoreTiming::RegisterEvent("VerifyState", &VerifyFileStateCallback); + ev_BufferLoad = CoreTiming::RegisterEvent("LoadBufferState", &LoadBufferStateCallback); ev_BufferSave = CoreTiming::RegisterEvent("SaveBufferState", &SaveBufferStateCallback); ev_BufferVerify = CoreTiming::RegisterEvent("VerifyBufferState", &VerifyBufferStateCallback); @@ -493,126 +388,114 @@ void State_Init() PanicAlertT("Internal LZO Error - lzo_init() failed"); } -void State_Shutdown() +void Shutdown() { - State_Flush(); + Flush(); - if (undoLoad) - { - delete[] undoLoad; - undoLoad = NULL; - } + g_current_buffer.swap(std::vector()); + g_undo_load_buffer.swap(std::vector()); } -static std::string MakeStateFilename(int state_number) +static std::string MakeStateFilename(int number) { - return StringFromFormat("%s%s.s%02i", File::GetUserPath(D_STATESAVES_IDX).c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), state_number); + return StringFromFormat("%s%s.s%02i", File::GetUserPath(D_STATESAVES_IDX).c_str(), + SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), number); } -void State_SaveAs(const std::string &filename) +void ScheduleFileEvent(const std::string &filename, int ev) { - if (state_op_in_progress) + if (g_op_in_progress) return; - state_op_in_progress = true; - cur_filename = filename; - lastFilename = filename; - CoreTiming::ScheduleEvent_Threadsafe_Immediate(ev_Save); + g_op_in_progress = true; + + g_current_filename = filename; + CoreTiming::ScheduleEvent_Threadsafe_Immediate(ev); } -void State_Save(int slot) +void SaveAs(const std::string &filename) { - State_SaveAs(MakeStateFilename(slot)); + g_last_filename = filename; + ScheduleFileEvent(filename, ev_FileSave); } -void State_LoadAs(const std::string &filename) +void LoadAs(const std::string &filename) { - if (state_op_in_progress) - return; - state_op_in_progress = true; - cur_filename = filename; - CoreTiming::ScheduleEvent_Threadsafe_Immediate(ev_Load); + ScheduleFileEvent(filename, ev_FileLoad); } -void State_Load(int slot) +void VerifyAt(const std::string &filename) { - State_LoadAs(MakeStateFilename(slot)); + ScheduleFileEvent(filename, ev_FileVerify); } -void State_VerifyAt(const std::string &filename) +void Save(int slot) { - if (state_op_in_progress) - return; - state_op_in_progress = true; - cur_filename = filename; - CoreTiming::ScheduleEvent_Threadsafe_Immediate(ev_Verify); + SaveAs(MakeStateFilename(slot)); } -void State_Verify(int slot) +void Load(int slot) { - State_VerifyAt(MakeStateFilename(slot)); + LoadAs(MakeStateFilename(slot)); } -void State_LoadLastSaved() +void Verify(int slot) { - if (lastFilename.empty()) + VerifyAt(MakeStateFilename(slot)); +} + +void LoadLastSaved() +{ + if (g_last_filename.empty()) Core::DisplayMessage("There is no last saved state", 2000); else - State_LoadAs(lastFilename); + LoadAs(g_last_filename); } -void State_LoadFromBuffer(u8 **buffer) +void ScheduleBufferEvent(std::vector& buffer, int ev) { - if (state_op_in_progress) + if (g_op_in_progress) return; - state_op_in_progress = true; - cur_buffer = buffer; - CoreTiming::ScheduleEvent_Threadsafe_Immediate(ev_BufferLoad); + g_op_in_progress = true; + + g_current_buffer.swap(buffer); + CoreTiming::ScheduleEvent_Threadsafe_Immediate(ev); } -void State_SaveToBuffer(u8 **buffer) +void SaveToBuffer(std::vector& buffer) { - if (state_op_in_progress) - return; - state_op_in_progress = true; - cur_buffer = buffer; - CoreTiming::ScheduleEvent_Threadsafe_Immediate(ev_BufferSave); + ScheduleBufferEvent(buffer, ev_BufferSave); } -void State_VerifyBuffer(u8 **buffer) +void LoadFromBuffer(std::vector& buffer) { - if (state_op_in_progress) - return; - state_op_in_progress = true; - cur_buffer = buffer; - CoreTiming::ScheduleEvent_Threadsafe_Immediate(ev_BufferVerify); + ScheduleBufferEvent(buffer, ev_BufferLoad); } -void State_Flush() +void VerifyBuffer(std::vector& buffer) +{ + ScheduleBufferEvent(buffer, ev_BufferVerify); +} + +void Flush() { // If already saving state, wait for it to finish - if (saveThread.joinable()) - { - saveThread.join(); - } + if (g_save_thread.joinable()) + g_save_thread.join(); } // Load the last state before loading the state -void State_UndoLoadState() +void UndoLoadState() { - State_LoadFromBuffer(&undoLoad); + if (!g_undo_load_buffer.empty()) + LoadFromBuffer(g_undo_load_buffer); + else + PanicAlert("There is nothing to undo!"); } // Load the state that the last save state overwritten on -void State_UndoSaveState() +void UndoSaveState() { - State_LoadAs((File::GetUserPath(D_STATESAVES_IDX) + "lastState.sav").c_str()); + LoadAs((File::GetUserPath(D_STATESAVES_IDX) + "lastState.sav").c_str()); } -size_t State_GetSize() -{ - // Measure the size of the buffer. - u8 *ptr = 0; - PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); - DoState(p); - return (size_t)ptr; -} +} // namespace State diff --git a/Source/Core/Core/Src/State.h b/Source/Core/Core/Src/State.h index 6102740946..791468f154 100644 --- a/Source/Core/Core/Src/State.h +++ b/Source/Core/Core/Src/State.h @@ -22,44 +22,37 @@ #include -typedef struct +namespace State { - u8 *buffer; - size_t size; -} saveStruct; -void State_Init(); -void State_Shutdown(); +void Init(); +void Shutdown(); + +void EnableCompression(bool compression); // These don't happen instantly - they get scheduled as events. // ...But only if we're not in the main cpu thread. // If we're in the main cpu thread then they run immediately instead // because some things (like Lua) need them to run immediately. // Slots from 0-99. -void State_Save(int slot); -void State_Load(int slot); -void State_Verify(int slot); +void Save(int slot); +void Load(int slot); +void Verify(int slot); -void State_SaveAs(const std::string &filename); -void State_LoadAs(const std::string &filename); -void State_VerifyAt(const std::string &filename); +void SaveAs(const std::string &filename); +void LoadAs(const std::string &filename); +void VerifyAt(const std::string &filename); -void State_LoadFromBuffer(u8 **buffer); -void State_SaveToBuffer(u8 **buffer); -void State_VerifyBuffer(u8 **buffer); +void SaveToBuffer(u8 **buffer); +void LoadFromBuffer(u8 **buffer); +void VerifyBuffer(u8 **buffer); -void State_LoadLastSaved(); -void State_UndoSaveState(); -void State_UndoLoadState(); +void LoadLastSaved(); +void UndoSaveState(); +void UndoLoadState(); -size_t State_GetSize(); -void State_Flush(); // wait until previously scheduled savestate event (if any) is done +void Flush(); // wait until previously scheduled savestate event (if any) is done - -typedef struct -{ - u8 gameID[6]; - size_t sz; -} state_header; +} #endif diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index d1e1b2a4ca..babd468fcd 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -885,20 +885,20 @@ void CFrame::OnKeyDown(wxKeyEvent& event) { int slot_number = event.GetKeyCode() - WXK_F1 + 1; if (event.GetModifiers() == wxMOD_NONE) - State_Load(slot_number); + State::Load(slot_number); else if (event.GetModifiers() == wxMOD_SHIFT) - State_Save(slot_number); + State::Save(slot_number); else event.Skip(); }*/ else if (event.GetKeyCode() == WXK_F11 && event.GetModifiers() == wxMOD_NONE) - State_LoadLastSaved(); + State::LoadLastSaved(); else if (event.GetKeyCode() == WXK_F12) { if (event.GetModifiers() == wxMOD_NONE) - State_UndoSaveState(); + State::UndoSaveState(); else if (event.GetModifiers() == wxMOD_SHIFT) - State_UndoLoadState(); + State::UndoLoadState(); else event.Skip(); } diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 1741b516b4..0ed693da50 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -1401,8 +1401,8 @@ void CFrame::OnLoadStateFromFile(wxCommandEvent& WXUNUSED (event)) wxFD_OPEN | wxFD_PREVIEW | wxFD_FILE_MUST_EXIST, this); - if(!path.IsEmpty()) - State_LoadAs((const char*)path.mb_str()); + if (!path.IsEmpty()) + State::LoadAs((const char*)path.mb_str()); } void CFrame::OnSaveStateToFile(wxCommandEvent& WXUNUSED (event)) @@ -1415,23 +1415,23 @@ void CFrame::OnSaveStateToFile(wxCommandEvent& WXUNUSED (event)) wxFD_SAVE, this); - if(! path.IsEmpty()) - State_SaveAs((const char*)path.mb_str()); + if (!path.IsEmpty()) + State::SaveAs((const char*)path.mb_str()); } void CFrame::OnLoadLastState(wxCommandEvent& WXUNUSED (event)) { - State_LoadLastSaved(); + State::LoadLastSaved(); } void CFrame::OnUndoLoadState(wxCommandEvent& WXUNUSED (event)) { - State_UndoLoadState(); + State::UndoLoadState(); } void CFrame::OnUndoSaveState(wxCommandEvent& WXUNUSED (event)) { - State_UndoSaveState(); + State::UndoSaveState(); } @@ -1439,14 +1439,14 @@ void CFrame::OnLoadState(wxCommandEvent& event) { int id = event.GetId(); int slot = id - IDM_LOADSLOT1 + 1; - State_Load(slot); + State::Load(slot); } void CFrame::OnSaveState(wxCommandEvent& event) { int id = event.GetId(); int slot = id - IDM_SAVESLOT1 + 1; - State_Save(slot); + State::Save(slot); } void CFrame::OnFrameSkip(wxCommandEvent& event) diff --git a/Source/Core/DolphinWX/Src/MainNoGUI.cpp b/Source/Core/DolphinWX/Src/MainNoGUI.cpp index 31a696db62..2f1dffc9e9 100644 --- a/Source/Core/DolphinWX/Src/MainNoGUI.cpp +++ b/Source/Core/DolphinWX/Src/MainNoGUI.cpp @@ -214,20 +214,20 @@ void X11_MainLoop() { int slot_number = key - XK_F1 + 1; if (event.xkey.state & ShiftMask) - State_Save(slot_number); + State::Save(slot_number); else - State_Load(slot_number); + State::Load(slot_number); } else if (key == XK_F9) Core::SaveScreenShot(); else if (key == XK_F11) - State_LoadLastSaved(); + State::LoadLastSaved(); else if (key == XK_F12) { if (event.xkey.state & ShiftMask) - State_UndoLoadState(); + State::UndoLoadState(); else - State_UndoSaveState(); + State::UndoSaveState(); } break; case FocusIn: diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp index 1ca0242c2f..5da8482e63 100644 --- a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp @@ -270,7 +270,6 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con // - EFB // EFB scale wxBoxSizer* const efb_scale_szr = new wxBoxSizer(wxHORIZONTAL); - // TODO: give this a label (?) const wxString efbscale_choices[] = { _("Fractional"), _("Integral [recommended]"), wxT("1x"), wxT("2x"), wxT("3x"), wxT("0.75x"), wxT("0.5x"), wxT("0.375x") }; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index f16d1464b9..2b6ee1af5b 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -171,7 +171,6 @@ bool VideoBackend::Initialize(void *&window_handle) return false; } - OSD::AddMessage("Dolphin Direct3D11 Video Backend.", 5000); s_BackendInitialized = true; return true; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index 191879170b..f6d38f24a0 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -156,7 +156,6 @@ bool VideoBackend::Initialize(void *&window_handle) return false; } - OSD::AddMessage("Dolphin Direct3D9 Video Backend.", 5000); s_BackendInitialized = true; return true; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index 354cf569f1..b9037e11a5 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -173,7 +173,6 @@ bool VideoBackend::Initialize(void *&window_handle) if (!OpenGL_Create(window_handle)) return false; - OSD::AddMessage("Dolphin OpenGL Video Backend.", 5000); s_BackendInitialized = true; return true; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp index 6d2a2723ff..7b0fb4e5da 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp @@ -178,17 +178,12 @@ void VideoSoftware::Video_EnterLoop() Common::YieldCPU(); } - if (!emuRunningState) + while (!emuRunningState && fifoStateRun) { - while (!emuRunningState && fifoStateRun) - { - g_video_backend->PeekMessages(); - Common::SleepCurrentThread(1); - } + g_video_backend->PeekMessages(); + Common::SleepCurrentThread(1); } - } - - + } } void VideoSoftware::Video_ExitLoop()