Просмотр исходного кода

service/hid: Update touch and gestures to use ring lifo and the emulated console

german77 4 лет назад
Родитель
Сommit
afe2d667d9

+ 100 - 174
src/core/hle/service/hid/controllers/gesture.cpp

@@ -5,8 +5,10 @@
 #include "common/logging/log.h"
 #include "common/logging/log.h"
 #include "common/math_util.h"
 #include "common/math_util.h"
 #include "common/settings.h"
 #include "common/settings.h"
+#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/core_timing.h"
 #include "core/frontend/emu_window.h"
 #include "core/frontend/emu_window.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/service/hid/controllers/gesture.h"
 #include "core/hle/service/hid/controllers/gesture.h"
 
 
 namespace Service::HID {
 namespace Service::HID {
@@ -23,16 +25,15 @@ constexpr f32 Square(s32 num) {
     return static_cast<f32>(num * num);
     return static_cast<f32>(num * num);
 }
 }
 
 
-Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) {}
+Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) {
+    console = system.HIDCore().GetEmulatedConsole();
+}
+
 Controller_Gesture::~Controller_Gesture() = default;
 Controller_Gesture::~Controller_Gesture() = default;
 
 
 void Controller_Gesture::OnInit() {
 void Controller_Gesture::OnInit() {
-    for (std::size_t id = 0; id < MAX_FINGERS; ++id) {
-        mouse_finger_id[id] = MAX_POINTS;
-        keyboard_finger_id[id] = MAX_POINTS;
-        udp_finger_id[id] = MAX_POINTS;
-    }
-    shared_memory.header.entry_count = 0;
+    gesture_lifo.entry_count = 0;
+    gesture_lifo.last_entry_index = 0;
     force_update = true;
     force_update = true;
 }
 }
 
 
@@ -40,50 +41,43 @@ void Controller_Gesture::OnRelease() {}
 
 
 void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
 void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                   std::size_t size) {
                                   std::size_t size) {
-    shared_memory.header.timestamp = core_timing.GetCPUTicks();
-    shared_memory.header.total_entry_count = 17;
-
+    // TODO FIND WTF IS WRONG HERE!!!!!!!!
+    return;
     if (!IsControllerActivated()) {
     if (!IsControllerActivated()) {
-        shared_memory.header.entry_count = 0;
-        shared_memory.header.last_entry_index = 0;
+        gesture_lifo.entry_count = 0;
+        gesture_lifo.last_entry_index = 0;
+        std::memcpy(data, &gesture_lifo, sizeof(gesture_lifo));
         return;
         return;
     }
     }
 
 
     ReadTouchInput();
     ReadTouchInput();
 
 
     GestureProperties gesture = GetGestureProperties();
     GestureProperties gesture = GetGestureProperties();
-    f32 time_difference = static_cast<f32>(shared_memory.header.timestamp - last_update_timestamp) /
-                          (1000 * 1000 * 1000);
+    f32 time_difference =
+        static_cast<f32>(gesture_lifo.timestamp - last_update_timestamp) / (1000 * 1000 * 1000);
 
 
     // Only update if necesary
     // Only update if necesary
     if (!ShouldUpdateGesture(gesture, time_difference)) {
     if (!ShouldUpdateGesture(gesture, time_difference)) {
         return;
         return;
     }
     }
 
 
-    last_update_timestamp = shared_memory.header.timestamp;
+    last_update_timestamp = gesture_lifo.timestamp;
     UpdateGestureSharedMemory(data, size, gesture, time_difference);
     UpdateGestureSharedMemory(data, size, gesture, time_difference);
 }
 }
 
 
 void Controller_Gesture::ReadTouchInput() {
 void Controller_Gesture::ReadTouchInput() {
-    const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus();
-    const Input::TouchStatus& udp_status = touch_udp_device->GetStatus();
-    for (std::size_t id = 0; id < mouse_status.size(); ++id) {
-        mouse_finger_id[id] = UpdateTouchInputEvent(mouse_status[id], mouse_finger_id[id]);
-        udp_finger_id[id] = UpdateTouchInputEvent(udp_status[id], udp_finger_id[id]);
-    }
-
-    if (Settings::values.use_touch_from_button) {
-        const Input::TouchStatus& keyboard_status = touch_btn_device->GetStatus();
-        for (std::size_t id = 0; id < mouse_status.size(); ++id) {
-            keyboard_finger_id[id] =
-                UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]);
-        }
+    const auto touch_status = console->GetTouch();
+    for (std::size_t id = 0; id < fingers.size(); ++id) {
+        const Core::HID::TouchFinger& status = touch_status[id];
+        Finger& finger = fingers[id];
+        finger.pos = status.position;
+        finger.pressed = status.pressed;
     }
     }
 }
 }
 
 
 bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
 bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
                                              f32 time_difference) {
                                              f32 time_difference) {
-    const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
+    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
     if (force_update) {
     if (force_update) {
         force_update = false;
         force_update = false;
         return true;
         return true;
@@ -97,7 +91,7 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
     }
     }
 
 
     // Update on press and hold event after 0.5 seconds
     // Update on press and hold event after 0.5 seconds
-    if (last_entry.type == TouchType::Touch && last_entry.point_count == 1 &&
+    if (last_entry.type == GestureType::Touch && last_entry.point_count == 1 &&
         time_difference > press_delay) {
         time_difference > press_delay) {
         return enable_press_and_tap;
         return enable_press_and_tap;
     }
     }
@@ -108,27 +102,19 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
 void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
 void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
                                                    GestureProperties& gesture,
                                                    GestureProperties& gesture,
                                                    f32 time_difference) {
                                                    f32 time_difference) {
-    TouchType type = TouchType::Idle;
-    Attribute attributes{};
-
-    const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
-    shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17;
-    auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
+    GestureType type = GestureType::Idle;
+    GestureAttribute attributes{};
 
 
-    if (shared_memory.header.entry_count < 16) {
-        shared_memory.header.entry_count++;
-    }
-
-    cur_entry.sampling_number = last_entry.sampling_number + 1;
-    cur_entry.sampling_number2 = cur_entry.sampling_number;
+    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
 
 
-    // Reset values to default
-    cur_entry.delta = {};
-    cur_entry.vel_x = 0;
-    cur_entry.vel_y = 0;
-    cur_entry.direction = Direction::None;
-    cur_entry.rotation_angle = 0;
-    cur_entry.scale = 0;
+    // Reset next state to default
+    next_state.sampling_number = last_entry.sampling_number + 1;
+    next_state.delta = {};
+    next_state.vel_x = 0;
+    next_state.vel_y = 0;
+    next_state.direction = GestureDirection::None;
+    next_state.rotation_angle = 0;
+    next_state.scale = 0;
 
 
     if (gesture.active_points > 0) {
     if (gesture.active_points > 0) {
         if (last_gesture.active_points == 0) {
         if (last_gesture.active_points == 0) {
@@ -141,46 +127,47 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
     }
     }
 
 
     // Apply attributes
     // Apply attributes
-    cur_entry.detection_count = gesture.detection_count;
-    cur_entry.type = type;
-    cur_entry.attributes = attributes;
-    cur_entry.pos = gesture.mid_point;
-    cur_entry.point_count = static_cast<s32>(gesture.active_points);
-    cur_entry.points = gesture.points;
+    next_state.detection_count = gesture.detection_count;
+    next_state.type = type;
+    next_state.attributes = attributes;
+    next_state.pos = gesture.mid_point;
+    next_state.point_count = static_cast<s32>(gesture.active_points);
+    next_state.points = gesture.points;
     last_gesture = gesture;
     last_gesture = gesture;
 
 
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
+    gesture_lifo.WriteNextEntry(next_state);
+    std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo));
 }
 }
 
 
