From 81a7b147fcd656ac88858aa38cb1a59878c14d38 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Wed, 27 May 2020 02:06:56 +1000 Subject: [PATCH] System: Add option to disable loading memory cards from save states --- src/core/host_interface.cpp | 1 + src/core/pad.cpp | 19 +++++++++++++-- src/core/settings.cpp | 2 ++ src/core/settings.h | 1 + src/duckstation-qt/generalsettingswidget.cpp | 6 +++++ src/duckstation-qt/generalsettingswidget.ui | 25 +++++++++++++------- src/duckstation-sdl/sdl_host_interface.cpp | 2 ++ 7 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index eeffacd83..d5c6ee43b 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -1022,6 +1022,7 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si) si.SetStringValue("Controller1", "Type", Settings::GetControllerTypeName(ControllerType::DigitalController)); si.SetStringValue("Controller2", "Type", Settings::GetControllerTypeName(ControllerType::None)); + si.SetBoolValue("MemoryCards", "LoadFromSaveStates", false); si.SetStringValue("MemoryCards", "Card1Type", Settings::GetMemoryCardTypeName(MemoryCardType::PerGameTitle)); si.SetStringValue("MemoryCards", "Card1Path", "memcards/shared_card_1.mcd"); si.SetStringValue("MemoryCards", "Card2Type", "None"); diff --git a/src/core/pad.cpp b/src/core/pad.cpp index 84886c7db..bdc0214f4 100644 --- a/src/core/pad.cpp +++ b/src/core/pad.cpp @@ -62,16 +62,31 @@ bool Pad::DoState(StateWrapper& sw) bool card_present = static_cast(m_memory_cards[i]); sw.Do(&card_present); + if (sw.IsReading() && card_present && !m_system->GetSettings().load_memory_cards_from_save_states) + { + Log_WarningPrintf("Skipping loading memory card %u from save state.", i + 1u); + + MemoryCard dummy_card(m_system); + if (!sw.DoMarker("MemoryCard") || !dummy_card.DoState(sw)) + return false; + + // we do need to reset the existing card though, in case it was in the middle of a write + if (m_memory_cards[i]) + m_memory_cards[i]->Reset(); + + continue; + } + if (card_present && !m_memory_cards[i]) { m_system->GetHostInterface()->AddFormattedOSDMessage( - 2.0f, "Memory card %c present in save state but not in system. Creating temporary card.", i + 1); + 2.0f, "Memory card %u present in save state but not in system. Creating temporary card.", i + 1u); m_memory_cards[i] = MemoryCard::Create(m_system); } else if (!card_present && m_memory_cards[i]) { m_system->GetHostInterface()->AddFormattedOSDMessage( - 2.0f, "Memory card %u present in system but not in save state. Removing card.", i + 1); + 2.0f, "Memory card %u present in system but not in save state. Removing card.", i + 1u); m_memory_cards[i].reset(); } diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 1df322756..5a433e353 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -74,6 +74,7 @@ void Settings::Load(SettingsInterface& si) // NOTE: The default value here if not present in the config is shared, but SetDefaultSettings() makes per-game. // This is so we don't break older builds which had the shared card by default. + load_memory_cards_from_save_states = si.GetBoolValue("MemoryCards", "LoadFromSaveStates", false); memory_card_types[0] = ParseMemoryCardTypeName( si.GetStringValue("MemoryCards", "Card1Type", GetMemoryCardTypeName(MemoryCardType::Shared)).c_str()) @@ -166,6 +167,7 @@ void Settings::Save(SettingsInterface& si) const else si.DeleteValue("Controller2", "Type"); + si.SetBoolValue("MemoryCards", "LoadFromSaveStates", load_memory_cards_from_save_states); si.SetStringValue("MemoryCards", "Card1Type", GetMemoryCardTypeName(memory_card_types[0])); si.SetStringValue("MemoryCards", "Card1Path", memory_card_paths[0].c_str()); si.SetStringValue("MemoryCards", "Card2Type", GetMemoryCardTypeName(memory_card_types[1])); diff --git a/src/core/settings.h b/src/core/settings.h index 78f9ea5df..33dc89365 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -45,6 +45,7 @@ struct Settings bool start_fullscreen = false; bool save_state_on_exit = true; bool confim_power_off = true; + bool load_memory_cards_from_save_states = false; GPURenderer gpu_renderer = GPURenderer::Software; u32 gpu_resolution_scale = 1; diff --git a/src/duckstation-qt/generalsettingswidget.cpp b/src/duckstation-qt/generalsettingswidget.cpp index 615b74501..45df7eaaf 100644 --- a/src/duckstation-qt/generalsettingswidget.cpp +++ b/src/duckstation-qt/generalsettingswidget.cpp @@ -12,6 +12,8 @@ GeneralSettingsWidget::GeneralSettingsWidget(QtHostInterface* host_interface, QW SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.renderToMain, "Main/RenderToMainWindow"); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.saveStateOnExit, "Main/SaveStateOnExit"); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.confirmPowerOff, "Main/ConfirmPowerOff"); + SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.loadMemoryCardsFromSaveStates, + "MemoryCards/LoadFromSaveStates"); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.showOSDMessages, "Display/ShowOSDMessages"); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.showFPS, "Display/ShowFPS"); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.showVPS, "Display/ShowVPS"); @@ -43,6 +45,10 @@ GeneralSettingsWidget::GeneralSettingsWidget(QtHostInterface* host_interface, QW "the game list. If unchecked, the display will render in a seperate window."); dialog->registerWidgetHelp(m_ui.pauseOnStart, "Pause On Start", "Unchecked", "Pauses the emulator when a game is started."); + dialog->registerWidgetHelp( + m_ui.loadMemoryCardsFromSaveStates, "Load Memory Cards From Save States", "Unchecked", + "When enabled, memory cards will be overwritten when save states are loaded. This can " + "result in lost saves. For deterministic save states, enable this option, otherwise leave disabled."); dialog->registerWidgetHelp(m_ui.enableSpeedLimiter, "Enable Speed Limiter", "Checked", "Throttles the emulation speed to the chosen speed above. If unchecked, the emulator will " "run as fast as possible, which may not be playable."); diff --git a/src/duckstation-qt/generalsettingswidget.ui b/src/duckstation-qt/generalsettingswidget.ui index c4afd34c0..06256f8c7 100644 --- a/src/duckstation-qt/generalsettingswidget.ui +++ b/src/duckstation-qt/generalsettingswidget.ui @@ -33,6 +33,13 @@ + + + Pause On Start + + + + Confirm Power Off @@ -46,27 +53,27 @@ - + + + + Load Memory Cards From Save States + + + + Start Fullscreen - + Render To Main Window - - - - Pause On Start - - - diff --git a/src/duckstation-sdl/sdl_host_interface.cpp b/src/duckstation-sdl/sdl_host_interface.cpp index 47e1eb548..cb79f9fe2 100644 --- a/src/duckstation-sdl/sdl_host_interface.cpp +++ b/src/duckstation-sdl/sdl_host_interface.cpp @@ -1026,6 +1026,8 @@ void SDLHostInterface::DrawSettingsWindow() settings_changed |= ImGui::Checkbox("Pause On Start", &m_settings_copy.start_paused); settings_changed |= ImGui::Checkbox("Start Fullscreen", &m_settings_copy.start_fullscreen); settings_changed |= ImGui::Checkbox("Save State On Exit", &m_settings_copy.save_state_on_exit); + settings_changed |= + ImGui::Checkbox("Load Memory Cards From Save States", &m_settings_copy.load_memory_cards_from_save_states); } ImGui::NewLine();