diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index dad42599a..a33741974 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -333,6 +333,7 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si) si.SetBoolValue("Main", "StartPaused", false); si.SetBoolValue("Main", "SaveStateOnExit", true); si.SetBoolValue("Main", "ConfirmPowerOff", true); + si.SetBoolValue("Main", "LoadDevicesFromSaveStates", false); si.SetStringValue("CPU", "ExecutionMode", Settings::GetCPUExecutionModeName(Settings::DEFAULT_CPU_EXECUTION_MODE)); @@ -374,7 +375,6 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si) si.SetStringValue("Controller1", "Type", Settings::GetControllerTypeName(Settings::DEFAULT_CONTROLLER_1_TYPE)); si.SetStringValue("Controller2", "Type", Settings::GetControllerTypeName(Settings::DEFAULT_CONTROLLER_2_TYPE)); - si.SetBoolValue("MemoryCards", "LoadFromSaveStates", false); si.SetStringValue("MemoryCards", "Card1Type", Settings::GetMemoryCardTypeName(Settings::DEFAULT_MEMORY_CARD_1_TYPE)); si.SetStringValue("MemoryCards", "Card1Path", "memcards/shared_card_1.mcd"); si.SetStringValue("MemoryCards", "Card2Type", Settings::GetMemoryCardTypeName(Settings::DEFAULT_MEMORY_CARD_2_TYPE)); diff --git a/src/core/pad.cpp b/src/core/pad.cpp index bdc0214f4..386a78b04 100644 --- a/src/core/pad.cpp +++ b/src/core/pad.cpp @@ -44,25 +44,48 @@ bool Pad::DoState(StateWrapper& sw) if (controller_type != state_controller_type) { - m_system->GetHostInterface()->AddFormattedOSDMessage( - 2.0f, "Save state contains controller type %s in port %u, but %s is used. Switching.", - Settings::GetControllerTypeName(state_controller_type), i, Settings::GetControllerTypeName(controller_type)); + if (m_system->GetSettings().load_devices_from_save_states) + { + m_system->GetHostInterface()->AddFormattedOSDMessage( + 2.0f, "Save state contains controller type %s in port %u, but %s is used. Switching.", + Settings::GetControllerTypeName(state_controller_type), i + 1u, + Settings::GetControllerTypeName(controller_type)); - m_controllers[i].reset(); - if (state_controller_type != ControllerType::None) - m_controllers[i] = Controller::Create(m_system, state_controller_type, i); + m_controllers[i].reset(); + if (state_controller_type != ControllerType::None) + m_controllers[i] = Controller::Create(m_system, state_controller_type, i); + } + else + { + m_system->GetHostInterface()->AddFormattedOSDMessage(2.0f, "Ignoring mismatched controller type %s in port %u.", + Settings::GetControllerTypeName(state_controller_type), + i + 1u); + + // we still need to read the save state controller state + if (state_controller_type != ControllerType::None) + { + std::unique_ptr dummy_controller = Controller::Create(m_system, state_controller_type, i); + if (dummy_controller) + { + if (!sw.DoMarker("Controller") || !dummy_controller->DoState(sw)) + return false; + } + } + } } - - if (m_controllers[i]) + else { - if (!sw.DoMarker("Controller") || !m_controllers[i]->DoState(sw)) - return false; + if (m_controllers[i]) + { + if (!sw.DoMarker("Controller") || !m_controllers[i]->DoState(sw)) + return false; + } } 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) + if (sw.IsReading() && card_present && !m_system->GetSettings().load_devices_from_save_states) { Log_WarningPrintf("Skipping loading memory card %u from save state.", i + 1u); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 4974ae075..01b25be3b 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -81,6 +81,7 @@ void Settings::Load(SettingsInterface& si) start_fullscreen = si.GetBoolValue("Main", "StartFullscreen", false); save_state_on_exit = si.GetBoolValue("Main", "SaveStateOnExit", true); confim_power_off = si.GetBoolValue("Main", "ConfirmPowerOff", true); + load_devices_from_save_states = si.GetBoolValue("Main", "LoadDevicesFromSaveStates", false); cpu_execution_mode = ParseCPUExecutionMode( @@ -146,7 +147,6 @@ 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(DEFAULT_MEMORY_CARD_1_TYPE)).c_str()) @@ -187,6 +187,7 @@ void Settings::Save(SettingsInterface& si) const si.SetBoolValue("Main", "StartFullscreen", start_fullscreen); si.SetBoolValue("Main", "SaveStateOnExit", save_state_on_exit); si.SetBoolValue("Main", "ConfirmPowerOff", confim_power_off); + si.SetBoolValue("Main", "LoadDevicesFromSaveStates", load_devices_from_save_states); si.SetStringValue("CPU", "ExecutionMode", GetCPUExecutionModeName(cpu_execution_mode)); @@ -239,7 +240,6 @@ 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 2f364d312..ad9067fcf 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -77,7 +77,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; + bool load_devices_from_save_states = false; GPURenderer gpu_renderer = GPURenderer::Software; std::string gpu_adapter; diff --git a/src/duckstation-qt/generalsettingswidget.cpp b/src/duckstation-qt/generalsettingswidget.cpp index 45df7eaaf..05f9020a7 100644 --- a/src/duckstation-qt/generalsettingswidget.cpp +++ b/src/duckstation-qt/generalsettingswidget.cpp @@ -12,8 +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.loadDevicesFromSaveStates, + "Main/LoadDevicesFromSaveStates"); 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"); @@ -46,9 +46,10 @@ GeneralSettingsWidget::GeneralSettingsWidget(QtHostInterface* host_interface, QW 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."); + m_ui.loadDevicesFromSaveStates, "Load Devices From Save States", "Unchecked", + "When enabled, memory cards and controllers will be overwritten when save states are loaded. This can " + "result in lost saves, and controller type mismatches. 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 dc1a8244b..1ea502e73 100644 --- a/src/duckstation-qt/generalsettingswidget.ui +++ b/src/duckstation-qt/generalsettingswidget.ui @@ -54,9 +54,9 @@ - + - Load Memory Cards From Save States + Load Devices From Save States diff --git a/src/duckstation-sdl/sdl_host_interface.cpp b/src/duckstation-sdl/sdl_host_interface.cpp index e7a56a027..876be449a 100644 --- a/src/duckstation-sdl/sdl_host_interface.cpp +++ b/src/duckstation-sdl/sdl_host_interface.cpp @@ -1086,7 +1086,7 @@ void SDLHostInterface::DrawSettingsWindow() 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::Checkbox("Load Devices From Save States", &m_settings_copy.load_devices_from_save_states); } ImGui::NewLine();