-void Controller_Gesture::NewGesture(GestureProperties& gesture, TouchType& type,
-                                    Attribute& attributes) {
-    const auto& last_entry = GetLastGestureEntry();
+void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
+                                    GestureAttribute& attributes) {
+    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
 
 
     gesture.detection_count++;
     gesture.detection_count++;
-    type = TouchType::Touch;
+    type = GestureType::Touch;
 
 
     // New touch after cancel is not considered new
     // New touch after cancel is not considered new
-    if (last_entry.type != TouchType::Cancel) {
+    if (last_entry.type != GestureType::Cancel) {
         attributes.is_new_touch.Assign(1);
         attributes.is_new_touch.Assign(1);
         enable_press_and_tap = true;
         enable_press_and_tap = true;
     }
     }
 }
 }
 
 
-void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, TouchType& type,
+void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type,
                                                f32 time_difference) {
                                                f32 time_difference) {
-    const auto& last_entry = GetLastGestureEntry();
+    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
 
 
     // Promote to pan type if touch moved
     // Promote to pan type if touch moved
     for (size_t id = 0; id < MAX_POINTS; id++) {
     for (size_t id = 0; id < MAX_POINTS; id++) {
         if (gesture.points[id] != last_gesture.points[id]) {
         if (gesture.points[id] != last_gesture.points[id]) {
-            type = TouchType::Pan;
+            type = GestureType::Pan;
             break;
             break;
         }
         }
     }
     }
 
 
     // Number of fingers changed cancel the last event and clear data
     // Number of fingers changed cancel the last event and clear data
     if (gesture.active_points != last_gesture.active_points) {
     if (gesture.active_points != last_gesture.active_points) {
-        type = TouchType::Cancel;
+        type = GestureType::Cancel;
         enable_press_and_tap = false;
         enable_press_and_tap = false;
         gesture.active_points = 0;
         gesture.active_points = 0;
         gesture.mid_point = {};
         gesture.mid_point = {};
@@ -189,41 +176,41 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Touch
     }
     }
 
 
     // Calculate extra parameters of panning
     // Calculate extra parameters of panning
-    if (type == TouchType::Pan) {
+    if (type == GestureType::Pan) {
         UpdatePanEvent(gesture, last_gesture, type, time_difference);
         UpdatePanEvent(gesture, last_gesture, type, time_difference);
         return;
         return;
     }
     }
 
 
     // Promote to press type
     // Promote to press type
-    if (last_entry.type == TouchType::Touch) {
-        type = TouchType::Press;
+    if (last_entry.type == GestureType::Touch) {
+        type = GestureType::Press;
     }
     }
 }
 }
 
 
 void Controller_Gesture::EndGesture(GestureProperties& gesture,
 void Controller_Gesture::EndGesture(GestureProperties& gesture,
-                                    GestureProperties& last_gesture_props, TouchType& type,
-                                    Attribute& attributes, f32 time_difference) {
-    const auto& last_entry = GetLastGestureEntry();
+                                    GestureProperties& last_gesture_props, GestureType& type,
+                                    GestureAttribute& attributes, f32 time_difference) {
+    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
 
 
     if (last_gesture_props.active_points != 0) {
     if (last_gesture_props.active_points != 0) {
         switch (last_entry.type) {
         switch (last_entry.type) {
-        case TouchType::Touch:
+        case GestureType::Touch:
             if (enable_press_and_tap) {
             if (enable_press_and_tap) {
                 SetTapEvent(gesture, last_gesture_props, type, attributes);
                 SetTapEvent(gesture, last_gesture_props, type, attributes);
                 return;
                 return;
             }
             }
-            type = TouchType::Cancel;
+            type = GestureType::Cancel;
             force_update = true;
             force_update = true;
             break;
             break;
-        case TouchType::Press:
-        case TouchType::Tap:
-        case TouchType::Swipe:
-        case TouchType::Pinch:
-        case TouchType::Rotate:
-            type = TouchType::Complete;
+        case GestureType::Press:
+        case GestureType::Tap:
+        case GestureType::Swipe:
+        case GestureType::Pinch:
+        case GestureType::Rotate:
+            type = GestureType::Complete;
             force_update = true;
             force_update = true;
             break;
             break;
-        case TouchType::Pan:
+        case GestureType::Pan:
             EndPanEvent(gesture, last_gesture_props, type, time_difference);
             EndPanEvent(gesture, last_gesture_props, type, time_difference);
             break;
             break;
         default:
         default:
@@ -231,15 +218,15 @@ void Controller_Gesture::EndGesture(GestureProperties& gesture,
         }
         }
         return;
         return;
     }
     }
-    if (last_entry.type == TouchType::Complete || last_entry.type == TouchType::Cancel) {
+    if (last_entry.type == GestureType::Complete || last_entry.type == GestureType::Cancel) {
         gesture.detection_count++;
         gesture.detection_count++;
     }
     }
 }
 }
 
 
 void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
 void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
-                                     GestureProperties& last_gesture_props, TouchType& type,
-                                     Attribute& attributes) {
-    type = TouchType::Tap;
+                                     GestureProperties& last_gesture_props, GestureType& type,
+                                     GestureAttribute& attributes) {
+    type = GestureType::Tap;
     gesture = last_gesture_props;
     gesture = last_gesture_props;
     force_update = true;
     force_update = true;
     f32 tap_time_difference =
     f32 tap_time_difference =
@@ -251,44 +238,42 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
 }
 }
 
 
 void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
 void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
