Merge pull request #1666 from ggrtk/controller-fixes

Minor controller fixes
This commit is contained in:
Connor McLaughlin 2021-02-22 12:08:35 +10:00 committed by GitHub
commit 7fc68d0aca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 131 additions and 60 deletions

View file

@ -130,7 +130,12 @@ void AnalogController::SetButtonState(Button button, bool pressed)
{ {
// analog toggle // analog toggle
if (pressed) if (pressed)
m_analog_toggle_queued = true; {
if (m_command == Command::Idle)
ProcessAnalogModeToggle();
else
m_analog_toggle_queued = true;
}
return; return;
} }
@ -197,26 +202,7 @@ void AnalogController::ResetTransferState()
{ {
if (m_analog_toggle_queued) if (m_analog_toggle_queued)
{ {
if (m_analog_locked) ProcessAnalogModeToggle();
{
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)
}
m_analog_toggle_queued = false; m_analog_toggle_queued = false;
} }
@ -238,6 +224,29 @@ void AnalogController::SetAnalogMode(bool enabled)
m_analog_mode = 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) void AnalogController::SetMotorState(u8 motor, u8 value)
{ {
DebugAssert(motor < NUM_MOTORS); DebugAssert(motor < NUM_MOTORS);
@ -314,6 +323,22 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
switch (m_command) switch (m_command)
{ {
case Command::Idle: 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) if (data_in == 0x42)
{ {
@ -378,15 +403,8 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
} }
else else
{ {
*data_out = 0xFF; Log_ErrorPrintf("Unimplemented analog controller command 0x%02X", data_in);
ack = (data_in == 0x01); Panic("Unimplemented analog controller command");
if (ack)
Log_DevPrintf("ACK controller access");
else
Log_DevPrintf("Unknown data_in = 0x%02X", data_in);
return ack;
} }
} }
break; break;

View file

@ -81,6 +81,7 @@ private:
enum class Command : u8 enum class Command : u8
{ {
Idle, Idle,
Ready,
ReadPad, // 0x42 ReadPad, // 0x42
ConfigModeSetMode, // 0x43 ConfigModeSetMode, // 0x43
SetAnalogMode, // 0x44 SetAnalogMode, // 0x44
@ -110,6 +111,7 @@ private:
constexpr u8 GetStatusByte() const { return 0x5A; }; constexpr u8 GetStatusByte() const { return 0x5A; };
void SetAnalogMode(bool enabled); void SetAnalogMode(bool enabled);
void ProcessAnalogModeToggle();
void SetMotorState(u8 motor, u8 value); void SetMotorState(u8 motor, u8 value);
u8 GetExtraButtonMaskLSB() const; u8 GetExtraButtonMaskLSB() const;
void ResetRumbleConfig(); void ResetRumbleConfig();

View file

@ -167,18 +167,27 @@ bool AnalogJoystick::Transfer(const u8 data_in, u8* data_out)
{ {
case TransferState::Idle: 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) if (data_in == 0x42)
{ {
*data_out = Truncate8(GetID()); *data_out = Truncate8(GetID());
m_transfer_state = TransferState::IDMSB; m_transfer_state = TransferState::IDMSB;
return true; return true;
} }
else
{ *data_out = 0xFF;
*data_out = 0xFF; return false;
return (data_in == 0x01);
}
} }
case TransferState::IDMSB: case TransferState::IDMSB:

View file

@ -71,6 +71,7 @@ private:
enum class TransferState : u8 enum class TransferState : u8
{ {
Idle, Idle,
Ready,
IDMSB, IDMSB,
ButtonsLSB, ButtonsLSB,
ButtonsMSB, ButtonsMSB,

View file

@ -89,18 +89,27 @@ bool DigitalController::Transfer(const u8 data_in, u8* data_out)
{ {
case TransferState::Idle: 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) if (data_in == 0x42)
{ {
*data_out = Truncate8(ID); *data_out = Truncate8(ID);
m_transfer_state = TransferState::IDMSB; m_transfer_state = TransferState::IDMSB;
return true; return true;
} }
else
{ *data_out = 0xFF;
*data_out = 0xFF; return false;
return (data_in == 0x01);
}
} }
case TransferState::IDMSB: case TransferState::IDMSB:

View file

@ -61,6 +61,7 @@ private:
enum class TransferState : u8 enum class TransferState : u8
{ {
Idle, Idle,
Ready,
IDMSB, IDMSB,
ButtonsLSB, ButtonsLSB,
ButtonsMSB ButtonsMSB

View file

@ -95,18 +95,27 @@ bool NamcoGunCon::Transfer(const u8 data_in, u8* data_out)
{ {
case TransferState::Idle: 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) if (data_in == 0x42)
{ {
*data_out = Truncate8(ID); *data_out = Truncate8(ID);
m_transfer_state = TransferState::IDMSB; m_transfer_state = TransferState::IDMSB;
return true; return true;
} }
else
{ *data_out = 0xFF;
*data_out = 0xFF; return false;
return (data_in == 0x01);
}
} }
case TransferState::IDMSB: case TransferState::IDMSB:

View file

@ -50,6 +50,7 @@ private:
enum class TransferState : u8 enum class TransferState : u8
{ {
Idle, Idle,
Ready,
IDMSB, IDMSB,
ButtonsLSB, ButtonsLSB,
ButtonsMSB, ButtonsMSB,

View file

@ -120,6 +120,18 @@ bool NeGcon::Transfer(const u8 data_in, u8* data_out)
switch (m_transfer_state) switch (m_transfer_state)
{ {
case TransferState::Idle: 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) if (data_in == 0x42)
{ {
@ -127,11 +139,9 @@ bool NeGcon::Transfer(const u8 data_in, u8* data_out)
m_transfer_state = TransferState::IDMSB; m_transfer_state = TransferState::IDMSB;
return true; return true;
} }
else
{ *data_out = 0xFF;
*data_out = 0xFF; return false;
return (data_in == 0x01);
}
} }
case TransferState::IDMSB: case TransferState::IDMSB:

View file

@ -66,6 +66,7 @@ private:
enum class TransferState : u8 enum class TransferState : u8
{ {
Idle, Idle,
Ready,
IDMSB, IDMSB,
ButtonsLSB, ButtonsLSB,
ButtonsMSB, ButtonsMSB,
@ -75,7 +76,7 @@ private:
AnalogL AnalogL
}; };
std::array<u8, static_cast<u8>(Axis::Count)> m_axis_state {}; std::array<u8, static_cast<u8>(Axis::Count)> m_axis_state{};
// buttons are active low; bits 0-2, 8-10, 14-15 are not used and are always high // 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); u16 m_button_state = UINT16_C(0xFFFF);

View file

@ -91,18 +91,27 @@ bool PlayStationMouse::Transfer(const u8 data_in, u8* data_out)
{ {
case TransferState::Idle: 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) if (data_in == 0x42)
{ {
*data_out = Truncate8(ID); *data_out = Truncate8(ID);
m_transfer_state = TransferState::IDMSB; m_transfer_state = TransferState::IDMSB;
return true; return true;
} }
else
{ *data_out = 0xFF;
*data_out = 0xFF; return false;
return (data_in == 0x01);
}
} }
case TransferState::IDMSB: case TransferState::IDMSB:

View file

@ -49,6 +49,7 @@ private:
enum class TransferState : u8 enum class TransferState : u8
{ {
Idle, Idle,
Ready,
IDMSB, IDMSB,
ButtonsLSB, ButtonsLSB,
ButtonsMSB, ButtonsMSB,