void SaveAs(const std::string& filename) { // Pause the core while we save the state bool wasUnpaused = Core::PauseAndLock(true); // Measure the size of the buffer. u8 *ptr = NULL; PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); DoState(p); const size_t buffer_size = reinterpret_cast<size_t>(ptr); // Then actually do the write. { std::lock_guard<std::mutex> lk(g_cs_current_buffer); g_current_buffer.resize(buffer_size); ptr = &g_current_buffer[0]; p.SetMode(PointerWrap::MODE_WRITE); DoState(p); } if (p.GetMode() == PointerWrap::MODE_WRITE) { Core::DisplayMessage("Saving State...", 1000); if ((Movie::IsRecordingInput() || Movie::IsPlayingInput()) && !Movie::IsJustStartingRecordingInputFromSaveState()) Movie::SaveRecording((filename + ".dtm").c_str()); else if (!Movie::IsRecordingInput() && !Movie::IsPlayingInput()) File::Delete(filename + ".dtm"); CompressAndDumpState_args save_args; save_args.buffer_vector = &g_current_buffer; save_args.buffer_mutex = &g_cs_current_buffer; save_args.filename = filename; Flush(); g_save_thread = std::thread(CompressAndDumpState, save_args); g_compressAndDumpStateSyncEvent.Wait(); g_last_filename = filename; } else { // someone aborted the save by changing the mode? Core::DisplayMessage("Unable to Save : Internal DoState Error", 4000); } // Resume the core and disable stepping Core::PauseAndLock(false, wasUnpaused); }
void SaveToBuffer(std::vector<u8>& buffer) { bool wasUnpaused = Core::PauseAndLock(true); u8* ptr = NULL; PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); DoState(p); const size_t buffer_size = reinterpret_cast<size_t>(ptr); buffer.resize(buffer_size); ptr = &buffer[0]; p.SetMode(PointerWrap::MODE_WRITE); DoState(p); Core::PauseAndLock(false, wasUnpaused); }
bool GameFileCache::SyncCacheFile(bool save) { const char* open_mode = save ? "wb" : "rb"; File::IOFile f(m_path, open_mode); if (!f) return false; bool success = false; if (save) { // Measure the size of the buffer. u8* ptr = nullptr; PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); DoState(&p); const size_t buffer_size = reinterpret_cast<size_t>(ptr); // Then actually do the write. std::vector<u8> buffer(buffer_size); ptr = &buffer[0]; p.SetMode(PointerWrap::MODE_WRITE); DoState(&p, buffer_size); if (f.WriteBytes(buffer.data(), buffer.size())) success = true; } else { std::vector<u8> buffer(f.GetSize()); if (!buffer.empty() && f.ReadBytes(buffer.data(), buffer.size())) { u8* ptr = buffer.data(); PointerWrap p(&ptr, PointerWrap::MODE_READ); DoState(&p, buffer.size()); if (p.GetMode() == PointerWrap::MODE_READ) success = true; } } if (!success) { // If some file operation failed, try to delete the probably-corrupted cache f.Close(); File::Delete(m_path); } return success; }
void VerifyBuffer(std::vector<u8>& buffer) { bool wasUnpaused = Core::PauseAndLock(true); u8* ptr = &buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); DoState(p); Core::PauseAndLock(false, wasUnpaused); }
void LoadFromBuffer(std::vector<u8>& buffer) { if (NetPlay::IsNetPlayRunning()) { OSD::AddMessage("Loading savestates is disabled in Netplay to prevent desyncs"); return; } bool wasUnpaused = Core::PauseAndLock(true); u8* ptr = &buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_READ); DoState(p); Core::PauseAndLock(false, wasUnpaused); }
void GCMemcardDirectory::DoState(PointerWrap &p) { m_LastBlock = -1; m_LastBlockAddress = nullptr; p.Do(m_SaveDirectory); p.DoPOD<Header>(m_hdr); p.DoPOD<Directory>(m_dir1); p.DoPOD<Directory>(m_dir2); p.DoPOD<BlockAlloc>(m_bat1); p.DoPOD<BlockAlloc>(m_bat2); int numSaves = (int)m_saves.size(); p.Do(numSaves); m_saves.resize(numSaves); for (auto itr = m_saves.begin(); itr != m_saves.end(); ++itr) { itr->DoState(p); } }
void VerifyAt(const std::string& filename) { bool wasUnpaused = Core::PauseAndLock(true); std::vector<u8> buffer; LoadFileStateData(filename, buffer); if (!buffer.empty()) { u8 *ptr = &buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); DoState(p); if (p.GetMode() == PointerWrap::MODE_VERIFY) Core::DisplayMessage(StringFromFormat("Verified state at %s", filename.c_str()).c_str(), 2000); else Core::DisplayMessage("Unable to Verify : Can't verify state from other revisions !", 4000); } Core::PauseAndLock(false, wasUnpaused); }
void VideoCommon_DoState(PointerWrap &p) { DoState(p); //TODO: search for more data that should be saved and add it here }
void LoadAs(const std::string& filename) { // Stop the core while we load the state bool wasUnpaused = Core::PauseAndLock(true); #if defined _DEBUG && defined _WIN32 // we use _CRTDBG_DELAY_FREE_MEM_DF (as a speed hack?), // but it was causing us to leak gigantic amounts of memory here, // enough that only a few savestates could be loaded before crashing, // so let's disable it temporarily. int tmpflag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); if (g_loadDepth == 0) _CrtSetDbgFlag(tmpflag & ~_CRTDBG_DELAY_FREE_MEM_DF); #endif g_loadDepth++; // Save temp buffer for undo load state { std::lock_guard<std::mutex> lk(g_cs_undo_load_buffer); SaveToBuffer(g_undo_load_buffer); } bool loaded = false; bool loadedSuccessfully = false; // brackets here are so buffer gets freed ASAP { std::vector<u8> buffer; LoadFileStateData(filename, buffer); if (!buffer.empty()) { u8 *ptr = &buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_READ); DoState(p); loaded = true; loadedSuccessfully = (p.GetMode() == PointerWrap::MODE_READ); } } if (loaded) { if (loadedSuccessfully) { Core::DisplayMessage(StringFromFormat("Loaded state from %s", filename.c_str()).c_str(), 2000); if (File::Exists(filename + ".dtm")) Movie::LoadInput((filename + ".dtm").c_str()); else if (!Movie::IsJustStartingRecordingInputFromSaveState()) Movie::EndPlayInput(false); } else { // failed to load Core::DisplayMessage("Unable to Load : Can't load state from other revisions !", 4000); // since we could be in an inconsistent state now (and might crash or whatever), undo. if (g_loadDepth < 2) UndoLoadState(); } } if (g_onAfterLoadCb) g_onAfterLoadCb(); g_loadDepth--; #if defined _DEBUG && defined _WIN32 // restore _CRTDBG_DELAY_FREE_MEM_DF if (g_loadDepth == 0) _CrtSetDbgFlag(tmpflag); #endif // resume dat core Core::PauseAndLock(false, wasUnpaused); }
MvcModel::StateType MvcModel::State() const { return DoState(); }
void LoadAs(const std::string& filename) { if (!Core::IsRunning()) { return; } else if (NetPlay::IsNetPlayRunning()) { OSD::AddMessage("Loading savestates is disabled in Netplay to prevent desyncs"); return; } // Stop the core while we load the state bool wasUnpaused = Core::PauseAndLock(true); g_loadDepth++; // Save temp buffer for undo load state if (!Movie::IsJustStartingRecordingInputFromSaveState()) { std::lock_guard<std::mutex> lk(g_cs_undo_load_buffer); SaveToBuffer(g_undo_load_buffer); if (Movie::IsMovieActive()) Movie::SaveRecording(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm"); else if (File::Exists(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm")) File::Delete(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm"); } bool loaded = false; bool loadedSuccessfully = false; std::string version_created_by; // brackets here are so buffer gets freed ASAP { std::vector<u8> buffer; LoadFileStateData(filename, buffer); if (!buffer.empty()) { u8* ptr = &buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_READ); version_created_by = DoState(p); loaded = true; loadedSuccessfully = (p.GetMode() == PointerWrap::MODE_READ); } } if (loaded) { if (loadedSuccessfully) { Core::DisplayMessage(StringFromFormat("Loaded state from %s", filename.c_str()), 2000); if (File::Exists(filename + ".dtm")) Movie::LoadInput(filename + ".dtm"); else if (!Movie::IsJustStartingRecordingInputFromSaveState() && !Movie::IsJustStartingPlayingInputFromSaveState()) Movie::EndPlayInput(false); } else { // failed to load Core::DisplayMessage("Unable to load: Can't load state from other versions!", 4000); if (!version_created_by.empty()) Core::DisplayMessage("The savestate was created using " + version_created_by, 4000); // since we could be in an inconsistent state now (and might crash or whatever), undo. if (g_loadDepth < 2) UndoLoadState(); } } if (g_onAfterLoadCb) g_onAfterLoadCb(); g_loadDepth--; // resume dat core Core::PauseAndLock(false, wasUnpaused); }
void VideoCommon_DoState(PointerWrap &p) { DoState(p); }