Controller: Move helper functions into their own file

pull/3750/head
Stenzek 4 months ago
parent 1e6a006bd0
commit 24fb22acf3
No known key found for this signature in database

@ -26,6 +26,7 @@ add_library(core
cheats.h
controller.cpp
controller.h
controller_helpers.h
core.cpp
core.h
cpu_code_cache.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,29 +193,29 @@ void AnalogController::SetBindState(u32 index, float value)
{
case HalfAxis::LLeft:
case HalfAxis::LRight:
m_axis_state[static_cast<u8>(Axis::LeftX)] =
MergeHalfAxes(m_half_axis_state[static_cast<size_t>(HalfAxis::LLeft)],
m_axis_state[static_cast<u8>(Axis::LeftX)] = ControllerHelpers::MergeHalfAxes(
m_half_axis_state[static_cast<size_t>(HalfAxis::LLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LRight)], (m_invert_left_stick & 1));
break;
case HalfAxis::LDown:
case HalfAxis::LUp:
m_axis_state[static_cast<u8>(Axis::LeftY)] =
MergeHalfAxes(m_half_axis_state[static_cast<size_t>(HalfAxis::LUp)],
m_axis_state[static_cast<u8>(Axis::LeftY)] = ControllerHelpers::MergeHalfAxes(
m_half_axis_state[static_cast<size_t>(HalfAxis::LUp)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LDown)], (m_invert_left_stick & 2));
break;
case HalfAxis::RLeft:
case HalfAxis::RRight:
m_axis_state[static_cast<u8>(Axis::RightX)] =
MergeHalfAxes(m_half_axis_state[static_cast<size_t>(HalfAxis::RLeft)],
m_axis_state[static_cast<u8>(Axis::RightX)] = ControllerHelpers::MergeHalfAxes(
m_half_axis_state[static_cast<size_t>(HalfAxis::RLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::RRight)], (m_invert_right_stick & 1));
break;
case HalfAxis::RDown:
case HalfAxis::RUp:
m_axis_state[static_cast<u8>(Axis::RightY)] =
MergeHalfAxes(m_half_axis_state[static_cast<size_t>(HalfAxis::RUp)],
m_axis_state[static_cast<u8>(Axis::RightY)] = ControllerHelpers::MergeHalfAxes(
m_half_axis_state[static_cast<size_t>(HalfAxis::RUp)],
m_half_axis_state[static_cast<size_t>(HalfAxis::RDown)], (m_invert_right_stick & 2));
break;
@ -227,24 +228,24 @@ void AnalogController::SetBindState(u32 index, float value)
float pos_x, pos_y;
if (static_cast<HalfAxis>(sub_index) < HalfAxis::RLeft)
{
pos_x =
MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::LLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LRight)], (m_invert_left_stick & 1));
pos_y =
MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::LUp)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LDown)], (m_invert_left_stick & 2));
pos_x = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::LLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LRight)],
(m_invert_left_stick & 1));
pos_y = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::LUp)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LDown)],
(m_invert_left_stick & 2));
}
else
{
pos_x =
MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::RLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::RRight)], (m_invert_right_stick & 1));
pos_y =
MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::RUp)],
m_half_axis_state[static_cast<size_t>(HalfAxis::RDown)], (m_invert_right_stick & 2));
pos_x = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::RLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::RRight)],
(m_invert_right_stick & 1));
pos_y = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::RUp)],
m_half_axis_state[static_cast<size_t>(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<HalfAxis>(sub_index) < HalfAxis::RLeft)
m_axis_state[static_cast<u8>(Axis::LeftX)] = m_axis_state[static_cast<u8>(Axis::LeftY)] = AXIS_CENTER;

@ -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,29 +113,29 @@ void AnalogJoystick::SetBindState(u32 index, float value)
{
case HalfAxis::LLeft:
case HalfAxis::LRight:
m_axis_state[static_cast<u8>(Axis::LeftX)] =
MergeHalfAxes(m_half_axis_state[static_cast<size_t>(HalfAxis::LLeft)],
m_axis_state[static_cast<u8>(Axis::LeftX)] = ControllerHelpers::MergeHalfAxes(
m_half_axis_state[static_cast<size_t>(HalfAxis::LLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LRight)], (m_invert_left_stick & 1));
break;
case HalfAxis::LDown:
case HalfAxis::LUp:
m_axis_state[static_cast<u8>(Axis::LeftY)] =
MergeHalfAxes(m_half_axis_state[static_cast<size_t>(HalfAxis::LUp)],
m_axis_state[static_cast<u8>(Axis::LeftY)] = ControllerHelpers::MergeHalfAxes(
m_half_axis_state[static_cast<size_t>(HalfAxis::LUp)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LDown)], (m_invert_left_stick & 2));
break;
case HalfAxis::RLeft:
case HalfAxis::RRight:
m_axis_state[static_cast<u8>(Axis::RightX)] =
MergeHalfAxes(m_half_axis_state[static_cast<size_t>(HalfAxis::RLeft)],
m_axis_state[static_cast<u8>(Axis::RightX)] = ControllerHelpers::MergeHalfAxes(
m_half_axis_state[static_cast<size_t>(HalfAxis::RLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::RRight)], (m_invert_right_stick & 1));
break;
case HalfAxis::RDown:
case HalfAxis::RUp:
m_axis_state[static_cast<u8>(Axis::RightY)] =
MergeHalfAxes(m_half_axis_state[static_cast<size_t>(HalfAxis::RUp)],
m_axis_state[static_cast<u8>(Axis::RightY)] = ControllerHelpers::MergeHalfAxes(
m_half_axis_state[static_cast<size_t>(HalfAxis::RUp)],
m_half_axis_state[static_cast<size_t>(HalfAxis::RDown)], (m_invert_right_stick & 2));
break;
@ -147,24 +148,24 @@ void AnalogJoystick::SetBindState(u32 index, float value)
float pos_x, pos_y;
if (static_cast<HalfAxis>(sub_index) < HalfAxis::RLeft)
{
pos_x =
MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::LLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LRight)], (m_invert_left_stick & 1));
pos_y =
MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::LUp)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LDown)], (m_invert_left_stick & 2));
pos_x = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::LLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LRight)],
(m_invert_left_stick & 1));
pos_y = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::LUp)],
m_half_axis_state[static_cast<size_t>(HalfAxis::LDown)],
(m_invert_left_stick & 2));
}
else
{
pos_x =
MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::RLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::RRight)], (m_invert_right_stick & 1));
pos_y =
MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::RUp)],
m_half_axis_state[static_cast<size_t>(HalfAxis::RDown)], (m_invert_right_stick & 2));
pos_x = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::RLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::RRight)],
(m_invert_right_stick & 1));
pos_y = ControllerHelpers::MergeHalfAxesToFloat(m_half_axis_state[static_cast<size_t>(HalfAxis::RUp)],
m_half_axis_state[static_cast<size_t>(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<HalfAxis>(sub_index) < HalfAxis::RLeft)
m_axis_state[static_cast<u8>(Axis::LeftX)] = m_axis_state[static_cast<u8>(Axis::LeftY)] = AXIS_CENTER;

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <stenzek@gmail.com>
// 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<u8>(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<u8>(128 + (static_cast<u32>(pos_value) / 2) - ((static_cast<u32>(neg_value) + 1) / 2));
}
float Controller::MergeHalfAxesToFloat(u8 neg_value, u8 pos_value, bool invert)
{
const float result = (static_cast<s32>(pos_value) - static_cast<s32>(neg_value)) / 255.0f;
return (invert ? -result : result);
}

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <stenzek@gmail.com>
// 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<u32, u32> 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;
};

