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 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); }
BOOL BSNetPack::SplitPack(BYTE* recvBuffer, UINT nRecvLen, UINT& nSavedLen) { BSAutoLock lock(&m_mutexBuffer); //TRACE("IntoSplitPack:%X len:%X\n:", *recvBuffer, nRecvLen); // 遍历RecvBuffer for (UINT i=0;i<nRecvLen;) { // 未取得当前包长度时 if (!IsHeaderFinished()) { // 计算包头长度 UINT nRealHeaderLen = GetHeaderLen(); // 当未收够包头长度时 if (ReceivedLen < nRealHeaderLen) { int tempcopylen = nRealHeaderLen - ReceivedLen; if (nRecvLen-i<tempcopylen) { tempcopylen=nRecvLen-i; SaveToBuffer((recvBuffer+i), tempcopylen); i+=tempcopylen; continue; } SaveToBuffer((recvBuffer+i), tempcopylen); i+=tempcopylen; } // 获取包长度(包括包头和包内容) ParsePackLen(); //TRACE("TotalLen:%d\n", nLen); } if ( GetPackLen() < GetHeaderLen()) { // pack len Error Handling ASSERT(FALSE); TRACE("ErrorPackLen:%d%X, len:%d\n", *(BYTE*)(Buffer), GetPackLen()); BSLogger::SysLog(LOG_ERROR, "报文长度不正确 %u", GetPackLen()); ClearBuffer(); return FALSE; break; } // 本次分包报文在当前recv到的buffer里可以读取的长度 int nPackThisRead = (nRecvLen-i) < (PackLen-ReceivedLen) ? (nRecvLen-i) : (PackLen-ReceivedLen); //TRACE("PackThisRead:%d\n", nPackThisRead); if(PackLen>MaxBufferLen || ReceivedLen+nPackThisRead>MaxBufferLen) { // pack len too big, drop it. ASSERT(FALSE); i += nPackThisRead; TRACE("DropTooBigPack:%X, len:%d\n", *(BYTE*)(Buffer), PackLen); BSLogger::SysLog(LOG_ERROR, "报文长度过大 %u", PackLen); ClearBuffer(); return FALSE; break; } SaveToBuffer(recvBuffer+i, nPackThisRead); i += nPackThisRead; nSavedLen = i; // 收到一个完整报文 if (IsPackFinished()) { return TRUE; } } return TRUE; };