-                                        GestureProperties& last_gesture_props, TouchType& type,
+                                        GestureProperties& last_gesture_props, GestureType& type,
                                         f32 time_difference) {
                                         f32 time_difference) {
-    auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
-    const auto& last_entry = GetLastGestureEntry();
+    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
 
 
-    cur_entry.delta = gesture.mid_point - last_entry.pos;
-    cur_entry.vel_x = static_cast<f32>(cur_entry.delta.x) / time_difference;
-    cur_entry.vel_y = static_cast<f32>(cur_entry.delta.y) / time_difference;
+    next_state.delta = gesture.mid_point - last_entry.pos;
+    next_state.vel_x = static_cast<f32>(next_state.delta.x) / time_difference;
+    next_state.vel_y = static_cast<f32>(next_state.delta.y) / time_difference;
     last_pan_time_difference = time_difference;
     last_pan_time_difference = time_difference;
 
 
     // Promote to pinch type
     // Promote to pinch type
     if (std::abs(gesture.average_distance - last_gesture_props.average_distance) >
     if (std::abs(gesture.average_distance - last_gesture_props.average_distance) >
         pinch_threshold) {
         pinch_threshold) {
-        type = TouchType::Pinch;
-        cur_entry.scale = gesture.average_distance / last_gesture_props.average_distance;
+        type = GestureType::Pinch;
+        next_state.scale = gesture.average_distance / last_gesture_props.average_distance;
     }
     }
 
 
     const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) /
     const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) /
                                                   (1 + (gesture.angle * last_gesture_props.angle)));
                                                   (1 + (gesture.angle * last_gesture_props.angle)));
     // Promote to rotate type
     // Promote to rotate type
     if (std::abs(angle_between_two_lines) > angle_threshold) {
     if (std::abs(angle_between_two_lines) > angle_threshold) {
-        type = TouchType::Rotate;
-        cur_entry.scale = 0;
-        cur_entry.rotation_angle = angle_between_two_lines * 180.0f / Common::PI;
+        type = GestureType::Rotate;
+        next_state.scale = 0;
+        next_state.rotation_angle = angle_between_two_lines * 180.0f / Common::PI;
     }
     }
 }
 }
 
 
 void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
 void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
