mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-27 08:05:41 +00:00
AnalogController: Simulate status byte toggling
This commit is contained in:
parent
ab496ef8fe
commit
3273ca36ef
|
@ -31,9 +31,11 @@ void AnalogController::Reset()
|
||||||
m_configuration_mode = false;
|
m_configuration_mode = false;
|
||||||
m_motor_state.fill(0);
|
m_motor_state.fill(0);
|
||||||
|
|
||||||
m_rumble_unlocked = false;
|
m_dualshock_enabled = false;
|
||||||
ResetRumbleConfig();
|
ResetRumbleConfig();
|
||||||
|
|
||||||
|
m_status_byte = 0x5A;
|
||||||
|
|
||||||
if (m_force_analog_on_reset)
|
if (m_force_analog_on_reset)
|
||||||
{
|
{
|
||||||
if (g_settings.controller_disable_analog_mode_forcing)
|
if (g_settings.controller_disable_analog_mode_forcing)
|
||||||
|
@ -56,10 +58,11 @@ bool AnalogController::DoState(StateWrapper& sw, bool apply_input_state)
|
||||||
const bool old_analog_mode = m_analog_mode;
|
const bool old_analog_mode = m_analog_mode;
|
||||||
|
|
||||||
sw.Do(&m_analog_mode);
|
sw.Do(&m_analog_mode);
|
||||||
sw.Do(&m_rumble_unlocked);
|
sw.Do(&m_dualshock_enabled);
|
||||||
sw.DoEx(&m_legacy_rumble_unlocked, 44, false);
|
sw.DoEx(&m_legacy_rumble_unlocked, 44, false);
|
||||||
sw.Do(&m_configuration_mode);
|
sw.Do(&m_configuration_mode);
|
||||||
sw.Do(&m_command_param);
|
sw.Do(&m_command_param);
|
||||||
|
sw.DoEx(&m_status_byte, 55, static_cast<u8>(0x5A));
|
||||||
|
|
||||||
u16 button_state = m_button_state;
|
u16 button_state = m_button_state;
|
||||||
sw.DoEx(&button_state, 44, static_cast<u16>(0xFFFF));
|
sw.DoEx(&button_state, 44, static_cast<u16>(0xFFFF));
|
||||||
|
@ -261,7 +264,8 @@ void AnalogController::ProcessAnalogModeToggle()
|
||||||
SetAnalogMode(!m_analog_mode);
|
SetAnalogMode(!m_analog_mode);
|
||||||
ResetRumbleConfig();
|
ResetRumbleConfig();
|
||||||
|
|
||||||
// TODO: Mode switch detection (0x00 returned on certain commands instead of 0x5A)
|
if (m_dualshock_enabled)
|
||||||
|
m_status_byte = 0x00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,21 +367,21 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
||||||
Assert(m_command_step == 0);
|
Assert(m_command_step == 0);
|
||||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||||
m_command = Command::ReadPad;
|
m_command = Command::ReadPad;
|
||||||
m_tx_buffer = {GetIDByte(), GetStatusByte(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
}
|
}
|
||||||
else if (data_in == 0x43)
|
else if (data_in == 0x43)
|
||||||
{
|
{
|
||||||
Assert(m_command_step == 0);
|
Assert(m_command_step == 0);
|
||||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||||
m_command = Command::ConfigModeSetMode;
|
m_command = Command::ConfigModeSetMode;
|
||||||
m_tx_buffer = {GetIDByte(), GetStatusByte(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
}
|
}
|
||||||
else if (m_configuration_mode && data_in == 0x44)
|
else if (m_configuration_mode && data_in == 0x44)
|
||||||
{
|
{
|
||||||
Assert(m_command_step == 0);
|
Assert(m_command_step == 0);
|
||||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||||
m_command = Command::SetAnalogMode;
|
m_command = Command::SetAnalogMode;
|
||||||
m_tx_buffer = {GetIDByte(), GetStatusByte(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
ResetRumbleConfig();
|
ResetRumbleConfig();
|
||||||
}
|
}
|
||||||
|
@ -386,35 +390,35 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
||||||
Assert(m_command_step == 0);
|
Assert(m_command_step == 0);
|
||||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||||
m_command = Command::GetAnalogMode;
|
m_command = Command::GetAnalogMode;
|
||||||
m_tx_buffer = {GetIDByte(), GetStatusByte(), 0x01, 0x02, BoolToUInt8(m_analog_mode), 0x02, 0x01, 0x00};
|
m_tx_buffer = {GetIDByte(), m_status_byte, 0x01, 0x02, BoolToUInt8(m_analog_mode), 0x02, 0x01, 0x00};
|
||||||
}
|
}
|
||||||
else if (m_configuration_mode && data_in == 0x46)
|
else if (m_configuration_mode && data_in == 0x46)
|
||||||
{
|
{
|
||||||
Assert(m_command_step == 0);
|
Assert(m_command_step == 0);
|
||||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||||
m_command = Command::Command46;
|
m_command = Command::Command46;
|
||||||
m_tx_buffer = {GetIDByte(), GetStatusByte(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
}
|
}
|
||||||
else if (m_configuration_mode && data_in == 0x47)
|
else if (m_configuration_mode && data_in == 0x47)
|
||||||
{
|
{
|
||||||
Assert(m_command_step == 0);
|
Assert(m_command_step == 0);
|
||||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||||
m_command = Command::Command47;
|
m_command = Command::Command47;
|
||||||
m_tx_buffer = {GetIDByte(), GetStatusByte(), 0x00, 0x00, 0x02, 0x00, 0x01, 0x00};
|
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00};
|
||||||
}
|
}
|
||||||
else if (m_configuration_mode && data_in == 0x4C)
|
else if (m_configuration_mode && data_in == 0x4C)
|
||||||
{
|
{
|
||||||
Assert(m_command_step == 0);
|
Assert(m_command_step == 0);
|
||||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||||
m_command = Command::Command4C;
|
m_command = Command::Command4C;
|
||||||
m_tx_buffer = {GetIDByte(), GetStatusByte(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
}
|
}
|
||||||
else if (m_configuration_mode && data_in == 0x4D)
|
else if (m_configuration_mode && data_in == 0x4D)
|
||||||
{
|
{
|
||||||
Assert(m_command_step == 0);
|
Assert(m_command_step == 0);
|
||||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||||
m_command = Command::GetSetRumble;
|
m_command = Command::GetSetRumble;
|
||||||
m_tx_buffer = {GetIDByte(), GetStatusByte(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
m_rumble_config_large_motor_index = -1;
|
m_rumble_config_large_motor_index = -1;
|
||||||
m_rumble_config_small_motor_index = -1;
|
m_rumble_config_small_motor_index = -1;
|
||||||
|
@ -440,7 +444,7 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
||||||
{
|
{
|
||||||
m_tx_buffer[m_command_step] = Truncate8(m_button_state) & GetExtraButtonMaskLSB();
|
m_tx_buffer[m_command_step] = Truncate8(m_button_state) & GetExtraButtonMaskLSB();
|
||||||
|
|
||||||
if (m_rumble_unlocked)
|
if (m_dualshock_enabled)
|
||||||
SetMotorStateForConfigIndex(rumble_index, data_in);
|
SetMotorStateForConfigIndex(rumble_index, data_in);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -449,7 +453,7 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
||||||
{
|
{
|
||||||
m_tx_buffer[m_command_step] = Truncate8(m_button_state >> 8);
|
m_tx_buffer[m_command_step] = Truncate8(m_button_state >> 8);
|
||||||
|
|
||||||
if (m_rumble_unlocked)
|
if (m_dualshock_enabled)
|
||||||
{
|
{
|
||||||
SetMotorStateForConfigIndex(rumble_index, data_in);
|
SetMotorStateForConfigIndex(rumble_index, data_in);
|
||||||
}
|
}
|
||||||
|
@ -466,7 +470,7 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
||||||
if (m_configuration_mode || m_analog_mode)
|
if (m_configuration_mode || m_analog_mode)
|
||||||
m_tx_buffer[m_command_step] = m_axis_state[static_cast<u8>(Axis::RightX)];
|
m_tx_buffer[m_command_step] = m_axis_state[static_cast<u8>(Axis::RightX)];
|
||||||
|
|
||||||
if (m_rumble_unlocked)
|
if (m_dualshock_enabled)
|
||||||
SetMotorStateForConfigIndex(rumble_index, data_in);
|
SetMotorStateForConfigIndex(rumble_index, data_in);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -476,7 +480,7 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
||||||
if (m_configuration_mode || m_analog_mode)
|
if (m_configuration_mode || m_analog_mode)
|
||||||
m_tx_buffer[m_command_step] = m_axis_state[static_cast<u8>(Axis::RightY)];
|
m_tx_buffer[m_command_step] = m_axis_state[static_cast<u8>(Axis::RightY)];
|
||||||
|
|
||||||
if (m_rumble_unlocked)
|
if (m_dualshock_enabled)
|
||||||
SetMotorStateForConfigIndex(rumble_index, data_in);
|
SetMotorStateForConfigIndex(rumble_index, data_in);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -486,7 +490,7 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
||||||
if (m_configuration_mode || m_analog_mode)
|
if (m_configuration_mode || m_analog_mode)
|
||||||
m_tx_buffer[m_command_step] = m_axis_state[static_cast<u8>(Axis::LeftX)];
|
m_tx_buffer[m_command_step] = m_axis_state[static_cast<u8>(Axis::LeftX)];
|
||||||
|
|
||||||
if (m_rumble_unlocked)
|
if (m_dualshock_enabled)
|
||||||
SetMotorStateForConfigIndex(rumble_index, data_in);
|
SetMotorStateForConfigIndex(rumble_index, data_in);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -496,7 +500,7 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
||||||
if (m_configuration_mode || m_analog_mode)
|
if (m_configuration_mode || m_analog_mode)
|
||||||
m_tx_buffer[m_command_step] = m_axis_state[static_cast<u8>(Axis::LeftY)];
|
m_tx_buffer[m_command_step] = m_axis_state[static_cast<u8>(Axis::LeftY)];
|
||||||
|
|
||||||
if (m_rumble_unlocked)
|
if (m_dualshock_enabled)
|
||||||
SetMotorStateForConfigIndex(rumble_index, data_in);
|
SetMotorStateForConfigIndex(rumble_index, data_in);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -567,7 +571,10 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
||||||
m_configuration_mode = (m_rx_buffer[2] == 1);
|
m_configuration_mode = (m_rx_buffer[2] == 1);
|
||||||
|
|
||||||
if (m_configuration_mode)
|
if (m_configuration_mode)
|
||||||
m_rumble_unlocked = true;
|
{
|
||||||
|
m_dualshock_enabled = true;
|
||||||
|
m_status_byte = 0x5A;
|
||||||
|
}
|
||||||
|
|
||||||
Log_DevPrintf("0x%02x(%s) config mode", m_rx_buffer[2], m_configuration_mode ? "enter" : "leave");
|
Log_DevPrintf("0x%02x(%s) config mode", m_rx_buffer[2], m_configuration_mode ? "enter" : "leave");
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,9 +109,6 @@ private:
|
||||||
u8 GetModeID() const;
|
u8 GetModeID() const;
|
||||||
u8 GetIDByte() const;
|
u8 GetIDByte() const;
|
||||||
|
|
||||||
// TODO: Return 0x00 on manual toggles
|
|
||||||
constexpr u8 GetStatusByte() const { return 0x5A; };
|
|
||||||
|
|
||||||
void SetAnalogMode(bool enabled);
|
void SetAnalogMode(bool enabled);
|
||||||
void ProcessAnalogModeToggle();
|
void ProcessAnalogModeToggle();
|
||||||
void SetMotorState(u8 motor, u8 value);
|
void SetMotorState(u8 motor, u8 value);
|
||||||
|
@ -128,7 +125,7 @@ private:
|
||||||
|
|
||||||
bool m_analog_mode = false;
|
bool m_analog_mode = false;
|
||||||
bool m_analog_locked = false;
|
bool m_analog_locked = false;
|
||||||
bool m_rumble_unlocked = false;
|
bool m_dualshock_enabled = false;
|
||||||
bool m_configuration_mode = false;
|
bool m_configuration_mode = false;
|
||||||
|
|
||||||
std::array<u8, static_cast<u8>(Axis::Count)> m_axis_state{};
|
std::array<u8, static_cast<u8>(Axis::Count)> m_axis_state{};
|
||||||
|
@ -144,6 +141,7 @@ private:
|
||||||
int m_rumble_config_small_motor_index = -1;
|
int m_rumble_config_small_motor_index = -1;
|
||||||
|
|
||||||
bool m_analog_toggle_queued = false;
|
bool m_analog_toggle_queued = false;
|
||||||
|
u8 m_status_byte = 0x5A;
|
||||||
|
|
||||||
// TODO: Set this with command 0x4D and increase response length in digital mode accordingly
|
// TODO: Set this with command 0x4D and increase response length in digital mode accordingly
|
||||||
u8 m_digital_mode_extra_halfwords = 0;
|
u8 m_digital_mode_extra_halfwords = 0;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
||||||
static constexpr u32 SAVE_STATE_VERSION = 54;
|
static constexpr u32 SAVE_STATE_VERSION = 55;
|
||||||
static constexpr u32 SAVE_STATE_MINIMUM_VERSION = 42;
|
static constexpr u32 SAVE_STATE_MINIMUM_VERSION = 42;
|
||||||
|
|
||||||
static_assert(SAVE_STATE_VERSION >= SAVE_STATE_MINIMUM_VERSION);
|
static_assert(SAVE_STATE_VERSION >= SAVE_STATE_MINIMUM_VERSION);
|
||||||
|
|
Loading…
Reference in a new issue