From 24fb22acf38d9a30fde6302a94826ca4c1405308 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 8 Jun 2026 19:50:10 +1000 Subject: [PATCH] Controller: Move helper functions into their own file --- src/core/CMakeLists.txt | 1 + src/core/analog_controller.cpp | 51 +++++++++++++++++----------------- src/core/analog_joystick.cpp | 51 +++++++++++++++++----------------- src/core/controller.cpp | 23 +-------------- src/core/controller.h | 11 +------- src/core/controller_helpers.h | 36 ++++++++++++++++++++++++ src/core/core.vcxproj | 1 + src/core/core.vcxproj.filters | 1 + src/core/negcon_rumble.cpp | 5 ++-- 9 files changed, 96 insertions(+), 84 deletions(-) create mode 100644 src/core/controller_helpers.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index d7f886cd2..fc724bfcd 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -26,6 +26,7 @@ add_library(core cheats.h controller.cpp controller.h + controller_helpers.h core.cpp core.h cpu_code_cache.cpp diff --git a/src/core/analog_controller.cpp b/src/core/analog_controller.cpp index 6d4478619..422fc3622 100644 --- a/src/core/analog_controller.cpp +++ b/src/core/analog_controller.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #include "analog_controller.h" +#include "controller_helpers.h" #include "settings.h" #include "system.h" @@ -192,30 +193,30 @@ void AnalogController::SetBindState(u32 index, float value) { case HalfAxis::LLeft: case HalfAxis::LRight: - m_axis_state[static_cast(Axis::LeftX)] = - MergeHalfAxes(m_half_axis_state[static_cast(HalfAxis::LLeft)], - m_half_axis_state[static_cast(HalfAxis::LRight)], (m_invert_left_stick & 1)); + m_axis_state[static_cast(Axis::LeftX)] = ControllerHelpers::MergeHalfAxes( + m_half_axis_state[static_cast(HalfAxis::LLeft)], + m_half_axis_state[static_cast(HalfAxis::LRight)], (m_invert_left_stick & 1)); break; case HalfAxis::LDown: case HalfAxis::LUp: - m_axis_state[static_cast(Axis::LeftY)] = - MergeHalfAxes(m_half_axis_state[static_cast(HalfAxis::LUp)], - m_half_axis_state[static_cast(HalfAxis::LDown)], (m_invert_left_stick & 2)); + m_axis_state[static_cast(Axis::LeftY)] = ControllerHelpers::MergeHalfAxes( + m_half_axis_state[static_cast(HalfAxis::LUp)], + m_half_axis_state[static_cast(HalfAxis::LDown)], (m_invert_left_stick & 2)); break; case HalfAxis::RLeft: case HalfAxis::RRight: - m_axis_state[static_cast(Axis::RightX)] = - MergeHalfAxes(m_half_axis_state[static_cast(HalfAxis::RLeft)], - m_half_axis_state[static_cast(HalfAxis::RRight)], (m_invert_right_stick & 1)); + m_axis_state[static_cast(Axis::RightX)] = ControllerHelpers::MergeHalfAxes( + m_half_axis_state[static_cast(HalfAxis::RLeft)], + m_half_axis_state[static_cast(HalfAxis::RRight)], (m_invert_right_stick & 1)); break; case HalfAxis::RDown: case HalfAxis::RUp: - m_axis_state[static_cast(Axis::RightY)] = - MergeHalfAxes(m_half_axis_state[static_cast(HalfAxis::RUp)], - m_half_axis_state[static_cast(HalfAxis::RDown)], (m_invert_right_stick & 2)); + m_axis_state[static_cast(Axis::RightY)] = ControllerHelpers::MergeHalfAxes( + m_half_axis_state[static_cast(HalfAxis::RUp)], + m_half_axis_state[static_cast(HalfAxis::RDown)], (m_invert_right_stick & 2)); break; default: @@ -227,24 +228,24 @@ void AnalogController::SetBindState(u32 index, float value) float pos_x, pos_y; if (static_cast(sub_index) < HalfAxis::RLeft) { - pos_x = - MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::LLeft)], - m_half_axis_state[static_cast(HalfAxis::LRight)], (m_invert_left_stick & 1)); - pos_y = - MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::LUp)], - m_half_axis_state[static_cast(HalfAxis::LDown)], (m_invert_left_stick & 2)); + pos_x = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::LLeft)], + m_half_axis_state[static_cast(HalfAxis::LRight)], + (m_invert_left_stick & 1)); + pos_y = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::LUp)], + m_half_axis_state[static_cast(HalfAxis::LDown)], + (m_invert_left_stick & 2)); } else { - pos_x = - MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::RLeft)], - m_half_axis_state[static_cast(HalfAxis::RRight)], (m_invert_right_stick & 1)); - pos_y = - MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::RUp)], - m_half_axis_state[static_cast(HalfAxis::RDown)], (m_invert_right_stick & 2)); + pos_x = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::RLeft)], + m_half_axis_state[static_cast(HalfAxis::RRight)], + (m_invert_right_stick & 1)); + pos_y = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::RUp)], + m_half_axis_state[static_cast(HalfAxis::RDown)], + (m_invert_right_stick & 2)); } - if (InCircularDeadzone(m_analog_deadzone, pos_x, pos_y)) + if (ControllerHelpers::InCircularDeadzone(m_analog_deadzone, pos_x, pos_y)) { if (static_cast(sub_index) < HalfAxis::RLeft) m_axis_state[static_cast(Axis::LeftX)] = m_axis_state[static_cast(Axis::LeftY)] = AXIS_CENTER; diff --git a/src/core/analog_joystick.cpp b/src/core/analog_joystick.cpp index a8bff5994..dd025ded4 100644 --- a/src/core/analog_joystick.cpp +++ b/src/core/analog_joystick.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #include "analog_joystick.h" +#include "controller_helpers.h" #include "system.h" #include "util/imgui_manager.h" @@ -112,30 +113,30 @@ void AnalogJoystick::SetBindState(u32 index, float value) { case HalfAxis::LLeft: case HalfAxis::LRight: - m_axis_state[static_cast(Axis::LeftX)] = - MergeHalfAxes(m_half_axis_state[static_cast(HalfAxis::LLeft)], - m_half_axis_state[static_cast(HalfAxis::LRight)], (m_invert_left_stick & 1)); + m_axis_state[static_cast(Axis::LeftX)] = ControllerHelpers::MergeHalfAxes( + m_half_axis_state[static_cast(HalfAxis::LLeft)], + m_half_axis_state[static_cast(HalfAxis::LRight)], (m_invert_left_stick & 1)); break; case HalfAxis::LDown: case HalfAxis::LUp: - m_axis_state[static_cast(Axis::LeftY)] = - MergeHalfAxes(m_half_axis_state[static_cast(HalfAxis::LUp)], - m_half_axis_state[static_cast(HalfAxis::LDown)], (m_invert_left_stick & 2)); + m_axis_state[static_cast(Axis::LeftY)] = ControllerHelpers::MergeHalfAxes( + m_half_axis_state[static_cast(HalfAxis::LUp)], + m_half_axis_state[static_cast(HalfAxis::LDown)], (m_invert_left_stick & 2)); break; case HalfAxis::RLeft: case HalfAxis::RRight: - m_axis_state[static_cast(Axis::RightX)] = - MergeHalfAxes(m_half_axis_state[static_cast(HalfAxis::RLeft)], - m_half_axis_state[static_cast(HalfAxis::RRight)], (m_invert_right_stick & 1)); + m_axis_state[static_cast(Axis::RightX)] = ControllerHelpers::MergeHalfAxes( + m_half_axis_state[static_cast(HalfAxis::RLeft)], + m_half_axis_state[static_cast(HalfAxis::RRight)], (m_invert_right_stick & 1)); break; case HalfAxis::RDown: case HalfAxis::RUp: - m_axis_state[static_cast(Axis::RightY)] = - MergeHalfAxes(m_half_axis_state[static_cast(HalfAxis::RUp)], - m_half_axis_state[static_cast(HalfAxis::RDown)], (m_invert_right_stick & 2)); + m_axis_state[static_cast(Axis::RightY)] = ControllerHelpers::MergeHalfAxes( + m_half_axis_state[static_cast(HalfAxis::RUp)], + m_half_axis_state[static_cast(HalfAxis::RDown)], (m_invert_right_stick & 2)); break; default: @@ -147,24 +148,24 @@ void AnalogJoystick::SetBindState(u32 index, float value) float pos_x, pos_y; if (static_cast(sub_index) < HalfAxis::RLeft) { - pos_x = - MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::LLeft)], - m_half_axis_state[static_cast(HalfAxis::LRight)], (m_invert_left_stick & 1)); - pos_y = - MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::LUp)], - m_half_axis_state[static_cast(HalfAxis::LDown)], (m_invert_left_stick & 2)); + pos_x = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::LLeft)], + m_half_axis_state[static_cast(HalfAxis::LRight)], + (m_invert_left_stick & 1)); + pos_y = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::LUp)], + m_half_axis_state[static_cast(HalfAxis::LDown)], + (m_invert_left_stick & 2)); } else { - pos_x = - MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::RLeft)], - m_half_axis_state[static_cast(HalfAxis::RRight)], (m_invert_right_stick & 1)); - pos_y = - MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::RUp)], - m_half_axis_state[static_cast(HalfAxis::RDown)], (m_invert_right_stick & 2)); + pos_x = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::RLeft)], + m_half_axis_state[static_cast(HalfAxis::RRight)], + (m_invert_right_stick & 1)); + pos_y = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast(HalfAxis::RUp)], + m_half_axis_state[static_cast(HalfAxis::RDown)], + (m_invert_right_stick & 2)); } - if (InCircularDeadzone(m_analog_deadzone, pos_x, pos_y)) + if (ControllerHelpers::InCircularDeadzone(m_analog_deadzone, pos_x, pos_y)) { if (static_cast(sub_index) < HalfAxis::RLeft) m_axis_state[static_cast(Axis::LeftX)] = m_axis_state[static_cast(Axis::LeftY)] = AXIS_CENTER; diff --git a/src/core/controller.cpp b/src/core/controller.cpp index f5a3a0503..997bed515 100644 --- a/src/core/controller.cpp +++ b/src/core/controller.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #include "controller.h" @@ -220,13 +220,6 @@ std::string Controller::GetSettingsSection(u32 pad) return fmt::format("Pad{}", pad + 1u); } -bool Controller::InCircularDeadzone(float deadzone, float pos_x, float pos_y) -{ - // Calculate the actual distance from center, and compare to deadzone radius. - const float distance = std::sqrt(pos_x * pos_x + pos_y * pos_y); - return (distance <= deadzone); -} - bool Controller::CanStartInAnalogMode(ControllerType ctype) { if (!g_settings.apply_compatibility_settings) @@ -239,17 +232,3 @@ bool Controller::CanStartInAnalogMode(ControllerType ctype) return ((dbentry->supported_controllers & (1u << static_cast(ctype))) != 0 && !dbentry->HasTrait(GameDatabase::Trait::DisableAutoAnalogMode)); } - -u8 Controller::MergeHalfAxes(u8 neg_value, u8 pos_value, bool invert) -{ - if (invert) - std::swap(neg_value, pos_value); - - return static_cast(128 + (static_cast(pos_value) / 2) - ((static_cast(neg_value) + 1) / 2)); -} - -float Controller::MergeHalfAxesToFloat(u8 neg_value, u8 pos_value, bool invert) -{ - const float result = (static_cast(pos_value) - static_cast(neg_value)) / 255.0f; - return (invert ? -result : result); -} diff --git a/src/core/controller.h b/src/core/controller.h index bf6cfe449..5d7e3e51b 100644 --- a/src/core/controller.h +++ b/src/core/controller.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #pragma once @@ -96,9 +96,6 @@ public: static const ControllerInfo& GetControllerInfo(ControllerType type); static const ControllerInfo* GetControllerInfo(std::string_view name); - /// Returns true if the specified coordinates are inside a circular deadzone. - static bool InCircularDeadzone(float deadzone, float pos_x, float pos_y); - /// Converts a global pad index to a multitap port and slot. static std::tuple ConvertPadToPortAndSlot(u32 index); @@ -122,12 +119,6 @@ public: /// Returns true if automatic analog mode can be used. static bool CanStartInAnalogMode(ControllerType ctype); - /// Converts a 0..255 half-axis value to an unsigned 8-bit value, with 128 indicating center. - static u8 MergeHalfAxes(u8 neg_value, u8 pos_value, bool invert); - - /// Converts a 0..255 half-axis value to a normalized floating-point value, with 0 indicating center. - static float MergeHalfAxesToFloat(u8 neg_value, u8 pos_value, bool invert); - protected: u32 m_index; }; diff --git a/src/core/controller_helpers.h b/src/core/controller_helpers.h new file mode 100644 index 000000000..df08331b4 --- /dev/null +++ b/src/core/controller_helpers.h @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin +// SPDX-License-Identifier: CC-BY-NC-ND-4.0 + +#pragma once + +#include "common/types.h" + +#include + +namespace ControllerHelpers { + +/// Returns true if the specified coordinates are inside a circular deadzone. +ALWAYS_INLINE bool InCircularDeadzone(float deadzone, float pos_x, float pos_y) +{ + // Calculate the actual distance from center, and compare to deadzone radius. + const float distance = std::sqrt(pos_x * pos_x + pos_y * pos_y); + return (distance <= deadzone); +} + +/// Converts a 0..255 half-axis value to an unsigned 8-bit value, with 128 indicating center. +ALWAYS_INLINE u8 MergeHalfAxes(u8 neg_value, u8 pos_value, bool invert) +{ + if (invert) + std::swap(neg_value, pos_value); + + return static_cast(128 + (static_cast(pos_value) / 2) - ((static_cast(neg_value) + 1) / 2)); +} + +/// Converts a 0..255 half-axis value to a normalized floating-point value, with 0 indicating center. +ALWAYS_INLINE float MergeHalfAxesToFloat(u8 neg_value, u8 pos_value, bool invert) +{ + const float result = (static_cast(pos_value) - static_cast(neg_value)) / 255.0f; + return (invert ? -result : result); +} + +} // namespace ControllerHelpers \ No newline at end of file diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index b7d345c62..5da86b75b 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -96,6 +96,7 @@ + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 7acb63471..60a4fe431 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -160,6 +160,7 @@ + diff --git a/src/core/negcon_rumble.cpp b/src/core/negcon_rumble.cpp index efb7d88d3..e6dee6517 100644 --- a/src/core/negcon_rumble.cpp +++ b/src/core/negcon_rumble.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #include "negcon_rumble.h" +#include "controller_helpers.h" #include "settings.h" #include "system.h" @@ -172,8 +173,8 @@ void NeGconRumble::SetBindState(u32 index, float value) static_cast(std::clamp(value * 255.0f, 0.0f, 255.0f)); m_axis_state[static_cast(Axis::Steering)] = - MergeHalfAxes(m_half_axis_state[static_cast(HalfAxis::SteeringLeft)], - m_half_axis_state[static_cast(HalfAxis::SteeringRight)], false); + ControllerHelpers::MergeHalfAxes(m_half_axis_state[static_cast(HalfAxis::SteeringLeft)], + m_half_axis_state[static_cast(HalfAxis::SteeringRight)], false); } else if (index >= static_cast(Button::Count)) {