-                                     GestureProperties& last_gesture_props, TouchType& type,
+                                     GestureProperties& last_gesture_props, GestureType& type,
                                      f32 time_difference) {
                                      f32 time_difference) {
-    auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
-    const auto& last_entry = GetLastGestureEntry();
-    cur_entry.vel_x =
+    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
+    next_state.vel_x =
         static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference);
         static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference);
-    cur_entry.vel_y =
+    next_state.vel_y =
         static_cast<f32>(last_entry.delta.y) / (last_pan_time_difference + time_difference);
         static_cast<f32>(last_entry.delta.y) / (last_pan_time_difference + time_difference);
     const f32 curr_vel =
     const f32 curr_vel =
-        std::sqrt((cur_entry.vel_x * cur_entry.vel_x) + (cur_entry.vel_y * cur_entry.vel_y));
+        std::sqrt((next_state.vel_x * next_state.vel_x) + (next_state.vel_y * next_state.vel_y));
 
 
     // Set swipe event with parameters
     // Set swipe event with parameters
     if (curr_vel > swipe_threshold) {
     if (curr_vel > swipe_threshold) {
@@ -297,93 +282,34 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
     }
     }
 
 
     // End panning without swipe
     // End panning without swipe
-    type = TouchType::Complete;
-    cur_entry.vel_x = 0;
-    cur_entry.vel_y = 0;
+    type = GestureType::Complete;
+    next_state.vel_x = 0;
+    next_state.vel_y = 0;
     force_update = true;
     force_update = true;
 }
 }
 
 
 void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
 void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
