System: Fix per-game achievements hardcore mode

By mostly reverting 4dd6365a99, I didn't
think of all the implications. Not just per-game HC mode, but it's also
problematic on Android too.
This commit is contained in:
Stenzek 2025-01-30 01:14:38 +10:00
parent 02234715c5
commit d314b25f91
No known key found for this signature in database
3 changed files with 65 additions and 31 deletions

View File

@ -2228,6 +2228,26 @@ bool Achievements::ConfirmSystemReset()
return true; return true;
} }
bool Achievements::ConfirmHardcoreModeDisable(const char* trigger)
{
#ifdef ENABLE_RAINTEGRATION
if (IsUsingRAIntegration())
return (RA_WarnDisableHardcore(trigger) != 0);
#endif
// I really hope this doesn't deadlock :/
const bool confirmed = Host::ConfirmMessage(
TRANSLATE("Achievements", "Confirm Hardcore Mode Disable"),
fmt::format(TRANSLATE_FS("Achievements", "{0} cannot be performed while hardcore mode is active. Do you "
"want to disable hardcore mode? {0} will be cancelled if you select No."),
trigger));
if (!confirmed)
return false;
DisableHardcoreMode();
return true;
}
void Achievements::ConfirmHardcoreModeDisableAsync(const char* trigger, std::function<void(bool)> callback) void Achievements::ConfirmHardcoreModeDisableAsync(const char* trigger, std::function<void(bool)> callback)
{ {
auto real_callback = [callback = std::move(callback)](bool res) mutable { auto real_callback = [callback = std::move(callback)](bool res) mutable {
@ -2249,7 +2269,7 @@ void Achievements::ConfirmHardcoreModeDisableAsync(const char* trigger, std::fun
#endif #endif
Host::ConfirmMessageAsync( Host::ConfirmMessageAsync(
TRANSLATE_STR("Achievements", "Confirm Hardcore Mode"), TRANSLATE_STR("Achievements", "Confirm Hardcore Mode Disable"),
fmt::format(TRANSLATE_FS("Achievements", "{0} cannot be performed while hardcore mode is active. Do you want to " fmt::format(TRANSLATE_FS("Achievements", "{0} cannot be performed while hardcore mode is active. Do you want to "
"disable hardcore mode? {0} will be cancelled if you select No."), "disable hardcore mode? {0} will be cancelled if you select No."),
trigger), trigger),

View File

@ -116,6 +116,7 @@ bool ResetHardcoreMode(bool is_booting);
void DisableHardcoreMode(); void DisableHardcoreMode();
/// Prompts the user to disable hardcore mode, if they agree, returns true. /// Prompts the user to disable hardcore mode, if they agree, returns true.
bool ConfirmHardcoreModeDisable(const char* trigger);
void ConfirmHardcoreModeDisableAsync(const char* trigger, std::function<void(bool)> callback); void ConfirmHardcoreModeDisableAsync(const char* trigger, std::function<void(bool)> callback);
/// Returns true if hardcore mode is active, and functionality should be restricted. /// Returns true if hardcore mode is active, and functionality should be restricted.

View File

@ -1741,36 +1741,6 @@ bool System::BootSystem(SystemBootParameters parameters, Error* error)
return false; return false;
} }
// Achievement hardcore checks before committing to anything.
if (!IsReplayingGPUDump())
{
// Check for resuming with hardcore mode.
if (parameters.disable_achievements_hardcore_mode)
Achievements::DisableHardcoreMode();
else
Achievements::ResetHardcoreMode(true);
if ((!parameters.save_state.empty() || !exe_override.empty()) && Achievements::IsHardcoreModeActive())
{
const bool is_exe_override_boot = parameters.save_state.empty();
Achievements::ConfirmHardcoreModeDisableAsync(
is_exe_override_boot ? TRANSLATE("Achievements", "Overriding executable") :
TRANSLATE("Achievements", "Resuming state"),
[parameters = std::move(parameters)](bool approved) mutable {
if (approved)
{
Host::RunOnCPUThread([parameters = std::move(parameters)]() mutable {
parameters.disable_achievements_hardcore_mode = true;
BootSystem(std::move(parameters), nullptr);
});
}
});
// Technically a failure, but user-initiated. Returning false here would try to display a non-existent error.
return true;
}
}
// Can't early cancel without destroying past this point. // Can't early cancel without destroying past this point.
Assert(s_state.state == State::Shutdown); Assert(s_state.state == State::Shutdown);
s_state.state = State::Starting; s_state.state = State::Starting;
@ -1800,6 +1770,49 @@ bool System::BootSystem(SystemBootParameters parameters, Error* error)
exe_override = std::move(parameters.override_exe); exe_override = std::move(parameters.override_exe);
} }
// Achievement hardcore checks before committing to anything.
if (disc)
{
// Check for resuming with hardcore mode.
if (parameters.disable_achievements_hardcore_mode)
Achievements::DisableHardcoreMode();
else
Achievements::ResetHardcoreMode(true);
if ((!parameters.save_state.empty() || !exe_override.empty()) && Achievements::IsHardcoreModeActive())
{
const bool is_exe_override_boot = parameters.save_state.empty();
bool cancelled;
if (FullscreenUI::IsInitialized())
{
Achievements::ConfirmHardcoreModeDisableAsync(is_exe_override_boot ?
TRANSLATE("Achievements", "Overriding executable") :
TRANSLATE("Achievements", "Resuming state"),
[parameters = std::move(parameters)](bool approved) mutable {
if (approved)
{
parameters.disable_achievements_hardcore_mode = true;
BootSystem(std::move(parameters), nullptr);
}
});
cancelled = true;
}
else
{
cancelled = !Achievements::ConfirmHardcoreModeDisable(is_exe_override_boot ?
TRANSLATE("Achievements", "Overriding executable") :
TRANSLATE("Achievements", "Resuming state"));
}
if (cancelled)
{
// Technically a failure, but user-initiated. Returning false here would try to display a non-existent error.
DestroySystem();
return true;
}
}
}
// Are we fast booting? Must be checked after updating game settings. // Are we fast booting? Must be checked after updating game settings.
if (boot_mode == BootMode::FullBoot && disc_region != DiscRegion::NonPS1 && if (boot_mode == BootMode::FullBoot && disc_region != DiscRegion::NonPS1 &&
parameters.override_fast_boot.value_or(static_cast<bool>(g_settings.bios_patch_fast_boot))) parameters.override_fast_boot.value_or(static_cast<bool>(g_settings.bios_patch_fast_boot)))