diff --git a/src/core/analog_controller.cpp b/src/core/analog_controller.cpp index d0516e995..1dc86ae76 100644 --- a/src/core/analog_controller.cpp +++ b/src/core/analog_controller.cpp @@ -130,7 +130,12 @@ void AnalogController::SetButtonState(Button button, bool pressed) { // analog toggle if (pressed) - m_analog_toggle_queued = true; + { + if (m_command == Command::Idle) + ProcessAnalogModeToggle(); + else + m_analog_toggle_queued = true; + } return; } @@ -197,26 +202,7 @@ void AnalogController::ResetTransferState() { if (m_analog_toggle_queued) { - if (m_analog_locked) - { - g_host_interface->AddFormattedOSDMessage( - 5.0f, - m_analog_mode ? - g_host_interface->TranslateString("AnalogController", "Controller %u is locked to analog mode by the game.") : - g_host_interface->TranslateString("AnalogController", "Controller %u is locked to digital mode by the game."), - m_index + 1u); - } - else - { - SetAnalogMode(!m_analog_mode); - - // Manually toggling controller mode resets and disables rumble configuration - m_rumble_unlocked = false; - ResetRumbleConfig(); - - // TODO: Mode switch detection (0x00 returned on certain commands instead of 0x5A) - } - + ProcessAnalogModeToggle(); m_analog_toggle_queued = false; } @@ -238,6 +224,29 @@ void AnalogController::SetAnalogMode(bool enabled) m_analog_mode = enabled; } +void AnalogController::ProcessAnalogModeToggle() +{ + if (m_analog_locked) + { + g_host_interface->AddFormattedOSDMessage( + 5.0f, + m_analog_mode ? + g_host_interface->TranslateString("AnalogController", "Controller %u is locked to analog mode by the game.") : + g_host_interface->TranslateString("AnalogController", "Controller %u is locked to digital mode by the game."), + m_index + 1u); + } + else + { + SetAnalogMode(!m_analog_mode); + + // Manually toggling controller mode resets and disables rumble configuration + m_rumble_unlocked = false; + ResetRumbleConfig(); + + // TODO: Mode switch detection (0x00 returned on certain commands instead of 0x5A) + } +} + void AnalogController::SetMotorState(u8 motor, u8 value) { DebugAssert(motor < NUM_MOTORS); @@ -314,6 +323,22 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out) switch (m_command) { case Command::Idle: + { + *data_out = 0xFF; + + if (data_in == 0x01) + { + Log_DevPrintf("ACK controller access"); + m_command = Command::Ready; + return true; + } + + Log_DevPrintf("Unknown data_in = 0x%02X", data_in); + return false; + } + break; + + case Command::Ready: { if (data_in == 0x42) { @@ -378,15 +403,8 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out) } else { - *data_out = 0xFF; - ack = (data_in == 0x01); - - if (ack) - Log_DevPrintf("ACK controller access"); - else - Log_DevPrintf("Unknown data_in = 0x%02X", data_in); - - return ack; + Log_ErrorPrintf("Unimplemented analog controller command 0x%02X", data_in); + Panic("Unimplemented analog controller command"); } } break; diff --git a/src/core/analog_controller.h b/src/core/analog_controller.h index 0091444f4..96cb6a6b9 100644 --- a/src/core/analog_controller.h +++ b/src/core/analog_controller.h @@ -81,6 +81,7 @@ private: enum class Command : u8 { Idle, + Ready, ReadPad, // 0x42 ConfigModeSetMode, // 0x43 SetAnalogMode, // 0x44 @@ -110,6 +111,7 @@ private: constexpr u8 GetStatusByte() const { return 0x5A; }; void SetAnalogMode(bool enabled); + void ProcessAnalogModeToggle(); void SetMotorState(u8 motor, u8 value); u8 GetExtraButtonMaskLSB() const; void ResetRumbleConfig(); diff --git a/src/core/analog_joystick.cpp b/src/core/analog_joystick.cpp index 398d10ac9..b47e88760 100644 --- a/src/core/analog_joystick.cpp +++ b/src/core/analog_joystick.cpp @@ -167,18 +167,27 @@ bool AnalogJoystick::Transfer(const u8 data_in, u8* data_out) { case TransferState::Idle: { - // ack when sent 0x01, send ID for 0x42 + *data_out = 0xFF; + + if (data_in == 0x01) + { + m_transfer_state = TransferState::Ready; + return true; + } + return false; + } + + case TransferState::Ready: + { if (data_in == 0x42) { *data_out = Truncate8(GetID()); m_transfer_state = TransferState::IDMSB; return true; } - else - { - *data_out = 0xFF; - return (data_in == 0x01); - } + + *data_out = 0xFF; + return false; } case TransferState::IDMSB: diff --git a/src/core/analog_joystick.h b/src/core/analog_joystick.h index 5816f3b2d..b5bf0d414 100644 --- a/src/core/analog_joystick.h +++ b/src/core/analog_joystick.h @@ -71,6 +71,7 @@ private: enum class TransferState : u8 { Idle, + Ready, IDMSB, ButtonsLSB, ButtonsMSB, diff --git a/src/core/digital_controller.cpp b/src/core/digital_controller.cpp index 389c5f91b..3563499ca 100644 --- a/src/core/digital_controller.cpp +++ b/src/core/digital_controller.cpp @@ -89,18 +89,27 @@ bool DigitalController::Transfer(const u8 data_in, u8* data_out) { case TransferState::Idle: { - // ack when sent 0x01, send ID for 0x42 + *data_out = 0xFF; + + if (data_in == 0x01) + { + m_transfer_state = TransferState::Ready; + return true; + } + return false; + } + + case TransferState::Ready: + { if (data_in == 0x42) { *data_out = Truncate8(ID); m_transfer_state = TransferState::IDMSB; return true; } - else - { - *data_out = 0xFF; - return (data_in == 0x01); - } + + *data_out = 0xFF; + return false; } case TransferState::IDMSB: diff --git a/src/core/digital_controller.h b/src/core/digital_controller.h index 69f4ebd7e..d57b91331 100644 --- a/src/core/digital_controller.h +++ b/src/core/digital_controller.h @@ -61,6 +61,7 @@ private: enum class TransferState : u8 { Idle, + Ready, IDMSB, ButtonsLSB, ButtonsMSB diff --git a/src/core/namco_guncon.cpp b/src/core/namco_guncon.cpp index 8e508e572..7a0104cba 100644 --- a/src/core/namco_guncon.cpp +++ b/src/core/namco_guncon.cpp @@ -95,18 +95,27 @@ bool NamcoGunCon::Transfer(const u8 data_in, u8* data_out) { case TransferState::Idle: { - // ack when sent 0x01, send ID for 0x42 + *data_out = 0xFF; + + if (data_in == 0x01) + { + m_transfer_state = TransferState::Ready; + return true; + } + return false; + } + + case TransferState::Ready: + { if (data_in == 0x42) { *data_out = Truncate8(ID); m_transfer_state = TransferState::IDMSB; return true; } - else - { - *data_out = 0xFF; - return (data_in == 0x01); - } + + *data_out = 0xFF; + return false; } case TransferState::IDMSB: diff --git a/src/core/namco_guncon.h b/src/core/namco_guncon.h index a316f8b55..eba8edf6f 100644 --- a/src/core/namco_guncon.h +++ b/src/core/namco_guncon.h @@ -50,6 +50,7 @@ private: enum class TransferState : u8 { Idle, + Ready, IDMSB, ButtonsLSB, ButtonsMSB, diff --git a/src/core/negcon.cpp b/src/core/negcon.cpp index 65e95ebc0..1d286dcfb 100644 --- a/src/core/negcon.cpp +++ b/src/core/negcon.cpp @@ -120,6 +120,18 @@ bool NeGcon::Transfer(const u8 data_in, u8* data_out) switch (m_transfer_state) { case TransferState::Idle: + { + *data_out = 0xFF; + + if (data_in == 0x01) + { + m_transfer_state = TransferState::Ready; + return true; + } + return false; + } + + case TransferState::Ready: { if (data_in == 0x42) { @@ -127,11 +139,9 @@ bool NeGcon::Transfer(const u8 data_in, u8* data_out) m_transfer_state = TransferState::IDMSB; return true; } - else - { - *data_out = 0xFF; - return (data_in == 0x01); - } + + *data_out = 0xFF; + return false; } case TransferState::IDMSB: diff --git a/src/core/negcon.h b/src/core/negcon.h index 819678166..6f5746173 100644 --- a/src/core/negcon.h +++ b/src/core/negcon.h @@ -66,6 +66,7 @@ private: enum class TransferState : u8 { Idle, + Ready, IDMSB, ButtonsLSB, ButtonsMSB, @@ -75,7 +76,7 @@ private: AnalogL }; - std::array(Axis::Count)> m_axis_state {}; + std::array(Axis::Count)> m_axis_state{}; // buttons are active low; bits 0-2, 8-10, 14-15 are not used and are always high u16 m_button_state = UINT16_C(0xFFFF); diff --git a/src/core/playstation_mouse.cpp b/src/core/playstation_mouse.cpp index 57c4eeb2b..a689d61d2 100644 --- a/src/core/playstation_mouse.cpp +++ b/src/core/playstation_mouse.cpp @@ -91,18 +91,27 @@ bool PlayStationMouse::Transfer(const u8 data_in, u8* data_out) { case TransferState::Idle: { - // ack when sent 0x01, send ID for 0x42 + *data_out = 0xFF; + + if (data_in == 0x01) + { + m_transfer_state = TransferState::Ready; + return true; + } + return false; + } + + case TransferState::Ready: + { if (data_in == 0x42) { *data_out = Truncate8(ID); m_transfer_state = TransferState::IDMSB; return true; } - else - { - *data_out = 0xFF; - return (data_in == 0x01); - } + + *data_out = 0xFF; + return false; } case TransferState::IDMSB: diff --git a/src/core/playstation_mouse.h b/src/core/playstation_mouse.h index c47f3501d..ecfc4abfd 100644 --- a/src/core/playstation_mouse.h +++ b/src/core/playstation_mouse.h @@ -49,6 +49,7 @@ private: enum class TransferState : u8 { Idle, + Ready, IDMSB, ButtonsLSB, ButtonsMSB,