-                                       GestureProperties& last_gesture_props, TouchType& type) {
-    auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
-    const auto& last_entry = GetLastGestureEntry();
+                                       GestureProperties& last_gesture_props, GestureType& type) {
+    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
 
 
-    type = TouchType::Swipe;
+    type = GestureType::Swipe;
     gesture = last_gesture_props;
     gesture = last_gesture_props;
     force_update = true;
     force_update = true;
-    cur_entry.delta = last_entry.delta;
+    next_state.delta = last_entry.delta;
 
 
-    if (std::abs(cur_entry.delta.x) > std::abs(cur_entry.delta.y)) {
-        if (cur_entry.delta.x > 0) {
-            cur_entry.direction = Direction::Right;
+    if (std::abs(next_state.delta.x) > std::abs(next_state.delta.y)) {
+        if (next_state.delta.x > 0) {
+            next_state.direction = GestureDirection::Right;
             return;
             return;
         }
         }
-        cur_entry.direction = Direction::Left;
+        next_state.direction = GestureDirection::Left;
         return;
         return;
     }
     }
-    if (cur_entry.delta.y > 0) {
-        cur_entry.direction = Direction::Down;
+    if (next_state.delta.y > 0) {
+        next_state.direction = GestureDirection::Down;
         return;
         return;
     }
     }
-    cur_entry.direction = Direction::Up;
-}
-
-void Controller_Gesture::OnLoadInputDevices() {
-    touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window");
-    touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp");
-    touch_btn_device = Input::CreateDevice<Input::TouchDevice>("engine:touch_from_button");
-}
-
-std::optional<std::size_t> Controller_Gesture::GetUnusedFingerID() const {
-    // Dont assign any touch input to a point if disabled
-    if (!Settings::values.touchscreen.enabled) {
-        return std::nullopt;
-    }
-    std::size_t first_free_id = 0;
-    while (first_free_id < MAX_POINTS) {
-        if (!fingers[first_free_id].pressed) {
-            return first_free_id;
-        } else {
-            first_free_id++;
-        }
-    }
-    return std::nullopt;
-}
-
-Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() {
-    return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17];
-}
-
-const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const {
-    return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17];
-}
-
-std::size_t Controller_Gesture::UpdateTouchInputEvent(
-    const std::tuple<float, float, bool>& touch_input, std::size_t finger_id) {
-    const auto& [x, y, pressed] = touch_input;
-    if (finger_id > MAX_POINTS) {
-        LOG_ERROR(Service_HID, "Invalid finger id {}", finger_id);
-        return MAX_POINTS;
-    }
-    if (pressed) {
-        if (finger_id == MAX_POINTS) {
-            const auto first_free_id = GetUnusedFingerID();
-            if (!first_free_id) {
-                // Invalid finger id do nothing
-                return MAX_POINTS;
-            }
-            finger_id = first_free_id.value();
-            fingers[finger_id].pressed = true;
-        }
-        fingers[finger_id].pos = {x, y};
-        return finger_id;
-    }
-
-    if (finger_id != MAX_POINTS) {
-        fingers[finger_id].pressed = false;
-    }
-
-    return MAX_POINTS;
+    next_state.direction = GestureDirection::Up;
 }
 }
 
 
 Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() {
 Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() {

+ 31 - 49
src/core/hle/service/hid/controllers/gesture.h

@@ -8,8 +8,12 @@
 #include "common/bit_field.h"
 #include "common/bit_field.h"
 #include "common/common_types.h"
 #include "common/common_types.h"
 #include "common/point.h"
 #include "common/point.h"
-#include "core/frontend/input.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/hid/ring_lifo.h"
+
+namespace Core::HID {
+class EmulatedController;
+} // namespace Core::HID
 
 
 namespace Service::HID {
 namespace Service::HID {
 class Controller_Gesture final : public ControllerBase {
 class Controller_Gesture final : public ControllerBase {
@@ -26,14 +30,12 @@ public:
     // When the controller is requesting an update for the shared memory
     // When the controller is requesting an update for the shared memory
     void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override;
     void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override;
 
 
-    // Called when input devices should be loaded
-    void OnLoadInputDevices() override;
-
 private:
 private:
     static constexpr size_t MAX_FINGERS = 16;
     static constexpr size_t MAX_FINGERS = 16;
     static constexpr size_t MAX_POINTS = 4;
     static constexpr size_t MAX_POINTS = 4;
 
 
-    enum class TouchType : u32 {
+    // This is nn::hid::GestureType
+    enum class GestureType : u32 {
         Idle,     // Nothing touching the screen
         Idle,     // Nothing touching the screen
         Complete, // Set at the end of a touch event
         Complete, // Set at the end of a touch event
         Cancel,   // Set when the number of fingers change
         Cancel,   // Set when the number of fingers change
@@ -46,7 +48,8 @@ private:
         Rotate,   // All points rotating from the midpoint
         Rotate,   // All points rotating from the midpoint
     };
     };
 
 
-    enum class Direction : u32 {
+    // This is nn::hid::GestureDirection
+    enum class GestureDirection : u32 {
         None,
         None,
         Left,
         Left,
         Up,
         Up,
@@ -54,7 +57,8 @@ private:
         Down,
         Down,
     };
     };
 
 
-    struct Attribute {
+    // This is nn::hid::GestureAttribute
+    struct GestureAttribute {
         union {
         union {
             u32_le raw{};
             u32_le raw{};
 
 
@@ -62,31 +66,25 @@ private:
             BitField<8, 1, u32> is_double_tap;
             BitField<8, 1, u32> is_double_tap;
         };
         };
     };
     };
-    static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size");
+    static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
 
 
+    // This is nn::hid::GestureState
     struct GestureState {
     struct GestureState {
         s64_le sampling_number;
         s64_le sampling_number;
-        s64_le sampling_number2;
         s64_le detection_count;
         s64_le detection_count;
-        TouchType type;
-        Direction direction;
+        GestureType type;
+        GestureDirection direction;
         Common::Point<s32_le> pos;
         Common::Point<s32_le> pos;
         Common::Point<s32_le> delta;
         Common::Point<s32_le> delta;
         f32 vel_x;
         f32 vel_x;
         f32 vel_y;
         f32 vel_y;
-        Attribute attributes;
+        GestureAttribute attributes;
         f32 scale;
         f32 scale;
         f32 rotation_angle;
         f32 rotation_angle;
         s32_le point_count;
         s32_le point_count;
         std::array<Common::Point<s32_le>, 4> points;
         std::array<Common::Point<s32_le>, 4> points;
     };
     };
-    static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size");
-
-    struct SharedMemory {
-        CommonHeader header;
-        std::array<GestureState, 17> gesture_states;
-    };
-    static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size");
+    static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
 
 
     struct Finger {
     struct Finger {
         Common::Point<f32> pos{};
         Common::Point<f32> pos{};
@@ -114,58 +112,42 @@ private:
                                    f32 time_difference);
                                    f32 time_difference);
 
 
     // Initializes new gesture
     // Initializes new gesture
-    void NewGesture(GestureProperties& gesture, TouchType& type, Attribute& attributes);
+    void NewGesture(GestureProperties& gesture, GestureType& type, GestureAttribute& attributes);
 
 
     // Updates existing gesture state
     // Updates existing gesture state
-    void UpdateExistingGesture(GestureProperties& gesture, TouchType& type, f32 time_difference);
+    void UpdateExistingGesture(GestureProperties& gesture, GestureType& type, f32 time_difference);
 
 
     // Terminates exiting gesture
     // Terminates exiting gesture
     void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props,
     void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props,
-                    TouchType& type, Attribute& attributes, f32 time_difference);
+                    GestureType& type, GestureAttribute& attributes, f32 time_difference);
 
 
     // Set current event to a tap event
     // Set current event to a tap event
     void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
     void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
-                     TouchType& type, Attribute& attributes);
+                     GestureType& type, GestureAttribute& attributes);
 
 
     // Calculates and set the extra parameters related to a pan event
     // Calculates and set the extra parameters related to a pan event
     void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
     void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
-                        TouchType& type, f32 time_difference);
+                        GestureType& type, f32 time_difference);
 
 
     // Terminates the pan event
     // Terminates the pan event
     void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
     void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
-                     TouchType& type, f32 time_difference);
+                     GestureType& type, f32 time_difference);
 
 
     // Set current event to a swipe event
     // Set current event to a swipe event
     void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
     void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
