System: Add taints to save states
This informs the user they are loading a save state that at some point had potentially-game-breaking options enabled, and a reset is necessary to clear them.
This commit is contained in:
parent
2aea06526c
commit
baa9065d2e
|
@ -237,6 +237,8 @@ static EnableCodeList s_enabled_patches;
|
|||
|
||||
static ActiveCodeList s_frame_end_codes;
|
||||
|
||||
static u32 s_active_patch_count = 0;
|
||||
static u32 s_active_cheat_count = 0;
|
||||
static bool s_patches_enabled = false;
|
||||
static bool s_cheats_enabled = false;
|
||||
static bool s_database_cheat_codes_enabled = false;
|
||||
|
@ -828,6 +830,8 @@ void Cheats::ReloadCheats(bool reload_files, bool reload_enabled_list, bool verb
|
|||
|
||||
void Cheats::UnloadAll()
|
||||
{
|
||||
s_active_cheat_count = 0;
|
||||
s_active_patch_count = 0;
|
||||
s_frame_end_codes = ActiveCodeList();
|
||||
s_enabled_patches = EnableCodeList();
|
||||
s_enabled_cheats = EnableCodeList();
|
||||
|
@ -862,14 +866,15 @@ void Cheats::UpdateActiveCodes(bool reload_enabled_list, bool verbose, bool verb
|
|||
const size_t prev_count = s_frame_end_codes.size();
|
||||
s_frame_end_codes.clear();
|
||||
|
||||
u32 patch_count = 0;
|
||||
u32 cheat_count = 0;
|
||||
s_active_patch_count = 0;
|
||||
s_active_cheat_count = 0;
|
||||
|
||||
if (!g_settings.disable_all_enhancements)
|
||||
{
|
||||
const bool hc_mode_active = Achievements::IsHardcoreModeActive();
|
||||
patch_count = EnableCheats(s_patch_codes, s_enabled_patches, "Patches", hc_mode_active);
|
||||
cheat_count = AreCheatsEnabled() ? EnableCheats(s_cheat_codes, s_enabled_cheats, "Cheats", hc_mode_active) : 0;
|
||||
s_active_patch_count = EnableCheats(s_patch_codes, s_enabled_patches, "Patches", hc_mode_active);
|
||||
s_active_cheat_count =
|
||||
AreCheatsEnabled() ? EnableCheats(s_cheat_codes, s_enabled_cheats, "Cheats", hc_mode_active) : 0;
|
||||
}
|
||||
|
||||
// Display message on first boot when we load patches.
|
||||
|
@ -877,20 +882,23 @@ void Cheats::UpdateActiveCodes(bool reload_enabled_list, bool verbose, bool verb
|
|||
const size_t new_count = s_frame_end_codes.size();
|
||||
if (verbose || (verbose_if_changed && prev_count != new_count))
|
||||
{
|
||||
if (patch_count > 0)
|
||||
{
|
||||
Host::AddIconOSDMessage("LoadPatches", ICON_FA_BAND_AID,
|
||||
TRANSLATE_PLURAL_STR("Cheats", "%n game patches are active.", "OSD Message", patch_count),
|
||||
Host::OSD_INFO_DURATION);
|
||||
}
|
||||
if (cheat_count > 0)
|
||||
if (s_active_patch_count > 0)
|
||||
{
|
||||
System::SetTaint(System::Taint::Patches);
|
||||
Host::AddIconOSDMessage(
|
||||
"LoadCheats", ICON_EMOJI_WARNING,
|
||||
TRANSLATE_PLURAL_STR("Cheats", "%n cheats are enabled. This may crash games.", "OSD Message", cheat_count),
|
||||
Host::OSD_WARNING_DURATION);
|
||||
"LoadPatches", ICON_FA_BAND_AID,
|
||||
TRANSLATE_PLURAL_STR("Cheats", "%n game patches are active.", "OSD Message", s_active_patch_count),
|
||||
Host::OSD_INFO_DURATION);
|
||||
}
|
||||
else if (patch_count == 0)
|
||||
if (s_active_cheat_count > 0)
|
||||
{
|
||||
System::SetTaint(System::Taint::Cheats);
|
||||
Host::AddIconOSDMessage("LoadCheats", ICON_EMOJI_WARNING,
|
||||
TRANSLATE_PLURAL_STR("Cheats", "%n cheats are enabled. This may crash games.",
|
||||
"OSD Message", s_active_cheat_count),
|
||||
Host::OSD_WARNING_DURATION);
|
||||
}
|
||||
else if (s_active_patch_count == 0)
|
||||
{
|
||||
Host::RemoveKeyedOSDMessage("LoadPatches");
|
||||
Host::AddIconOSDMessage("LoadCheats", ICON_FA_BAND_AID,
|
||||
|
@ -936,6 +944,16 @@ bool Cheats::ApplyManualCode(const std::string_view name)
|
|||
return false;
|
||||
}
|
||||
|
||||
u32 Cheats::GetActivePatchCount()
|
||||
{
|
||||
return s_active_patch_count;
|
||||
}
|
||||
|
||||
u32 Cheats::GetActiveCheatCount()
|
||||
{
|
||||
return s_active_cheat_count;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// File Parsing
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -143,6 +143,12 @@ extern bool EnumerateManualCodes(std::function<bool(const std::string& name)> ca
|
|||
/// Invokes/applies the specified manually-activated code.
|
||||
extern bool ApplyManualCode(const std::string_view name);
|
||||
|
||||
/// Returns the number of active patches.
|
||||
extern u32 GetActivePatchCount();
|
||||
|
||||
/// Returns the number of active cheats.
|
||||
extern u32 GetActiveCheatCount();
|
||||
|
||||
// Config sections/keys to use to enable patches.
|
||||
extern const char* PATCHES_CONFIG_SECTION;
|
||||
extern const char* CHEATS_CONFIG_SECTION;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "common/types.h"
|
||||
|
||||
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 74;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 75;
|
||||
static constexpr u32 SAVE_STATE_MINIMUM_VERSION = 42;
|
||||
|
||||
static_assert(SAVE_STATE_VERSION >= SAVE_STATE_MINIMUM_VERSION);
|
||||
|
|
|
@ -151,6 +151,8 @@ static bool ShouldStartPaused();
|
|||
|
||||
/// Checks for settings changes, std::move() the old settings away for comparing beforehand.
|
||||
static void CheckForSettingsChanges(const Settings& old_settings);
|
||||
static void SetTaintsFromSettings();
|
||||
static void WarnAboutStateTaints(u32 state_taints);
|
||||
static void WarnAboutUnsafeSettings();
|
||||
static void LogUnsafeSettingsToConsole(const SmallStringBase& messages);
|
||||
|
||||
|
@ -251,6 +253,7 @@ static u32 s_frame_number = 1;
|
|||
static u32 s_internal_frame_number = 1;
|
||||
static const BIOS::ImageInfo* s_bios_image_info = nullptr;
|
||||
static BIOS::ImageInfo::Hash s_bios_hash = {};
|
||||
static u32 s_taints = 0;
|
||||
|
||||
static std::string s_running_game_path;
|
||||
static std::string s_running_game_serial;
|
||||
|
@ -660,6 +663,49 @@ bool System::IsPALRegion()
|
|||
return s_region == ConsoleRegion::PAL;
|
||||
}
|
||||
|
||||
const char* System::GetTaintDisplayName(Taint taint)
|
||||
{
|
||||
static constexpr const std::array<const char*, static_cast<size_t>(Taint::MaxCount)> names = {{
|
||||
TRANSLATE_DISAMBIG_NOOP("System", "CPU Overclock", "Taint"),
|
||||
TRANSLATE_DISAMBIG_NOOP("System", "CD-ROM Read Speedup", "Taint"),
|
||||
TRANSLATE_DISAMBIG_NOOP("System", "CD-ROM Seek Speedup", "Taint"),
|
||||
TRANSLATE_DISAMBIG_NOOP("System", "Force Frame Timings", "Taint"),
|
||||
TRANSLATE_DISAMBIG_NOOP("System", "8MB RAM", "Taint"),
|
||||
TRANSLATE_DISAMBIG_NOOP("System", "Cheats", "Taint"),
|
||||
TRANSLATE_DISAMBIG_NOOP("System", "Game Patches", "Taint"),
|
||||
}};
|
||||
|
||||
return names[static_cast<size_t>(taint)];
|
||||
}
|
||||
|
||||
const char* System::GetTaintName(Taint taint)
|
||||
{
|
||||
static constexpr const std::array<const char*, static_cast<size_t>(Taint::MaxCount)> names = {{
|
||||
"CPUOverclock",
|
||||
"CDROMReadSpeedup",
|
||||
"CDROMSeekSpeedup",
|
||||
"ForceFrameTimings",
|
||||
"RAM8MB",
|
||||
"Cheats",
|
||||
"Patches",
|
||||
}};
|
||||
|
||||
return names[static_cast<size_t>(taint)];
|
||||
}
|
||||
|
||||
bool System::HasTaint(Taint taint)
|
||||
{
|
||||
return (s_taints & (1u << static_cast<u8>(taint))) != 0u;
|
||||
}
|
||||
|
||||
void System::SetTaint(Taint taint)
|
||||
{
|
||||
if (!HasTaint(taint))
|
||||
WARNING_LOG("Setting system taint: {}", GetTaintName(taint));
|
||||
|
||||
s_taints |= (1u << static_cast<u8>(taint));
|
||||
}
|
||||
|
||||
TickCount System::GetMaxSliceTicks()
|
||||
{
|
||||
return s_max_slice_ticks;
|
||||
|
@ -2039,6 +2085,7 @@ void System::DestroySystem()
|
|||
Host::ReleaseGPUDevice();
|
||||
}
|
||||
|
||||
s_taints = 0;
|
||||
s_bios_hash = {};
|
||||
s_bios_image_info = nullptr;
|
||||
s_exe_override = {};
|
||||
|
@ -2464,6 +2511,11 @@ bool System::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_di
|
|||
sw.Do(&s_region);
|
||||
}
|
||||
|
||||
u32 state_taints = s_taints;
|
||||
sw.DoEx(&state_taints, 75, static_cast<u32>(0));
|
||||
if (state_taints != s_taints) [[unlikely]]
|
||||
WarnAboutStateTaints(state_taints);
|
||||
|
||||
sw.Do(&s_frame_number);
|
||||
sw.Do(&s_internal_frame_number);
|
||||
|
||||
|
@ -2600,6 +2652,9 @@ void System::InternalReset()
|
|||
if (IsShutdown())
|
||||
return;
|
||||
|
||||
// reset and clear taints
|
||||
SetTaintsFromSettings();
|
||||
|
||||
TimingEvents::Reset();
|
||||
CPU::Reset();
|
||||
CPU::CodeCache::Reset();
|
||||
|
@ -4580,6 +4635,54 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
|||
}
|
||||
}
|
||||
|
||||
void System::SetTaintsFromSettings()
|
||||
{
|
||||
s_taints = 0;
|
||||
|
||||
if (g_settings.cdrom_read_speedup > 1)
|
||||
SetTaint(Taint::CDROMReadSpeedup);
|
||||
if (g_settings.cdrom_seek_speedup > 1)
|
||||
SetTaint(Taint::CDROMSeekSpeedup);
|
||||
if (g_settings.cpu_overclock_active)
|
||||
SetTaint(Taint::CPUOverclock);
|
||||
if (g_settings.gpu_force_video_timing != ForceVideoTimingMode::Disabled)
|
||||
SetTaint(Taint::ForceFrameTimings);
|
||||
if (g_settings.enable_8mb_ram)
|
||||
SetTaint(Taint::RAM8MB);
|
||||
if (Cheats::GetActivePatchCount() > 0)
|
||||
SetTaint(Taint::Patches);
|
||||
if (Cheats::GetActiveCheatCount() > 0)
|
||||
SetTaint(Taint::Cheats);
|
||||
}
|
||||
|
||||
void System::WarnAboutStateTaints(u32 state_taints)
|
||||
{
|
||||
const u32 taints_active_in_file = state_taints & ~s_taints;
|
||||
if (taints_active_in_file == 0)
|
||||
return;
|
||||
|
||||
LargeString messages;
|
||||
for (u32 i = 0; i < static_cast<u32>(Taint::MaxCount); i++)
|
||||
{
|
||||
if (!(taints_active_in_file & (1u << i)))
|
||||
continue;
|
||||
|
||||
if (messages.empty())
|
||||
{
|
||||
messages.append_format(
|
||||
"{} {}\n", ICON_EMOJI_WARNING,
|
||||
TRANSLATE_SV("System", "This save state was created with the following tainted options, and may\n"
|
||||
" be unstable. You will need to reset the system to clear any effects."));
|
||||
}
|
||||
|
||||
messages.append(" \u2022 ");
|
||||
messages.append(GetTaintDisplayName(static_cast<Taint>(i)));
|
||||
messages.append('\n');
|
||||
}
|
||||
|
||||
Host::AddKeyedOSDWarning("SystemTaintsFromState", std::string(messages.view()), Host::OSD_WARNING_DURATION);
|
||||
}
|
||||
|
||||
void System::WarnAboutUnsafeSettings()
|
||||
{
|
||||
LargeString messages;
|
||||
|
|
|
@ -104,6 +104,18 @@ enum class BootMode
|
|||
BootPSF,
|
||||
};
|
||||
|
||||
enum class Taint : u8
|
||||
{
|
||||
CPUOverclock,
|
||||
CDROMReadSpeedup,
|
||||
CDROMSeekSpeedup,
|
||||
ForceFrameTimings,
|
||||
RAM8MB,
|
||||
Cheats,
|
||||
Patches,
|
||||
MaxCount,
|
||||
};
|
||||
|
||||
extern TickCount g_ticks_per_second;
|
||||
|
||||
/// Returns true if the filename is a PlayStation executable we can inject.
|
||||
|
@ -156,6 +168,12 @@ ConsoleRegion GetRegion();
|
|||
DiscRegion GetDiscRegion();
|
||||
bool IsPALRegion();
|
||||
|
||||
/// Taints - flags that are set on the system and only cleared on reset.
|
||||
const char* GetTaintDisplayName(Taint taint);
|
||||
const char* GetTaintName(Taint taint);
|
||||
bool HasTaint(Taint taint);
|
||||
void SetTaint(Taint taint);
|
||||
|
||||
ALWAYS_INLINE TickCount GetTicksPerSecond()
|
||||
{
|
||||
return g_ticks_per_second;
|
||||
|
|
Loading…
Reference in New Issue