From 47f0720b936945b7e86844511c99e657f0029fb2 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Thu, 17 Dec 2020 00:09:32 +1000 Subject: [PATCH] Controller: Always preserve internal state when loading/resuming Fixes analog mode getting disabled when loading state. --- src/core/analog_controller.cpp | 11 ++++++++--- src/core/analog_controller.h | 2 +- src/core/analog_joystick.cpp | 18 ++++++++++++++---- src/core/analog_joystick.h | 2 +- src/core/controller.cpp | 2 +- src/core/controller.h | 2 +- src/core/digital_controller.cpp | 10 +++++++--- src/core/digital_controller.h | 2 +- src/core/namco_guncon.cpp | 20 +++++++++++++++----- src/core/namco_guncon.h | 2 +- src/core/negcon.cpp | 10 +++++++--- src/core/negcon.h | 2 +- src/core/pad.cpp | 33 +++++++++++++++++++++++++-------- src/core/playstation_mouse.cpp | 20 +++++++++++++++----- src/core/playstation_mouse.h | 2 +- 15 files changed, 99 insertions(+), 39 deletions(-) diff --git a/src/core/analog_controller.cpp b/src/core/analog_controller.cpp index fdf0e309b..2b7f30914 100644 --- a/src/core/analog_controller.cpp +++ b/src/core/analog_controller.cpp @@ -45,9 +45,9 @@ void AnalogController::Reset() } } -bool AnalogController::DoState(StateWrapper& sw) +bool AnalogController::DoState(StateWrapper& sw, bool apply_input_state) { - if (!Controller::DoState(sw)) + if (!Controller::DoState(sw, apply_input_state)) return false; const bool old_analog_mode = m_analog_mode; @@ -57,7 +57,12 @@ bool AnalogController::DoState(StateWrapper& sw) sw.DoEx(&m_legacy_rumble_unlocked, 44, false); sw.Do(&m_configuration_mode); sw.Do(&m_command_param); - sw.DoEx(&m_button_state, 44, static_cast(0xFFFF)); + + u16 button_state = m_button_state; + sw.DoEx(&button_state, 44, static_cast(0xFFFF)); + if (apply_input_state) + m_button_state = button_state; + sw.Do(&m_state); sw.DoEx(&m_rumble_config, 45, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); diff --git a/src/core/analog_controller.h b/src/core/analog_controller.h index f7fe9a8e6..2ab2a89d5 100644 --- a/src/core/analog_controller.h +++ b/src/core/analog_controller.h @@ -57,7 +57,7 @@ public: std::optional GetButtonCodeByName(std::string_view button_name) const override; void Reset() override; - bool DoState(StateWrapper& sw) override; + bool DoState(StateWrapper& sw, bool ignore_input_state) override; void SetAxisState(s32 axis_code, float value) override; void SetButtonState(s32 button_code, bool pressed) override; diff --git a/src/core/analog_joystick.cpp b/src/core/analog_joystick.cpp index a40e6ab95..6fefb96ce 100644 --- a/src/core/analog_joystick.cpp +++ b/src/core/analog_joystick.cpp @@ -26,16 +26,26 @@ void AnalogJoystick::Reset() m_transfer_state = TransferState::Idle; } -bool AnalogJoystick::DoState(StateWrapper& sw) +bool AnalogJoystick::DoState(StateWrapper& sw, bool apply_input_state) { - if (!Controller::DoState(sw)) + if (!Controller::DoState(sw, apply_input_state)) return false; const bool old_analog_mode = m_analog_mode; sw.Do(&m_analog_mode); - sw.Do(&m_button_state); - sw.Do(&m_axis_state); + + u16 button_state = m_button_state; + auto axis_state = m_axis_state; + sw.Do(&button_state); + sw.Do(&axis_state); + + if (apply_input_state) + { + m_button_state = button_state; + m_axis_state = axis_state; + } + sw.Do(&m_transfer_state); if (sw.IsReading() && (old_analog_mode != m_analog_mode)) diff --git a/src/core/analog_joystick.h b/src/core/analog_joystick.h index fc76ded9d..d960627ac 100644 --- a/src/core/analog_joystick.h +++ b/src/core/analog_joystick.h @@ -55,7 +55,7 @@ public: std::optional GetButtonCodeByName(std::string_view button_name) const override; void Reset() override; - bool DoState(StateWrapper& sw) override; + bool DoState(StateWrapper& sw, bool apply_input_state) override; void SetAxisState(s32 axis_code, float value) override; void SetButtonState(s32 button_code, bool pressed) override; diff --git a/src/core/controller.cpp b/src/core/controller.cpp index c2be54bb6..9ec931ed3 100644 --- a/src/core/controller.cpp +++ b/src/core/controller.cpp @@ -13,7 +13,7 @@ Controller::~Controller() = default; void Controller::Reset() {} -bool Controller::DoState(StateWrapper& sw) +bool Controller::DoState(StateWrapper& sw, bool apply_input_state) { return !sw.HasError(); } diff --git a/src/core/controller.h b/src/core/controller.h index ad281eec3..7c51f9d1b 100644 --- a/src/core/controller.h +++ b/src/core/controller.h @@ -37,7 +37,7 @@ public: virtual std::optional GetButtonCodeByName(std::string_view button_name) const; virtual void Reset(); - virtual bool DoState(StateWrapper& sw); + virtual bool DoState(StateWrapper& sw, bool apply_input_state); // Resets all state for the transferring to/from the device. virtual void ResetTransferState(); diff --git a/src/core/digital_controller.cpp b/src/core/digital_controller.cpp index d10ff4635..b95b5f7a4 100644 --- a/src/core/digital_controller.cpp +++ b/src/core/digital_controller.cpp @@ -27,12 +27,16 @@ void DigitalController::Reset() m_transfer_state = TransferState::Idle; } -bool DigitalController::DoState(StateWrapper& sw) +bool DigitalController::DoState(StateWrapper& sw, bool apply_input_state) { - if (!Controller::DoState(sw)) + if (!Controller::DoState(sw, apply_input_state)) return false; - sw.Do(&m_button_state); + u16 button_state = m_button_state; + sw.Do(&button_state); + if (apply_input_state) + m_button_state = apply_input_state; + sw.Do(&m_transfer_state); return true; } diff --git a/src/core/digital_controller.h b/src/core/digital_controller.h index 2e45a702d..69f4ebd7e 100644 --- a/src/core/digital_controller.h +++ b/src/core/digital_controller.h @@ -44,7 +44,7 @@ public: std::optional GetButtonCodeByName(std::string_view button_name) const override; void Reset() override; - bool DoState(StateWrapper& sw) override; + bool DoState(StateWrapper& sw, bool apply_input_state) override; void SetAxisState(s32 axis_code, float value) override; void SetButtonState(s32 button_code, bool pressed) override; diff --git a/src/core/namco_guncon.cpp b/src/core/namco_guncon.cpp index 295aed3f6..6a6a4cade 100644 --- a/src/core/namco_guncon.cpp +++ b/src/core/namco_guncon.cpp @@ -34,14 +34,24 @@ void NamcoGunCon::Reset() m_transfer_state = TransferState::Idle; } -bool NamcoGunCon::DoState(StateWrapper& sw) +bool NamcoGunCon::DoState(StateWrapper& sw, bool apply_input_state) { - if (!Controller::DoState(sw)) + if (!Controller::DoState(sw, apply_input_state)) return false; - sw.Do(&m_button_state); - sw.Do(&m_position_x); - sw.Do(&m_position_y); + u16 button_state = m_button_state; + u16 position_x = m_position_x; + u16 position_y = m_position_y; + sw.Do(&button_state); + sw.Do(&position_x); + sw.Do(&position_y); + if (apply_input_state) + { + m_button_state = button_state; + m_position_x = position_x; + m_position_y = position_y; + } + sw.Do(&m_transfer_state); return true; } diff --git a/src/core/namco_guncon.h b/src/core/namco_guncon.h index 274833278..4c96a8c7b 100644 --- a/src/core/namco_guncon.h +++ b/src/core/namco_guncon.h @@ -31,7 +31,7 @@ public: std::optional GetButtonCodeByName(std::string_view button_name) const override; void Reset() override; - bool DoState(StateWrapper& sw) override; + bool DoState(StateWrapper& sw, bool apply_input_state) override; void LoadSettings(const char* section) override; bool GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale) override; diff --git a/src/core/negcon.cpp b/src/core/negcon.cpp index 031e85f50..5afa28507 100644 --- a/src/core/negcon.cpp +++ b/src/core/negcon.cpp @@ -34,12 +34,16 @@ void NeGcon::Reset() m_transfer_state = TransferState::Idle; } -bool NeGcon::DoState(StateWrapper& sw) +bool NeGcon::DoState(StateWrapper& sw, bool apply_input_state) { - if (!Controller::DoState(sw)) + if (!Controller::DoState(sw, apply_input_state)) return false; - sw.Do(&m_button_state); + u16 button_state = m_button_state; + sw.Do(&button_state); + if (apply_input_state) + m_button_state = button_state; + sw.Do(&m_transfer_state); return true; } diff --git a/src/core/negcon.h b/src/core/negcon.h index 4dff225ea..4ed93c1e5 100644 --- a/src/core/negcon.h +++ b/src/core/negcon.h @@ -46,7 +46,7 @@ public: std::optional GetButtonCodeByName(std::string_view button_name) const override; void Reset() override; - bool DoState(StateWrapper& sw) override; + bool DoState(StateWrapper& sw, bool apply_input_state) override; void SetAxisState(s32 axis_code, float value) override; void SetButtonState(s32 button_code, bool pressed) override; diff --git a/src/core/pad.cpp b/src/core/pad.cpp index b8b0a5314..467fb0365 100644 --- a/src/core/pad.cpp +++ b/src/core/pad.cpp @@ -71,7 +71,7 @@ bool Pad::DoState(StateWrapper& sw) if (state_controller_type != ControllerType::None) { m_controllers[i] = Controller::Create(state_controller_type, i); - if (!sw.DoMarker("Controller") || !m_controllers[i]->DoState(sw)) + if (!sw.DoMarker("Controller") || !m_controllers[i]->DoState(sw, false)) return false; } } @@ -88,7 +88,7 @@ bool Pad::DoState(StateWrapper& sw) std::unique_ptr dummy_controller = Controller::Create(state_controller_type, i); if (dummy_controller) { - if (!sw.DoMarker("Controller") || !dummy_controller->DoState(sw)) + if (!sw.DoMarker("Controller") || !dummy_controller->DoState(sw, true)) return false; } } @@ -98,21 +98,38 @@ bool Pad::DoState(StateWrapper& sw) { if (m_controllers[i]) { - if (!sw.DoMarker("Controller") || !m_controllers[i]->DoState(sw)) + if (!sw.DoMarker("Controller") || !m_controllers[i]->DoState(sw, true)) return false; } } } else { - // we still need to read the save state controller state if (state_controller_type != ControllerType::None) { - std::unique_ptr dummy_controller = Controller::Create(state_controller_type, i); - if (dummy_controller) + if (controller_type != state_controller_type) { - if (!sw.DoMarker("Controller") || !dummy_controller->DoState(sw)) - return false; + g_host_interface->AddFormattedOSDMessage( + 10.0f, + g_host_interface->TranslateString("OSDMessage", "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 + std::unique_ptr dummy_controller = Controller::Create(state_controller_type, i); + if (dummy_controller) + { + if (!sw.DoMarker("Controller") || !dummy_controller->DoState(sw, true)) + return false; + } + } + else + { + // we still need to load some things from the state, e.g. configuration mode, analog mode + if (m_controllers[i]) + { + if (!sw.DoMarker("Controller") || !m_controllers[i]->DoState(sw, false)) + return false; + } } } } diff --git a/src/core/playstation_mouse.cpp b/src/core/playstation_mouse.cpp index 7541fc1bd..1cd8da15d 100644 --- a/src/core/playstation_mouse.cpp +++ b/src/core/playstation_mouse.cpp @@ -37,14 +37,24 @@ void PlayStationMouse::Reset() m_transfer_state = TransferState::Idle; } -bool PlayStationMouse::DoState(StateWrapper& sw) +bool PlayStationMouse::DoState(StateWrapper& sw, bool apply_input_state) { - if (!Controller::DoState(sw)) + if (!Controller::DoState(sw, apply_input_state)) return false; - sw.Do(&m_button_state); - sw.Do(&m_delta_x); - sw.Do(&m_delta_y); + u16 button_state = m_button_state; + u8 delta_x = m_delta_x; + u8 delta_y = m_delta_y; + sw.Do(&button_state); + sw.Do(&delta_x); + sw.Do(&delta_y); + if (apply_input_state) + { + m_button_state = button_state; + m_delta_x = delta_x; + m_delta_y = delta_y; + } + sw.Do(&m_transfer_state); return true; } diff --git a/src/core/playstation_mouse.h b/src/core/playstation_mouse.h index 1d2d3057d..3ffcafb60 100644 --- a/src/core/playstation_mouse.h +++ b/src/core/playstation_mouse.h @@ -29,7 +29,7 @@ public: std::optional GetButtonCodeByName(std::string_view button_name) const override; void Reset() override; - bool DoState(StateWrapper& sw) override; + bool DoState(StateWrapper& sw, bool apply_input_state) override; void SetAxisState(s32 axis_code, float value) override; void SetButtonState(s32 button_code, bool pressed) override;