-                       TouchType& type);
-
-    // Returns an unused finger id, if there is no fingers available std::nullopt is returned.
-    [[nodiscard]] std::optional<size_t> GetUnusedFingerID() const;
-
-    // Retrieves the last gesture entry, as indicated by shared memory indices.
-    [[nodiscard]] GestureState& GetLastGestureEntry();
-    [[nodiscard]] const GestureState& GetLastGestureEntry() const;
-
-    /**
-     * If the touch is new it tries to assign a new finger id, if there is no fingers available no
-     * changes will be made. Updates the coordinates if the finger id it's already set. If the touch
-     * ends delays the output by one frame to set the end_touch flag before finally freeing the
-     * finger id
-     */
-    size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input,
-                                 size_t finger_id);
+                       GestureType& type);
 
 
     // Returns the average distance, angle and middle point of the active fingers
     // Returns the average distance, angle and middle point of the active fingers
     GestureProperties GetGestureProperties();
     GestureProperties GetGestureProperties();
 
 
-    SharedMemory shared_memory{};
-    std::unique_ptr<Input::TouchDevice> touch_mouse_device;
-    std::unique_ptr<Input::TouchDevice> touch_udp_device;
-    std::unique_ptr<Input::TouchDevice> touch_btn_device;
-    std::array<size_t, MAX_FINGERS> mouse_finger_id{};
-    std::array<size_t, MAX_FINGERS> keyboard_finger_id{};
-    std::array<size_t, MAX_FINGERS> udp_finger_id{};
+    // This is nn::hid::detail::GestureLifo
+    Lifo<GestureState> gesture_lifo{};
+    static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
+    GestureState next_state{};
+
     std::array<Finger, MAX_POINTS> fingers{};
     std::array<Finger, MAX_POINTS> fingers{};
+    Core::HID::EmulatedConsole* console;
+
     GestureProperties last_gesture{};
     GestureProperties last_gesture{};
     s64_le last_update_timestamp{};
     s64_le last_update_timestamp{};
     s64_le last_tap_timestamp{};
     s64_le last_tap_timestamp{};

+ 43 - 93
src/core/hle/service/hid/controllers/touchscreen.cpp

@@ -7,72 +7,79 @@
 #include "common/common_types.h"
 #include "common/common_types.h"
 #include "common/logging/log.h"
 #include "common/logging/log.h"
 #include "common/settings.h"
 #include "common/settings.h"
+#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/core_timing.h"
 #include "core/frontend/emu_window.h"
 #include "core/frontend/emu_window.h"
-#include "core/frontend/input.h"
 #include "core/hle/service/hid/controllers/touchscreen.h"
 #include "core/hle/service/hid/controllers/touchscreen.h"
 
 
 namespace Service::HID {
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
 
 
-Controller_Touchscreen::Controller_Touchscreen(Core::System& system_) : ControllerBase{system_} {}
+Controller_Touchscreen::Controller_Touchscreen(Core::System& system_) : ControllerBase{system_} {
+    console = system.HIDCore().GetEmulatedConsole();
+}
+
 Controller_Touchscreen::~Controller_Touchscreen() = default;
 Controller_Touchscreen::~Controller_Touchscreen() = default;
 
 
-void Controller_Touchscreen::OnInit() {
-    for (std::size_t id = 0; id < MAX_FINGERS; ++id) {
-        mouse_finger_id[id] = MAX_FINGERS;
-        keyboard_finger_id[id] = MAX_FINGERS;
-        udp_finger_id[id] = MAX_FINGERS;
-    }
-}
+void Controller_Touchscreen::OnInit() {}
 
 
 void Controller_Touchscreen::OnRelease() {}
 void Controller_Touchscreen::OnRelease() {}
 
 
 void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
 void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                       std::size_t size) {
                                       std::size_t size) {
-    shared_memory.header.timestamp = core_timing.GetCPUTicks();
-    shared_memory.header.total_entry_count = 17;
+    touch_screen_lifo.timestamp = core_timing.GetCPUTicks();
 
 
     if (!IsControllerActivated()) {
     if (!IsControllerActivated()) {
-        shared_memory.header.entry_count = 0;
-        shared_memory.header.last_entry_index = 0;
+        touch_screen_lifo.entry_count = 0;
+        touch_screen_lifo.last_entry_index = 0;
+        std::memcpy(data, &touch_screen_lifo, sizeof(touch_screen_lifo));
         return;
         return;
     }
     }
-    shared_memory.header.entry_count = 16;
 
 
-    const auto& last_entry =
-        shared_memory.shared_memory_entries[shared_memory.header.last_entry_index];
-    shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17;
-    auto& cur_entry = shared_memory.shared_memory_entries[shared_memory.header.last_entry_index];
+    const auto touch_status = console->GetTouch();
+    for (std::size_t id = 0; id < MAX_FINGERS; id++) {
+        const auto& current_touch = touch_status[id];
+        auto& finger = fingers[id];
+        finger.position = current_touch.position;
+        finger.id = current_touch.id;
 
 
-    cur_entry.sampling_number = last_entry.sampling_number + 1;
-    cur_entry.sampling_number2 = cur_entry.sampling_number;
+        if (finger.attribute.start_touch) {
+            finger.attribute.raw = 0;
+            continue;
+        }
 
 
-    const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus();
-    const Input::TouchStatus& udp_status = touch_udp_device->GetStatus();
-    for (std::size_t id = 0; id < mouse_status.size(); ++id) {
-        mouse_finger_id[id] = UpdateTouchInputEvent(mouse_status[id], mouse_finger_id[id]);
-        udp_finger_id[id] = UpdateTouchInputEvent(udp_status[id], udp_finger_id[id]);
-    }
+        if (finger.attribute.end_touch) {
+            finger.attribute.raw = 0;
+            finger.pressed = false;
+            continue;
+        }
+
+        if (!finger.pressed && current_touch.pressed) {
+            finger.attribute.start_touch.Assign(1);
+            finger.pressed = true;
+            continue;
+        }
 
 
-    if (Settings::values.use_touch_from_button) {
-        const Input::TouchStatus& keyboard_status = touch_btn_device->GetStatus();
-        for (std::size_t id = 0; id < mouse_status.size(); ++id) {
-            keyboard_finger_id[id] =
-                UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]);
+        if (finger.pressed && !current_touch.pressed) {
+            finger.attribute.raw = 0;
+            finger.attribute.end_touch.Assign(1);
         }
         }
     }
     }
 
 
