From 6d14583f287c5b19ebb06636b9c6ecd1541436d2 Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez Date: Tue, 15 Aug 2017 14:14:13 -0500 Subject: [PATCH] Better evdev joystick axis scaling (#3202) Fix evdev scaling when the minimum value is <0 Declare a trigger as pressed as long as any value >0 is given --- rpcs3/evdev_joystick_handler.cpp | 56 +++++++++++++++++++------------- rpcs3/evdev_joystick_handler.h | 5 +-- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/rpcs3/evdev_joystick_handler.cpp b/rpcs3/evdev_joystick_handler.cpp index 91e450da96..e3f92029bc 100644 --- a/rpcs3/evdev_joystick_handler.cpp +++ b/rpcs3/evdev_joystick_handler.cpp @@ -34,7 +34,6 @@ void evdev_joystick_handler::Init(const u32 max_connect) g_evdev_joystick_config.load(); - needscale = static_cast(g_evdev_joystick_config.needscale); axistrigger = static_cast(g_evdev_joystick_config.axistrigger); revaxis.emplace_back(g_evdev_joystick_config.lxreverse); @@ -173,12 +172,16 @@ bool evdev_joystick_handler::try_open_dev(u32 index) int axes=0; for (int i=ABS_X; i<=ABS_RZ; i++) { - // Skip ABS_Z and ABS_RZ on controllers where it's used for the triggers. - if (axistrigger && (i == ABS_Z || i == ABS_RZ)) continue; if (libevdev_has_event_code(dev, EV_ABS, i)) { LOG_NOTICE(GENERAL, "Joystick #%d has axis %d as %d", index, i, axes); + + axis_ranges[i].first = libevdev_get_abs_minimum(dev, i); + axis_ranges[i].second = libevdev_get_abs_maximum(dev, i); + + // Skip ABS_Z and ABS_RZ on controllers where it's used for the triggers. + if (axistrigger && (i == ABS_Z || i == ABS_RZ)) continue; joy_axis_maps[index][i - ABS_X] = axes++; } } @@ -220,6 +223,28 @@ void evdev_joystick_handler::Close() } } +int evdev_joystick_handler::scale_axis(int axis, int value) +{ + auto range = axis_ranges[axis]; + // Check if scaling is needed. + if (range.first != 0 || range.second != 255) + { + if (range.first < 0) + { + // Move the ranges up to make the following calculation actually *work* + value += -range.first; + range.second += -range.first; + range.first = 0; + } + + return (static_cast(value - range.first) / range.second) * 255; + } + else + { + return value; + } +} + void evdev_joystick_handler::thread_func() { while (active) @@ -331,7 +356,7 @@ void evdev_joystick_handler::thread_func() } else if (axistrigger && (evt.code == ABS_Z || evt.code == ABS_RZ)) { - // For Xbox 360 controllers, a third axis represent the left/right triggers. + // For Xbox controllers, a third axis represent the left/right triggers. int which_trigger=0; if (evt.code == ABS_Z) @@ -356,8 +381,10 @@ void evdev_joystick_handler::thread_func() LOG_ERROR(GENERAL, "Joystick #%d's pad has no trigger %d", i, which_trigger); break; } - which_button->m_pressed = evt.value == 255; - which_button->m_value = evt.value; + + int value = scale_axis(evt.code, evt.value); + which_button->m_pressed = value > 0; + which_button->m_value = value; } else if (evt.code >= ABS_X && evt.code <= ABS_RZ) { @@ -369,22 +396,7 @@ void evdev_joystick_handler::thread_func() break; } - auto& stick = pad.m_sticks[axis]; - - int value = evt.value; - - if (needscale) - { - // Scale from the -32768...32768 range to the 0...256 range. - value = (value / 256) + 128; - } - - if (revaxis[axis]) - { - value = 256 - value; - } - - stick.m_value = value; + pad.m_sticks[axis].m_value = scale_axis(evt.code, evt.value); } break; default: diff --git a/rpcs3/evdev_joystick_handler.h b/rpcs3/evdev_joystick_handler.h index 66285687fe..30e8a9a120 100644 --- a/rpcs3/evdev_joystick_handler.h +++ b/rpcs3/evdev_joystick_handler.h @@ -44,7 +44,6 @@ struct evdev_joystick_config final : cfg::node cfg::_bool lxreverse{this, "Reverse left stick X axis", false}; cfg::_bool lyreverse{this, "Reverse left stick Y axis", false}; - cfg::_bool needscale{this, "Axis scaling", true}; cfg::_bool axistrigger{this, "Z axis triggers", true}; bool load() @@ -76,6 +75,7 @@ public: private: void update_devs(); bool try_open_dev(u32 index); + int scale_axis(int axis, int value); void thread_func(); std::unique_ptr joy_thread; @@ -85,6 +85,7 @@ private: std::vector> joy_button_maps; std::vector> joy_axis_maps; std::vector joy_hat_ids; - bool needscale, axistrigger; + bool axistrigger; + std::map> axis_ranges; std::vector revaxis; };