#include "analog_controller.h" #include "common/log.h" #include "common/state_wrapper.h" #include "common/string_util.h" #include "host_interface.h" #include "settings.h" #include "system.h" #include Log_SetChannel(AnalogController); AnalogController::AnalogController(u32 index) : m_index(index) { m_axis_state.fill(0x80); Reset(); } AnalogController::~AnalogController() = default; ControllerType AnalogController::GetType() const { return ControllerType::AnalogController; } void AnalogController::Reset() { m_command = Command::Idle; m_command_step = 0; m_rx_buffer.fill(0x00); m_tx_buffer.fill(0x00); m_analog_mode = false; m_configuration_mode = false; m_motor_state.fill(0); m_rumble_unlocked = false; ResetRumbleConfig(); if (m_force_analog_on_reset) { if (g_settings.controller_disable_analog_mode_forcing) { g_host_interface->AddOSDMessage( g_host_interface->TranslateStdString( "OSDMessage", "Analog mode forcing is disabled by game settings. Controller will start in digital mode."), 10.0f); } else SetAnalogMode(true); } } bool AnalogController::DoState(StateWrapper& sw, bool apply_input_state) { 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_rumble_unlocked); sw.DoEx(&m_legacy_rumble_unlocked, 44, false); sw.Do(&m_configuration_mode); sw.Do(&m_command_param); 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_command); sw.DoEx(&m_rumble_config, 45, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); sw.DoEx(&m_rumble_config_large_motor_index, 45, -1); sw.DoEx(&m_rumble_config_small_motor_index, 45, -1); sw.DoEx(&m_analog_toggle_queued, 45, false); MotorState motor_state = m_motor_state; sw.Do(&motor_state); if (sw.IsReading()) { for (u8 i = 0; i < NUM_MOTORS; i++) SetMotorState(i, motor_state[i]); if (old_analog_mode != m_analog_mode) { g_host_interface->AddFormattedOSDMessage( 5.0f, m_analog_mode ? g_host_interface->TranslateString("AnalogController", "Controller %u switched to analog mode.") : g_host_interface->TranslateString("AnalogController", "Controller %u switched to digital mode."), m_index + 1u); } } return true; } std::optional AnalogController::GetAxisCodeByName(std::string_view axis_name) const { return StaticGetAxisCodeByName(axis_name); } std::optional AnalogController::GetButtonCodeByName(std::string_view button_name) const { return StaticGetButtonCodeByName(button_name); } void AnalogController::SetAxisState(s32 axis_code, float value) { if (axis_code < 0 || axis_code >= static_cast(Axis::Count)) return; // -1..1 -> 0..255 const float scaled_value = std::clamp(value * m_axis_scale, -1.0f, 1.0f); const u8 u8_value = static_cast(std::clamp(((scaled_value + 1.0f) / 2.0f) * 255.0f, 0.0f, 255.0f)); SetAxisState(static_cast(axis_code), u8_value); } void AnalogController::SetAxisState(Axis axis, u8 value) { if (value != m_axis_state[static_cast(axis)]) System::SetRunaheadReplayFlag(); m_axis_state[static_cast(axis)] = value; } void AnalogController::SetButtonState(Button button, bool pressed) { if (button == Button::Analog) { // analog toggle if (pressed) { if (m_command == Command::Idle) ProcessAnalogModeToggle(); else m_analog_toggle_queued = true; } return; } const u16 bit = u16(1) << static_cast(button); if (pressed) { if (m_button_state & bit) System::SetRunaheadReplayFlag(); m_button_state &= ~(bit); } else { if (!(m_button_state & bit)) System::SetRunaheadReplayFlag(); m_button_state |= bit; } } void AnalogController::SetButtonState(s32 button_code, bool pressed) { if (button_code < 0 || button_code >= static_cast(Button::Count)) return; SetButtonState(static_cast