-    std::array<Finger, 16> active_fingers;
+    std::array<Finger, MAX_FINGERS> active_fingers;
     const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
     const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
                                        [](const auto& finger) { return finger.pressed; });
                                        [](const auto& finger) { return finger.pressed; });
     const auto active_fingers_count =
     const auto active_fingers_count =
         static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
         static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
 
 
     const u64 tick = core_timing.GetCPUTicks();
     const u64 tick = core_timing.GetCPUTicks();
-    cur_entry.entry_count = static_cast<s32_le>(active_fingers_count);
+    const auto& last_entry = touch_screen_lifo.ReadCurrentEntry().state;
+
+    next_state.sampling_number = last_entry.sampling_number + 1;
+    next_state.entry_count = static_cast<s32_le>(active_fingers_count);
+
     for (std::size_t id = 0; id < MAX_FINGERS; ++id) {
     for (std::size_t id = 0; id < MAX_FINGERS; ++id) {
-        auto& touch_entry = cur_entry.states[id];
+        auto& touch_entry = next_state.states[id];
         if (id < active_fingers_count) {
         if (id < active_fingers_count) {
             const auto& [active_x, active_y] = active_fingers[id].position;
             const auto& [active_x, active_y] = active_fingers[id].position;
             touch_entry.position = {
             touch_entry.position = {
@@ -97,66 +104,9 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
             touch_entry.finger = 0;
             touch_entry.finger = 0;
         }
         }
     }
     }
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(TouchScreenSharedMemory));
-}
-
-void Controller_Touchscreen::OnLoadInputDevices() {
-    touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window");
-    touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp");
-    touch_btn_device = Input::CreateDevice<Input::TouchDevice>("engine:touch_from_button");
-}
-
-std::optional<std::size_t> Controller_Touchscreen::GetUnusedFingerID() const {
-    // Dont assign any touch input to a finger if disabled
-    if (!Settings::values.touchscreen.enabled) {
-        return std::nullopt;
-    }
-    std::size_t first_free_id = 0;
-    while (first_free_id < MAX_FINGERS) {
-        if (!fingers[first_free_id].pressed) {
-            return first_free_id;
-        } else {
-            first_free_id++;
-        }
-    }
-    return std::nullopt;
-}
-
-std::size_t Controller_Touchscreen::UpdateTouchInputEvent(
-    const std::tuple<float, float, bool>& touch_input, std::size_t finger_id) {
-    const auto& [x, y, pressed] = touch_input;
-    if (finger_id > MAX_FINGERS) {
-        LOG_ERROR(Service_HID, "Invalid finger id {}", finger_id);
-        return MAX_FINGERS;
-    }
-    if (pressed) {
-        Attributes attribute{};
-        if (finger_id == MAX_FINGERS) {
-            const auto first_free_id = GetUnusedFingerID();
-            if (!first_free_id) {
-                // Invalid finger id do nothing
-                return MAX_FINGERS;
-            }
-            finger_id = first_free_id.value();
-            fingers[finger_id].pressed = true;
-            fingers[finger_id].id = static_cast<u32_le>(finger_id);
-            attribute.start_touch.Assign(1);
-        }
-        fingers[finger_id].position = {x, y};
-        fingers[finger_id].attribute = attribute;
-        return finger_id;
-    }
-
-    if (finger_id != MAX_FINGERS) {
-        if (!fingers[finger_id].attribute.end_touch) {
-            fingers[finger_id].attribute.end_touch.Assign(1);
-            fingers[finger_id].attribute.start_touch.Assign(0);
-            return finger_id;
-        }
-        fingers[finger_id].pressed = false;
-    }
 
 
-    return MAX_FINGERS;
+    touch_screen_lifo.WriteNextEntry(next_state);
+    std::memcpy(data + SHARED_MEMORY_OFFSET, &touch_screen_lifo, sizeof(touch_screen_lifo));
 }
 }
 
 
 } // namespace Service::HID
 } // namespace Service::HID

