diff --git a/rpcs3/Emu/Io/PadHandler.cpp b/rpcs3/Emu/Io/PadHandler.cpp index 544cab563c..2efdebc585 100644 --- a/rpcs3/Emu/Io/PadHandler.cpp +++ b/rpcs3/Emu/Io/PadHandler.cpp @@ -261,9 +261,13 @@ PadHandlerBase::connection PadHandlerBase::get_next_button_press(const std::stri const bool is_trigger = get_is_left_trigger(device, keycode) || get_is_right_trigger(device, keycode); const bool is_stick = !is_trigger && (get_is_left_stick(device, keycode) || get_is_right_stick(device, keycode)); - const bool is_button = !is_trigger && !is_stick; + const bool is_touch_motion = !is_trigger && !is_stick && get_is_touch_pad_motion(device, keycode); + const bool is_button = !is_trigger && !is_stick && !is_touch_motion; - if ((is_trigger && (value > m_trigger_threshold)) || (is_stick && (value > m_thumb_threshold)) || (is_button && (value > 0))) + if ((is_trigger && (value > m_trigger_threshold)) || + (is_stick && (value > m_thumb_threshold)) || + (is_button && (value > 0)) || + (is_touch_motion && (value > 255 * 0.9))) { if (get_blacklist) { diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index 3081657c86..dfdc5c4f7e 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -290,6 +290,7 @@ private: virtual bool get_is_right_trigger(const std::shared_ptr& /*device*/, u64 /*keyCode*/) { return false; } virtual bool get_is_left_stick(const std::shared_ptr& /*device*/, u64 /*keyCode*/) { return false; } virtual bool get_is_right_stick(const std::shared_ptr& /*device*/, u64 /*keyCode*/) { return false; } + virtual bool get_is_touch_pad_motion(const std::shared_ptr& /*device*/, u64 /*keyCode*/) { return false; } virtual PadHandlerBase::connection update_connection(const std::shared_ptr& /*device*/) { return connection::disconnected; } virtual void get_extended_info(const pad_ensemble& /*binding*/) {} virtual void apply_pad_data(const pad_ensemble& /*binding*/) {} diff --git a/rpcs3/Input/ds4_pad_handler.cpp b/rpcs3/Input/ds4_pad_handler.cpp index 427773afb7..2b80d17c0e 100644 --- a/rpcs3/Input/ds4_pad_handler.cpp +++ b/rpcs3/Input/ds4_pad_handler.cpp @@ -85,6 +85,10 @@ ds4_pad_handler::ds4_pad_handler() { DS4KeyCodes::Share, "Share" }, { DS4KeyCodes::PSButton, "PS Button" }, { DS4KeyCodes::TouchPad, "Touch Pad" }, + { DS4KeyCodes::Touch_L, "Touch Left" }, + { DS4KeyCodes::Touch_R, "Touch Right" }, + { DS4KeyCodes::Touch_U, "Touch Up" }, + { DS4KeyCodes::Touch_D, "Touch Down" }, { DS4KeyCodes::L1, "L1" }, { DS4KeyCodes::L2, "L2" }, { DS4KeyCodes::L3, "L3" }, @@ -333,6 +337,47 @@ std::unordered_map ds4_pad_handler::get_button_values(const std::share keyBuffer[DS4KeyCodes::L2] = input.z; keyBuffer[DS4KeyCodes::R2] = input.rz; + // Touch Pad + const auto apply_touch = [&keyBuffer](const ds4_touch_report& touch) + { + for (const ds4_touch_point& point : touch.points) + { + if (!(point.contact & DS4_TOUCH_POINT_INACTIVE)) + { + const s32 x = (point.x_hi << 8) | point.x_lo; + const s32 y = (point.y_hi << 4) | point.y_lo; + + const f32 x_scaled = ScaledInput(static_cast(x), 0.0f, static_cast(DS4_TOUCHPAD_WIDTH), 0.0f, 255.0f); + const f32 y_scaled = ScaledInput(static_cast(y), 0.0f, static_cast(DS4_TOUCHPAD_HEIGHT), 0.0f, 255.0f); + + keyBuffer[DS4KeyCodes::Touch_L] = Clamp0To255((127.5f - x_scaled) * 2.0f); + keyBuffer[DS4KeyCodes::Touch_R] = Clamp0To255((x_scaled - 127.5f) * 2.0f); + + keyBuffer[DS4KeyCodes::Touch_U] = Clamp0To255((127.5f - y_scaled) * 2.0f); + keyBuffer[DS4KeyCodes::Touch_D] = Clamp0To255((y_scaled - 127.5f) * 2.0f); + } + } + }; + + if (ds4_dev->bt_controller) + { + const ds4_input_report_bt& report = ds4_dev->report_bt; + + for (u32 i = 0; i < std::min(report.num_touch_reports, ::size32(report.touch_reports)); i++) + { + apply_touch(report.touch_reports[i]); + } + } + else + { + const ds4_input_report_usb& report = ds4_dev->report_usb; + + for (u32 i = 0; i < std::min(report.num_touch_reports, ::size32(report.touch_reports)); i++) + { + apply_touch(report.touch_reports[i]); + } + } + return keyBuffer; } @@ -759,6 +804,20 @@ bool ds4_pad_handler::get_is_right_stick(const std::shared_ptr& /*dev } } +bool ds4_pad_handler::get_is_touch_pad_motion(const std::shared_ptr& /*device*/, u64 keyCode) +{ + switch (keyCode) + { + case DS4KeyCodes::Touch_L: + case DS4KeyCodes::Touch_R: + case DS4KeyCodes::Touch_U: + case DS4KeyCodes::Touch_D: + return true; + default: + return false; + } +} + PadHandlerBase::connection ds4_pad_handler::update_connection(const std::shared_ptr& device) { DS4Device* ds4_dev = static_cast(device.get()); diff --git a/rpcs3/Input/ds4_pad_handler.h b/rpcs3/Input/ds4_pad_handler.h index aab8b49623..37c51dcfe2 100644 --- a/rpcs3/Input/ds4_pad_handler.h +++ b/rpcs3/Input/ds4_pad_handler.h @@ -19,6 +19,7 @@ namespace reports constexpr u32 DS4_OUTPUT_REPORT_BLUETOOTH_SIZE = 78; constexpr u32 DS4_TOUCHPAD_WIDTH = 1920; constexpr u32 DS4_TOUCHPAD_HEIGHT = 942; + constexpr u32 DS4_TOUCH_POINT_INACTIVE = 0x80; struct ds4_touch_point { @@ -33,7 +34,7 @@ namespace reports struct ds4_touch_report { u8 timestamp; - ds4_touch_point points[2]; + std::array points; }; static_assert(sizeof(ds4_touch_report) == 9); @@ -61,7 +62,7 @@ namespace reports u8 report_id; ds4_input_report_common common; u8 num_touch_reports; - ds4_touch_report touch_reports[3]; + std::array touch_reports; u8 reserved[3]; }; static_assert(sizeof(ds4_input_report_usb) == DS4_INPUT_REPORT_USB_SIZE); @@ -72,7 +73,7 @@ namespace reports u8 reserved[2]; ds4_input_report_common common; u8 num_touch_reports; - ds4_touch_report touch_reports[4]; + std::array touch_reports; u8 reserved2[2]; u8 crc32[4]; }; @@ -150,6 +151,11 @@ class ds4_pad_handler final : public hid_pad_handler PSButton, TouchPad, + Touch_L, + Touch_R, + Touch_U, + Touch_D, + L2, R2, @@ -184,6 +190,7 @@ private: bool get_is_right_trigger(const std::shared_ptr& device, u64 keyCode) override; bool get_is_left_stick(const std::shared_ptr& device, u64 keyCode) override; bool get_is_right_stick(const std::shared_ptr& device, u64 keyCode) override; + bool get_is_touch_pad_motion(const std::shared_ptr& device, u64 keyCode) override; PadHandlerBase::connection update_connection(const std::shared_ptr& device) override; void get_extended_info(const pad_ensemble& binding) override; void apply_pad_data(const pad_ensemble& binding) override; diff --git a/rpcs3/Input/dualsense_pad_handler.cpp b/rpcs3/Input/dualsense_pad_handler.cpp index 57c646f446..fcda473cbd 100644 --- a/rpcs3/Input/dualsense_pad_handler.cpp +++ b/rpcs3/Input/dualsense_pad_handler.cpp @@ -52,6 +52,10 @@ dualsense_pad_handler::dualsense_pad_handler() { DualSenseKeyCodes::PSButton, "PS Button" }, { DualSenseKeyCodes::Mic, "Mic" }, { DualSenseKeyCodes::TouchPad, "Touch Pad" }, + { DualSenseKeyCodes::Touch_L, "Touch Left" }, + { DualSenseKeyCodes::Touch_R, "Touch Right" }, + { DualSenseKeyCodes::Touch_U, "Touch Up" }, + { DualSenseKeyCodes::Touch_D, "Touch Down" }, { DualSenseKeyCodes::L1, "L1" }, { DualSenseKeyCodes::L2, "L2" }, { DualSenseKeyCodes::L3, "L3" }, @@ -538,6 +542,20 @@ bool dualsense_pad_handler::get_is_right_stick(const std::shared_ptr& } } +bool dualsense_pad_handler::get_is_touch_pad_motion(const std::shared_ptr& /*device*/, u64 keyCode) +{ + switch (keyCode) + { + case DualSenseKeyCodes::Touch_L: + case DualSenseKeyCodes::Touch_R: + case DualSenseKeyCodes::Touch_U: + case DualSenseKeyCodes::Touch_D: + return true; + default: + return false; + } +} + PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::shared_ptr& device) { DualSenseDevice* dualsense_dev = static_cast(device.get()); @@ -728,6 +746,25 @@ std::unordered_map dualsense_pad_handler::get_button_values(const std: keyBuffer[DualSenseKeyCodes::TouchPad] = ((data & 0x02) != 0) ? 255 : 0; keyBuffer[DualSenseKeyCodes::Mic] = ((data & 0x04) != 0) ? 255 : 0; + // Touch Pad + for (const dualsense_touch_point& point : input.points) + { + if (!(point.contact & DUALSENSE_TOUCH_POINT_INACTIVE)) + { + const s32 x = (point.x_hi << 8) | point.x_lo; + const s32 y = (point.y_hi << 4) | point.y_lo; + + const f32 x_scaled = ScaledInput(static_cast(x), 0.0f, static_cast(DUALSENSE_TOUCHPAD_WIDTH), 0.0f, 255.0f); + const f32 y_scaled = ScaledInput(static_cast(y), 0.0f, static_cast(DUALSENSE_TOUCHPAD_HEIGHT), 0.0f, 255.0f); + + keyBuffer[DualSenseKeyCodes::Touch_L] = Clamp0To255((127.5f - x_scaled) * 2.0f); + keyBuffer[DualSenseKeyCodes::Touch_R] = Clamp0To255((x_scaled - 127.5f) * 2.0f); + + keyBuffer[DualSenseKeyCodes::Touch_U] = Clamp0To255((127.5f - y_scaled) * 2.0f); + keyBuffer[DualSenseKeyCodes::Touch_D] = Clamp0To255((y_scaled - 127.5f) * 2.0f); + } + } + if (dualsense_dev->feature_set == DualSenseDevice::DualSenseFeatureSet::Edge) { keyBuffer[DualSenseKeyCodes::EdgeFnL] = ((data & 0x10) != 0) ? 255 : 0; diff --git a/rpcs3/Input/dualsense_pad_handler.h b/rpcs3/Input/dualsense_pad_handler.h index 8598927b63..1a0ad46f0d 100644 --- a/rpcs3/Input/dualsense_pad_handler.h +++ b/rpcs3/Input/dualsense_pad_handler.h @@ -19,6 +19,7 @@ namespace reports constexpr u32 DUALSENSE_INPUT_REPORT_GYRO_X_OFFSET = 15; constexpr u32 DUALSENSE_TOUCHPAD_WIDTH = 1920; constexpr u32 DUALSENSE_TOUCHPAD_HEIGHT = 1080; + constexpr u32 DUALSENSE_TOUCH_POINT_INACTIVE = 0x80; enum { @@ -82,7 +83,7 @@ namespace reports le_t accel[3]; le_t sensor_timestamp; u8 reserved2; - dualsense_touch_point points[2]; + std::array points; u8 reserved3[12]; u8 status; u8 reserved4[10]; @@ -210,6 +211,11 @@ class dualsense_pad_handler final : public hid_pad_handler Mic, TouchPad, + Touch_L, + Touch_R, + Touch_U, + Touch_D, + L2, R2, @@ -247,6 +253,7 @@ private: bool get_is_right_trigger(const std::shared_ptr& device, u64 keyCode) override; bool get_is_left_stick(const std::shared_ptr& device, u64 keyCode) override; bool get_is_right_stick(const std::shared_ptr& device, u64 keyCode) override; + bool get_is_touch_pad_motion(const std::shared_ptr& device, u64 keyCode) override; PadHandlerBase::connection update_connection(const std::shared_ptr& device) override; std::unordered_map get_button_values(const std::shared_ptr& device) override; pad_preview_values get_preview_values(const std::unordered_map& data) override; diff --git a/rpcs3/Input/sdl_pad_handler.cpp b/rpcs3/Input/sdl_pad_handler.cpp index 725fe3842b..05690986ca 100644 --- a/rpcs3/Input/sdl_pad_handler.cpp +++ b/rpcs3/Input/sdl_pad_handler.cpp @@ -143,6 +143,10 @@ sdl_pad_handler::sdl_pad_handler() : PadHandlerBase(pad_handler::sdl) { SDLKeyCodes::Paddle3, "Paddle 3" }, { SDLKeyCodes::Paddle4, "Paddle 4" }, { SDLKeyCodes::Touchpad, "Touchpad" }, + { SDLKeyCodes::Touch_L, "Touch Left" }, + { SDLKeyCodes::Touch_R, "Touch Right" }, + { SDLKeyCodes::Touch_U, "Touch Up" }, + { SDLKeyCodes::Touch_D, "Touch Down" }, { SDLKeyCodes::LT, "LT" }, { SDLKeyCodes::RT, "RT" }, { SDLKeyCodes::LSXNeg, "LS X-" }, @@ -342,6 +346,27 @@ SDLDevice::sdl_info sdl_pad_handler::get_sdl_info(int i) info.has_accel = SDL_GameControllerHasSensor(info.game_controller, SDL_SENSOR_ACCEL); info.has_gyro = SDL_GameControllerHasSensor(info.game_controller, SDL_SENSOR_GYRO); + if (const int num_touchpads = SDL_GameControllerGetNumTouchpads(info.game_controller); num_touchpads > 0) + { + info.touchpads.resize(num_touchpads); + + for (int i = 0; i < num_touchpads; i++) + { + SDLDevice::touchpad& touchpad = ::at32(info.touchpads, i); + touchpad.index = i; + + if (const int num_fingers = SDL_GameControllerGetNumTouchpadFingers(info.game_controller, touchpad.index); num_fingers > 0) + { + touchpad.fingers.resize(num_fingers); + + for (int f = 0; f < num_fingers; f++) + { + ::at32(touchpad.fingers, f).index = f; + } + } + } + } + sdl_log.notice("Found game controller %d: type=%d, name='%s', path='%s', serial='%s', vid=0x%x, pid=0x%x, product_version=0x%x, firmware_version=0x%x, has_led=%d, has_rumble=%d, has_rumble_triggers=%d, has_accel=%d, has_gyro=%d", i, static_cast(info.type), info.name, info.path, info.serial, info.vid, info.pid, info.product_version, info.firmware_version, info.has_led, info.has_rumble, info.has_rumble_triggers, info.has_accel, info.has_gyro); @@ -913,6 +938,20 @@ bool sdl_pad_handler::get_is_right_stick(const std::shared_ptr& /*dev } } +bool sdl_pad_handler::get_is_touch_pad_motion(const std::shared_ptr& /*device*/, u64 keyCode) +{ + switch (keyCode) + { + case SDLKeyCodes::Touch_L: + case SDLKeyCodes::Touch_R: + case SDLKeyCodes::Touch_U: + case SDLKeyCodes::Touch_D: + return true; + default: + return false; + } +} + std::unordered_map sdl_pad_handler::get_button_values(const std::shared_ptr& device) { std::unordered_map values; @@ -962,6 +1001,40 @@ std::unordered_map sdl_pad_handler::get_button_values(const std::share } } + for (const SDLDevice::touchpad& touchpad : dev->sdl.touchpads) + { + for (const SDLDevice::touch_point& finger : touchpad.fingers) + { + u8 state = 0; // 1 means the finger is touching the pad + f32 x = 0.0f; // 0 = left, 1 = right + f32 y = 0.0f; // 0 = top, 1 = bottom + f32 pressure = 0.0f; // In the current SDL version the pressure is always 1 if the state is 1 + + if (SDL_GameControllerGetTouchpadFinger(dev->sdl.game_controller, touchpad.index, finger.index, &state, &x, &y, &pressure) != 0) + { + sdl_log.error("Could not get touchpad %d finger %d data of device %d! SDL Error: %s", touchpad.index, finger.index, dev->player_id, SDL_GetError()); + } + else + { + sdl_log.trace("touchpad=%d, finger=%d, state=%d, x=%f, y=%f, pressure=%f", touchpad.index, finger.index, state, x, y, pressure); + + if (state == 0) + { + continue; + } + + const f32 x_scaled = ScaledInput(x, 0.0f, 1.0f, 0.0f, 255.0f); + const f32 y_scaled = ScaledInput(y, 0.0f, 1.0f, 0.0f, 255.0f); + + values[SDLKeyCodes::Touch_L] = Clamp0To255((127.5f - x_scaled) * 2.0f); + values[SDLKeyCodes::Touch_R] = Clamp0To255((x_scaled - 127.5f) * 2.0f); + + values[SDLKeyCodes::Touch_U] = Clamp0To255((127.5f - y_scaled) * 2.0f); + values[SDLKeyCodes::Touch_D] = Clamp0To255((y_scaled - 127.5f) * 2.0f); + } + } + } + return values; } diff --git a/rpcs3/Input/sdl_pad_handler.h b/rpcs3/Input/sdl_pad_handler.h index a070423b96..e82d3b5c14 100644 --- a/rpcs3/Input/sdl_pad_handler.h +++ b/rpcs3/Input/sdl_pad_handler.h @@ -8,6 +8,20 @@ class SDLDevice : public PadDevice { public: + + struct touch_point + { + int index = 0; + int x = 0; + int y = 0; + }; + + struct touchpad + { + int index = 0; + std::vector fingers; + }; + struct sdl_info { SDL_GameController* game_controller = nullptr; @@ -37,6 +51,8 @@ public: std::set button_ids; std::set axis_ids; + + std::vector touchpads; }; sdl_info sdl{}; @@ -81,6 +97,11 @@ class sdl_pad_handler : public PadHandlerBase Paddle4, Touchpad, + Touch_L, + Touch_R, + Touch_U, + Touch_D, + LT, RT, @@ -124,6 +145,7 @@ private: bool get_is_right_trigger(const std::shared_ptr& device, u64 keyCode) override; bool get_is_left_stick(const std::shared_ptr& device, u64 keyCode) override; bool get_is_right_stick(const std::shared_ptr& device, u64 keyCode) override; + bool get_is_touch_pad_motion(const std::shared_ptr& device, u64 keyCode) override; std::unordered_map get_button_values(const std::shared_ptr& device) override; pad_preview_values get_preview_values(const std::unordered_map& data) override;