@ -0,0 +1,36 @@
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
#pragma once
#include "common/types.h"
#include <cmath>
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<u8>(128 + (static_cast<u32>(pos_value) / 2) - ((static_cast<u32>(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<s32>(pos_value) - static_cast<s32>(neg_value)) / 255.0f;
return (invert ? -result : result);
}
} // namespace ControllerHelpers

@ -96,6 +96,7 @@
<ClInclude Include="cdrom_subq_replacement.h" />
<ClInclude Include="cheats.h" />
<ClInclude Include="achievements.h" />
<ClInclude Include="controller_helpers.h" />
<ClInclude Include="core.h" />
<ClInclude Include="core_private.h" />
<ClInclude Include="cpu_code_cache_private.h" />

@ -160,6 +160,7 @@
<ClInclude Include="gpu_helpers.h" />
<ClInclude Include="discord_presence.h" />
<ClInclude Include="video_thread_private.h" />
<ClInclude Include="controller_helpers.h" />
</ItemGroup>
<ItemGroup>
<None Include="gpu_sw_rasterizer.inl" />

@ -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,7 +173,7 @@ void NeGconRumble::SetBindState(u32 index, float value)
static_cast<u8>(std::clamp(value * 255.0f, 0.0f, 255.0f));
m_axis_state[static_cast<u32>(Axis::Steering)] =
MergeHalfAxes(m_half_axis_state[static_cast<size_t>(HalfAxis::SteeringLeft)],
ControllerHelpers::MergeHalfAxes(m_half_axis_state[static_cast<size_t>(HalfAxis::SteeringLeft)],
m_half_axis_state[static_cast<size_t>(HalfAxis::SteeringRight)], false);
}
else if (index >= static_cast<u32>(Button::Count))

Loading…
Cancel
Save