+ 17 - 54
src/core/hle/service/hid/controllers/touchscreen.h

@@ -9,18 +9,22 @@
 #include "common/common_types.h"
 #include "common/common_types.h"
 #include "common/point.h"
 #include "common/point.h"
 #include "common/swap.h"
 #include "common/swap.h"
-#include "core/frontend/input.h"
+#include "core/hid/hid_core.h"
+#include "core/hid/hid_types.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/hid/ring_lifo.h"
 
 
 namespace Service::HID {
 namespace Service::HID {
 class Controller_Touchscreen final : public ControllerBase {
 class Controller_Touchscreen final : public ControllerBase {
 public:
 public:
+    // This is nn::hid::TouchScreenModeForNx
     enum class TouchScreenModeForNx : u8 {
     enum class TouchScreenModeForNx : u8 {
         UseSystemSetting,
         UseSystemSetting,
         Finger,
         Finger,
         Heat2,
         Heat2,
     };
     };
 
 
+    // This is nn::hid::TouchScreenConfigurationForNx
     struct TouchScreenConfigurationForNx {
     struct TouchScreenConfigurationForNx {
         TouchScreenModeForNx mode;
         TouchScreenModeForNx mode;
         INSERT_PADDING_BYTES_NOINIT(0x7);
         INSERT_PADDING_BYTES_NOINIT(0x7);
@@ -41,73 +45,32 @@ public:
     // When the controller is requesting an update for the shared memory
     // When the controller is requesting an update for the shared memory
     void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
     void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
 
 
-    // Called when input devices should be loaded
-    void OnLoadInputDevices() override;
-
 private:
 private:
     static constexpr std::size_t MAX_FINGERS = 16;
     static constexpr std::size_t MAX_FINGERS = 16;
 
 
-    // Returns an unused finger id, if there is no fingers available std::nullopt will be returned
-    std::optional<std::size_t> GetUnusedFingerID() const;
-
-    // If the touch is new it tries to assing a new finger id, if there is no fingers avaliable no
-    // changes will be made. Updates the coordinates if the finger id it's already set. If the touch
-    // ends delays the output by one frame to set the end_touch flag before finally freeing the
-    // finger id
-    std::size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input,
-                                      std::size_t finger_id);
-
-    struct Attributes {
-        union {
-            u32 raw{};
-            BitField<0, 1, u32> start_touch;
-            BitField<1, 1, u32> end_touch;
-        };
-    };
-    static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size");
-
-    struct TouchState {
-        u64_le delta_time;
-        Attributes attribute;
-        u32_le finger;
-        Common::Point<u32_le> position;
-        u32_le diameter_x;
-        u32_le diameter_y;
-        u32_le rotation_angle;
-    };
-    static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
-
-    struct TouchScreenEntry {
+    // This is nn::hid::TouchScreenState
+    struct TouchScreenState {
         s64_le sampling_number;
         s64_le sampling_number;
-        s64_le sampling_number2;
         s32_le entry_count;
         s32_le entry_count;
-        std::array<TouchState, MAX_FINGERS> states;
+        INSERT_PADDING_BYTES(4); // Reserved
+        std::array<Core::HID::TouchState, MAX_FINGERS> states;
     };
     };
-    static_assert(sizeof(TouchScreenEntry) == 0x298, "TouchScreenEntry is an invalid size");
-
-    struct TouchScreenSharedMemory {
-        CommonHeader header;
-        std::array<TouchScreenEntry, 17> shared_memory_entries{};
-        INSERT_PADDING_BYTES(0x3c8);
-    };
-    static_assert(sizeof(TouchScreenSharedMemory) == 0x3000,
-                  "TouchScreenSharedMemory is an invalid size");
+    static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
 
 
     struct Finger {
     struct Finger {
         u64_le last_touch{};
         u64_le last_touch{};
         Common::Point<float> position;
         Common::Point<float> position;
         u32_le id{};
         u32_le id{};
         bool pressed{};
         bool pressed{};
-        Attributes attribute;
+        Core::HID::TouchAttribute attribute;
     };
     };
 
 
-    TouchScreenSharedMemory shared_memory{};
-    std::unique_ptr<Input::TouchDevice> touch_mouse_device;
-    std::unique_ptr<Input::TouchDevice> touch_udp_device;
-    std::unique_ptr<Input::TouchDevice> touch_btn_device;
-    std::array<std::size_t, MAX_FINGERS> mouse_finger_id;
-    std::array<std::size_t, MAX_FINGERS> keyboard_finger_id;
-    std::array<std::size_t, MAX_FINGERS> udp_finger_id;
+    // This is nn::hid::detail::TouchScreenLifo
+    Lifo<TouchScreenState> touch_screen_lifo{};
+    static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
+    TouchScreenState next_state{};
+
     std::array<Finger, MAX_FINGERS> fingers;
     std::array<Finger, MAX_FINGERS> fingers;
+    Core::HID::EmulatedConsole* console;
 };
 };
 } // namespace Service::HID
 } // namespace Service::HID