void Process() { #ifndef USING_GLES2 if (g_Config.iRewindFlipFrequency != 0 && gpuStats.numFlips != 0) CheckRewindState(); #endif if (!needsProcess) return; needsProcess = false; if (!__KernelIsRunning()) { ERROR_LOG(COMMON, "Savestate failure: Unable to load without kernel, this should never happen."); return; } std::vector<Operation> operations = Flush(); SaveStart state; for (size_t i = 0, n = operations.size(); i < n; ++i) { Operation &op = operations[i]; CChunkFileReader::Error result; bool callbackResult; std::string reason; I18NCategory *s = GetI18NCategory("Screen"); // I couldn't stand the inconsistency. But trying not to break old lang files. const char *i18nLoadFailure = s->T("Load savestate failed", ""); const char *i18nSaveFailure = s->T("Save State Failed", ""); if (strlen(i18nLoadFailure) == 0) i18nLoadFailure = s->T("Failed to load state"); if (strlen(i18nSaveFailure) == 0) i18nSaveFailure = s->T("Failed to save state"); switch (op.type) { case SAVESTATE_LOAD: INFO_LOG(COMMON, "Loading state from %s", op.filename.c_str()); result = CChunkFileReader::Load(op.filename, REVISION, PPSSPP_GIT_VERSION, state, &reason); if (result == CChunkFileReader::ERROR_NONE) { osm.Show(s->T("Loaded State"), 2.0); callbackResult = true; } else if (result == CChunkFileReader::ERROR_BROKEN_STATE) { HandleFailure(); osm.Show(i18nLoadFailure, 2.0); ERROR_LOG(COMMON, "Load state failure: %s", reason.c_str()); callbackResult = false; } else { osm.Show(s->T(reason.c_str(), i18nLoadFailure), 2.0); callbackResult = false; } break; case SAVESTATE_SAVE: INFO_LOG(COMMON, "Saving state to %s", op.filename.c_str()); result = CChunkFileReader::Save(op.filename, REVISION, PPSSPP_GIT_VERSION, state); if (result == CChunkFileReader::ERROR_NONE) { osm.Show(s->T("Saved State"), 2.0); callbackResult = true; } else if (result == CChunkFileReader::ERROR_BROKEN_STATE) { HandleFailure(); osm.Show(i18nSaveFailure, 2.0); ERROR_LOG(COMMON, "Save state failure: %s", reason.c_str()); callbackResult = false; } else { osm.Show(i18nSaveFailure, 2.0); callbackResult = false; } break; case SAVESTATE_VERIFY: INFO_LOG(COMMON, "Verifying save state system"); callbackResult = CChunkFileReader::Verify(state) == CChunkFileReader::ERROR_NONE; break; case SAVESTATE_REWIND: INFO_LOG(COMMON, "Rewinding to recent savestate snapshot"); result = rewindStates.Restore(); if (result == CChunkFileReader::ERROR_NONE) { osm.Show(s->T("Loaded State"), 2.0); callbackResult = true; } else if (result == CChunkFileReader::ERROR_BROKEN_STATE) { // Cripes. Good news is, we might have more. Let's try those too, better than a reset. if (HandleFailure()) { // Well, we did rewind, even if too much... osm.Show(s->T("Loaded State"), 2.0); callbackResult = true; } else { osm.Show(i18nLoadFailure, 2.0); callbackResult = false; } } else { osm.Show(i18nLoadFailure, 2.0); callbackResult = false; } break; default: ERROR_LOG(COMMON, "Savestate failure: unknown operation type %d", op.type); callbackResult = false; break; } if (op.callback) op.callback(callbackResult, op.cbUserData); } }
void Process() { #ifndef MOBILE_DEVICE if (g_Config.iRewindFlipFrequency != 0 && gpuStats.numFlips != 0) CheckRewindState(); #endif if (!needsProcess) return; needsProcess = false; if (!__KernelIsRunning()) { ERROR_LOG(COMMON, "Savestate failure: Unable to load without kernel, this should never happen."); return; } std::vector<Operation> operations = Flush(); SaveStart state; for (size_t i = 0, n = operations.size(); i < n; ++i) { Operation &op = operations[i]; CChunkFileReader::Error result; bool callbackResult; std::string callbackMessage; std::string reason; I18NCategory *sc = GetI18NCategory("Screen"); const char *i18nLoadFailure = sc->T("Load savestate failed", ""); const char *i18nSaveFailure = sc->T("Save State Failed", ""); if (strlen(i18nLoadFailure) == 0) i18nLoadFailure = sc->T("Failed to load state"); if (strlen(i18nSaveFailure) == 0) i18nSaveFailure = sc->T("Failed to save state"); switch (op.type) { case SAVESTATE_LOAD: INFO_LOG(COMMON, "Loading state from %s", op.filename.c_str()); result = CChunkFileReader::Load(op.filename, PPSSPP_GIT_VERSION, state, &reason); if (result == CChunkFileReader::ERROR_NONE) { callbackMessage = sc->T("Loaded State"); callbackResult = true; hasLoadedState = true; } else if (result == CChunkFileReader::ERROR_BROKEN_STATE) { HandleFailure(); callbackMessage = i18nLoadFailure; ERROR_LOG(COMMON, "Load state failure: %s", reason.c_str()); callbackResult = false; } else { callbackMessage = sc->T(reason.c_str(), i18nLoadFailure); callbackResult = false; } break; case SAVESTATE_SAVE: INFO_LOG(COMMON, "Saving state to %s", op.filename.c_str()); result = CChunkFileReader::Save(op.filename, g_paramSFO.GetValueString("TITLE"), PPSSPP_GIT_VERSION, state); if (result == CChunkFileReader::ERROR_NONE) { callbackMessage = sc->T("Saved State"); callbackResult = true; } else if (result == CChunkFileReader::ERROR_BROKEN_STATE) { HandleFailure(); callbackMessage = i18nSaveFailure; ERROR_LOG(COMMON, "Save state failure: %s", reason.c_str()); callbackResult = false; } else { callbackMessage = i18nSaveFailure; callbackResult = false; } break; case SAVESTATE_VERIFY: callbackResult = CChunkFileReader::Verify(state) == CChunkFileReader::ERROR_NONE; if (callbackResult) { INFO_LOG(COMMON, "Verified save state system"); } else { ERROR_LOG(COMMON, "Save state system verification failed"); } break; case SAVESTATE_REWIND: INFO_LOG(COMMON, "Rewinding to recent savestate snapshot"); result = rewindStates.Restore(); if (result == CChunkFileReader::ERROR_NONE) { callbackMessage = sc->T("Loaded State"); callbackResult = true; hasLoadedState = true; } else if (result == CChunkFileReader::ERROR_BROKEN_STATE) { // Cripes. Good news is, we might have more. Let's try those too, better than a reset. if (HandleFailure()) { // Well, we did rewind, even if too much... callbackMessage = sc->T("Loaded State"); callbackResult = true; hasLoadedState = true; } else { callbackMessage = i18nLoadFailure; callbackResult = false; } } else { callbackMessage = i18nLoadFailure; callbackResult = false; } break; case SAVESTATE_SAVE_SCREENSHOT: callbackResult = TakeGameScreenshot(op.filename.c_str(), SCREENSHOT_JPG, SCREENSHOT_RENDER); if (!callbackResult) { ERROR_LOG(COMMON, "Failed to take a screenshot for the savestate! %s", op.filename.c_str()); } break; default: ERROR_LOG(COMMON, "Savestate failure: unknown operation type %d", op.type); callbackResult = false; break; } if (op.callback) op.callback(callbackResult, callbackMessage, op.cbUserData); } if (operations.size()) { // Avoid triggering frame skipping due to slowdown __DisplaySetWasPaused(); } }