diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index db983922ca..8f4ba4a853 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -196,17 +196,18 @@ int g_screenshotFailures; pspFileSystem.DoState(p); } - void Enqueue(const SaveState::Operation &op) { - if (!NetworkAllowSaveState()) { - return; + // Hardcore mode bans loading savestates outright, and saving too unless the user opted + // back into that. + bool BannedInHardcoreMode(OperationType type) { + if (!Achievements::HardcoreModeActive()) { + return false; } - 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; - } + return !(g_Config.bAchievementsSaveStateInHardcoreMode && type == OperationType::Save); + } + + void Enqueue(const SaveState::Operation &op) { + if (!NetworkAllowSaveState() || BannedInHardcoreMode(op.type)) { + return; } std::lock_guard guard(mutex); @@ -810,6 +811,17 @@ 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 (BannedInHardcoreMode(op.type)) { + WARN_LOG(Log::SaveState, "Dropping queued savestate operation - hardcore mode is active"); + Achievements::WarnUserIfHardcoreModeActive(op.type == OperationType::Save); + continue; + } + CChunkFileReader::Error result; Status callbackResult; std::string callbackMessage;