diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index db983922ca..1dee9fa660 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -197,16 +197,16 @@ int g_screenshotFailures; } void Enqueue(const SaveState::Operation &op) { - if (!NetworkAllowSaveState()) { + // These two both refuse the operation, and both say so - dropping it silently just + // looks like the hotkey didn't work. Callers that ask the same questions themselves + // return before getting here, so nothing shows a message twice. + if (NetworkWarnUserIfOnlineAndCantSavestate()) { return; } - if (Achievements::HardcoreModeActive()) { - if (g_Config.bAchievementsSaveStateInHardcoreMode && ((op.type == SaveState::OperationType::Save))) { - // We allow saving in hardcore mode if this setting is on. - } else { - // Operation not allowed - return; - } + // Hardcore mode bans loading savestates outright, and saving too unless the user opted + // back into that. + if (Achievements::WarnUserIfHardcoreModeActive(op.type == OperationType::Save)) { + return; } std::lock_guard guard(mutex); @@ -218,7 +218,7 @@ int g_screenshotFailures; } void Load(const Path &filename, int slot, Callback callback) { - if (!NetworkAllowSaveState()) { + if (NetworkWarnUserIfOnlineAndCantSavestate()) { return; } @@ -229,7 +229,7 @@ int g_screenshotFailures; } void Save(const Path &filename, int slot, Callback callback) { - if (!NetworkAllowSaveState()) { + if (NetworkWarnUserIfOnlineAndCantSavestate()) { return; } @@ -399,7 +399,7 @@ int g_screenshotFailures; } void LoadSlot(std::string_view gamePrefix, int slot, Callback callback) { - if (!NetworkAllowSaveState()) { + if (NetworkWarnUserIfOnlineAndCantSavestate()) { return; } @@ -440,7 +440,7 @@ int g_screenshotFailures; } bool UndoLoad(std::string_view gamePrefix, Callback callback) { - if (!NetworkAllowSaveState()) { + if (NetworkWarnUserIfOnlineAndCantSavestate()) { return false; } @@ -466,7 +466,7 @@ int g_screenshotFailures; } void SaveSlot(std::string_view gamePrefix, int slot, Callback callback) { - if (!NetworkAllowSaveState()) { + if (NetworkWarnUserIfOnlineAndCantSavestate()) { return; } @@ -511,7 +511,7 @@ int g_screenshotFailures; } bool UndoSaveSlot(std::string_view gamePrefix, int slot) { - if (!NetworkAllowSaveState()) { + if (NetworkWarnUserIfOnlineAndCantSavestate()) { return false; } @@ -544,7 +544,7 @@ int g_screenshotFailures; } bool UndoLastSave(std::string_view gamePrefix) { - if (!NetworkAllowSaveState()) { + if (NetworkWarnUserIfOnlineAndCantSavestate()) { return false; } @@ -810,6 +810,16 @@ int g_screenshotFailures; SaveStart state; for (const auto &op : operations) { + // Re-check here, and not just in Enqueue: during boot, RetroAchievements is still + // identifying the game asynchronously, and until it's done hardcore mode doesn't + // read as active yet. An operation queued in that window (a hotkey press, --state, + // auto-load) passed the check in Enqueue and would otherwise be applied here, after + // identification has finished and hardcore mode has come up. + if (Achievements::WarnUserIfHardcoreModeActive(op.type == OperationType::Save)) { + WARN_LOG(Log::SaveState, "Dropping queued savestate operation - hardcore mode is active"); + continue; + } + CChunkFileReader::Error result; Status callbackResult; std::string callbackMessage; diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index 5c43b5c25f..c652c919fa 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -58,6 +58,7 @@ #include "Core/ConfigValues.h" #include "Core/System.h" #include "Core/Reporting.h" +#include "Core/RetroAchievements.h" #include "Core/CoreParameter.h" #include "Core/HLE/sceKernel.h" // GPI/GPO #include "Core/MIPS/MIPSTables.h" @@ -187,6 +188,10 @@ void DevMenuScreen::CreatePopupContents(UI::ViewGroup *parent) { }); items->Add(new Choice(dev->T("Toggle Freeze")))->OnClick.Add([](UI::EventParams &e) { + // Freezing restores a savestate every frame, so it's not allowed in hardcore mode. + if (Achievements::WarnUserIfHardcoreModeActive(false)) { + return; + } if (PSP_CoreParameter().frozen) { PSP_CoreParameter().frozen = false; } else { diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 618ee0dd72..014db251d9 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1709,8 +1709,14 @@ ScreenRenderFlags EmuScreen::RunEmulation(bool skipBufferEffects) { gpu->BeginHostFrame(displayLayoutConfig); } - // Freeze-frame functionality (loads a savestate on every frame). - if (PSP_CoreParameter().freezeNext) { + // Freeze-frame functionality (loads a savestate on every frame). It's a savestate load + // like any other, so it's banned in hardcore mode - and checked here rather than only + // where it's toggled, since hardcore mode can come up after the fact, once the game + // has been identified. + if (Achievements::HardcoreModeActive()) { + PSP_CoreParameter().freezeNext = false; + PSP_CoreParameter().frozen = false; + } else if (PSP_CoreParameter().freezeNext) { PSP_CoreParameter().frozen = true; PSP_CoreParameter().freezeNext = false; SaveState::SaveToRam(freezeState_);