From ad5142ac2c56aded4090ad031a9351cd188caacf Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 14:56:55 -0500
Subject: [PATCH 01/88] common: Rewrite and move core/frontend/input.h to
 common

---
 src/common/CMakeLists.txt |   1 +
 src/common/input.h        | 242 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 243 insertions(+)
 create mode 100644 src/common/input.h

diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 23d43a394e..919da4a53e 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -73,6 +73,7 @@ add_library(common STATIC
     hex_util.h
     host_memory.cpp
     host_memory.h
+    input.h
     intrusive_red_black_tree.h
     literals.h
     logging/backend.cpp
diff --git a/src/common/input.h b/src/common/input.h
new file mode 100644
index 0000000000..6eefc55f9c
--- /dev/null
+++ b/src/common/input.h
@@ -0,0 +1,242 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include "common/logging/log.h"
+#include "common/param_package.h"
+
+namespace Input {
+
+enum class InputType {
+    None,
+    Battery,
+    Button,
+    Stick,
+    Analog,
+    Trigger,
+    Motion,
+    Touch,
+    Color,
+    Vibration,
+    Nfc,
+    Ir,
+};
+
+enum class BatteryLevel {
+    Empty,
+    Critical,
+    Low,
+    Medium,
+    Full,
+    Charging,
+};
+
+struct AnalogProperties {
+    float deadzone{};
+    float range{1.0f};
+    float threshold{0.5f};
+    float offset{};
+    bool inverted{};
+};
+
+struct AnalogStatus {
+    float value{};
+    float raw_value{};
+    AnalogProperties properties{};
+};
+
+struct ButtonStatus {
+    bool value{};
+    bool inverted{};
+    bool toggle{};
+    bool locked{};
+};
+
+using BatteryStatus = BatteryLevel;
+
+struct StickStatus {
+    AnalogStatus x{};
+    AnalogStatus y{};
+    bool left{};
+    bool right{};
+    bool up{};
+    bool down{};
+};
+
+struct TriggerStatus {
+    AnalogStatus analog{};
+    bool pressed{};
+};
+
+struct MotionSensor {
+    AnalogStatus x{};
+    AnalogStatus y{};
+    AnalogStatus z{};
+};
+
+struct MotionStatus {
+    MotionSensor gyro{};
+    MotionSensor accel{};
+    u64 delta_timestamp{};
+};
+
+struct TouchStatus {
+    ButtonStatus pressed{};
+    AnalogStatus x{};
+    AnalogStatus y{};
+    u32 id{};
+};
+
+struct BodyColorStatus {
+    u32 body{};
+    u32 buttons{};
+};
+
+struct VibrationStatus {
+    f32 low_amplitude{};
+    f32 low_frequency{};
+    f32 high_amplitude{};
+    f32 high_frequency{};
+};
+
+struct LedStatus {
+    bool led_1{};
+    bool led_2{};
+    bool led_3{};
+    bool led_4{};
+};
+
+struct CallbackStatus {
+    InputType type{InputType::None};
+    ButtonStatus button_status{};
+    StickStatus stick_status{};
+    AnalogStatus analog_status{};
+    TriggerStatus trigger_status{};
+    MotionStatus motion_status{};
+    TouchStatus touch_status{};
+    BodyColorStatus color_status{};
+    BatteryStatus battery_status{};
+    VibrationStatus vibration_status{};
+};
+
+struct InputCallback {
+    std::function<void(CallbackStatus)> on_change;
+};
+
+/// An abstract class template for an input device (a button, an analog input, etc.).
+class InputDevice {
+public:
+    virtual ~InputDevice() = default;
+
+    void SetCallback(InputCallback callback_) {
+        callback = std::move(callback_);
+    }
+
+    void TriggerOnChange(CallbackStatus status) {
+        if (callback.on_change) {
+            callback.on_change(status);
+        }
+    }
+
+private:
+    InputCallback callback;
+};
+
+/// An abstract class template for a factory that can create input devices.
+template <typename InputDeviceType>
+class Factory {
+public:
+    virtual ~Factory() = default;
+    virtual std::unique_ptr<InputDeviceType> Create(const Common::ParamPackage&) = 0;
+};
+
+namespace Impl {
+
+template <typename InputDeviceType>
+using FactoryListType = std::unordered_map<std::string, std::shared_ptr<Factory<InputDeviceType>>>;
+
+template <typename InputDeviceType>
+struct FactoryList {
+    static FactoryListType<InputDeviceType> list;
+};
+
+template <typename InputDeviceType>
+FactoryListType<InputDeviceType> FactoryList<InputDeviceType>::list;
+
+} // namespace Impl
+
+/**
+ * Registers an input device factory.
+ * @tparam InputDeviceType the type of input devices the factory can create
+ * @param name the name of the factory. Will be used to match the "engine" parameter when creating
+ *     a device
+ * @param factory the factory object to register
+ */
+template <typename InputDeviceType>
+void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDeviceType>> factory) {
+    auto pair = std::make_pair(name, std::move(factory));
+    if (!Impl::FactoryList<InputDeviceType>::list.insert(std::move(pair)).second) {
+        LOG_ERROR(Input, "Factory '{}' already registered", name);
+    }
+}
+
+/**
+ * Unregisters an input device factory.
+ * @tparam InputDeviceType the type of input devices the factory can create
+ * @param name the name of the factory to unregister
+ */
+template <typename InputDeviceType>
+void UnregisterFactory(const std::string& name) {
+    if (Impl::FactoryList<InputDeviceType>::list.erase(name) == 0) {
+        LOG_ERROR(Input, "Factory '{}' not registered", name);
+    }
+}
+
+/**
+ * Create an input device from given paramters.
+ * @tparam InputDeviceType the type of input devices to create
+ * @param params a serialized ParamPackage string that contains all parameters for creating the
+ * device
+ */
+template <typename InputDeviceType>
+std::unique_ptr<InputDeviceType> CreateDeviceFromString(const std::string& params) {
+    const Common::ParamPackage package(params);
+    const std::string engine = package.Get("engine", "null");
+    const auto& factory_list = Impl::FactoryList<InputDeviceType>::list;
+    const auto pair = factory_list.find(engine);
+    if (pair == factory_list.end()) {
+        if (engine != "null") {
+            LOG_ERROR(Input, "Unknown engine name: {}", engine);
+        }
+        return std::make_unique<InputDeviceType>();
+    }
+    return pair->second->Create(package);
+}
+
+/**
+ * Create an input device from given paramters.
+ * @tparam InputDeviceType the type of input devices to create
+ * @param A ParamPackage that contains all parameters for creating the device
+ */
+template <typename InputDeviceType>
+std::unique_ptr<InputDeviceType> CreateDevice(const Common::ParamPackage package) {
+    const std::string engine = package.Get("engine", "null");
+    const auto& factory_list = Impl::FactoryList<InputDeviceType>::list;
+    const auto pair = factory_list.find(engine);
+    if (pair == factory_list.end()) {
+        if (engine != "null") {
+            LOG_ERROR(Input, "Unknown engine name: {}", engine);
+        }
+        return std::make_unique<InputDeviceType>();
+    }
+    return pair->second->Create(package);
+}
+
+} // namespace Input

From bf71d18af99368d7658c9519086c40e73c6abfdd Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 15:02:01 -0500
Subject: [PATCH 02/88] core/hid: Move input_interpreter to hid

---
 src/core/CMakeLists.txt                          | 4 ++--
 src/core/{frontend => hid}/input_interpreter.cpp | 2 +-
 src/core/{frontend => hid}/input_interpreter.h   | 0
 src/yuzu/applets/qt_web_browser.cpp              | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)
 rename src/core/{frontend => hid}/input_interpreter.cpp (97%)
 rename src/core/{frontend => hid}/input_interpreter.h (100%)

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 9f0fbba2d9..14ba986d3e 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -132,11 +132,11 @@ add_library(core STATIC
     frontend/emu_window.h
     frontend/framebuffer_layout.cpp
     frontend/framebuffer_layout.h
-    frontend/input_interpreter.cpp
-    frontend/input_interpreter.h
     frontend/input.h
     hardware_interrupt_manager.cpp
     hardware_interrupt_manager.h
+    hid/input_interpreter.cpp
+    hid/input_interpreter.h
     hle/api_version.h
     hle/ipc.h
     hle/ipc_helpers.h
diff --git a/src/core/frontend/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp
similarity index 97%
rename from src/core/frontend/input_interpreter.cpp
rename to src/core/hid/input_interpreter.cpp
index 9f6a90e8f1..c33d8a11ad 100644
--- a/src/core/frontend/input_interpreter.cpp
+++ b/src/core/hid/input_interpreter.cpp
@@ -3,7 +3,7 @@
 // Refer to the license.txt file included.
 
 #include "core/core.h"
-#include "core/frontend/input_interpreter.h"
+#include "core/hid/input_interpreter.h"
 #include "core/hle/service/hid/controllers/npad.h"
 #include "core/hle/service/hid/hid.h"
 #include "core/hle/service/sm/sm.h"
diff --git a/src/core/frontend/input_interpreter.h b/src/core/hid/input_interpreter.h
similarity index 100%
rename from src/core/frontend/input_interpreter.h
rename to src/core/hid/input_interpreter.h
diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp
index da8c6882ab..24d72a4960 100644
--- a/src/yuzu/applets/qt_web_browser.cpp
+++ b/src/yuzu/applets/qt_web_browser.cpp
@@ -15,7 +15,7 @@
 
 #include "common/fs/path_util.h"
 #include "core/core.h"
-#include "core/frontend/input_interpreter.h"
+#include "core/hid/input_interpreter.h"
 #include "input_common/keyboard.h"
 #include "input_common/main.h"
 #include "yuzu/applets/qt_web_browser.h"

From 449576df93f6beb70cff0e009ccb2dd8bce1e085 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 16:29:43 -0500
Subject: [PATCH 03/88] core/hid: Move motion_input, create input converter and
 hid_types

---
 src/core/CMakeLists.txt          |   5 +
 src/core/hid/hid_types.h         | 388 +++++++++++++++++++++++++++++++
 src/core/hid/input_converter.cpp | 345 +++++++++++++++++++++++++++
 src/core/hid/input_converter.h   |  77 ++++++
 src/core/hid/motion_input.cpp    | 278 ++++++++++++++++++++++
 src/core/hid/motion_input.h      |  71 ++++++
 6 files changed, 1164 insertions(+)
 create mode 100644 src/core/hid/hid_types.h
 create mode 100644 src/core/hid/input_converter.cpp
 create mode 100644 src/core/hid/input_converter.h
 create mode 100644 src/core/hid/motion_input.cpp
 create mode 100644 src/core/hid/motion_input.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 14ba986d3e..eddf455c08 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -135,8 +135,13 @@ add_library(core STATIC
     frontend/input.h
     hardware_interrupt_manager.cpp
     hardware_interrupt_manager.h
+    hid/hid_types.h
+    hid/input_converter.cpp
+    hid/input_converter.h
     hid/input_interpreter.cpp
     hid/input_interpreter.h
+    hid/motion_input.cpp
+    hid/motion_input.h
     hle/api_version.h
     hle/ipc.h
     hle/ipc_helpers.h
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
new file mode 100644
index 0000000000..d3f7930c93
--- /dev/null
+++ b/src/core/hid/hid_types.h
@@ -0,0 +1,388 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/bit_field.h"
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+#include "common/point.h"
+#include "common/uuid.h"
+
+namespace Core::HID {
+
+// This is nn::hid::NpadIdType
+enum class NpadIdType : u8 {
+    Player1 = 0x0,
+    Player2 = 0x1,
+    Player3 = 0x2,
+    Player4 = 0x3,
+    Player5 = 0x4,
+    Player6 = 0x5,
+    Player7 = 0x6,
+    Player8 = 0x7,
+    Other = 0x10,
+    Handheld = 0x20,
+
+    Invalid = 0xFF,
+};
+
+/// Converts a NpadIdType to an array index.
+constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
+    switch (npad_id_type) {
+    case NpadIdType::Player1:
+        return 0;
+    case NpadIdType::Player2:
+        return 1;
+    case NpadIdType::Player3:
+        return 2;
+    case NpadIdType::Player4:
+        return 3;
+    case NpadIdType::Player5:
+        return 4;
+    case NpadIdType::Player6:
+        return 5;
+    case NpadIdType::Player7:
+        return 6;
+    case NpadIdType::Player8:
+        return 7;
+    case NpadIdType::Other:
+        return 8;
+    case NpadIdType::Handheld:
+        return 9;
+    default:
+        return 0;
+    }
+}
+
+/// Converts an array index to a NpadIdType
+constexpr NpadIdType IndexToNpadIdType(size_t index) {
+    switch (index) {
+    case 0:
+        return NpadIdType::Player1;
+    case 1:
+        return NpadIdType::Player2;
+    case 2:
+        return NpadIdType::Player3;
+    case 3:
+        return NpadIdType::Player4;
+    case 4:
+        return NpadIdType::Player5;
+    case 5:
+        return NpadIdType::Player6;
+    case 6:
+        return NpadIdType::Player7;
+    case 7:
+        return NpadIdType::Player8;
+    case 8:
+        return NpadIdType::Other;
+    case 9:
+        return NpadIdType::Handheld;
+    default:
+        return NpadIdType::Invalid;
+    }
+}
+
+// This is nn::hid::NpadType
+enum class NpadType : u8 {
+    None = 0,
+    ProController = 3,
+    Handheld = 4,
+    JoyconDual = 5,
+    JoyconLeft = 6,
+    JoyconRight = 7,
+    GameCube = 8,
+    Pokeball = 9,
+    MaxNpadType = 10,
+};
+
+// This is nn::hid::NpadStyleTag
+struct NpadStyleTag {
+    union {
+        u32_le raw{};
+
+        BitField<0, 1, u32> fullkey;
+        BitField<1, 1, u32> handheld;
+        BitField<2, 1, u32> joycon_dual;
+        BitField<3, 1, u32> joycon_left;
+        BitField<4, 1, u32> joycon_right;
+        BitField<5, 1, u32> gamecube;
+        BitField<6, 1, u32> palma;
+        BitField<7, 1, u32> lark;
+        BitField<8, 1, u32> handheld_lark;
+        BitField<9, 1, u32> lucia;
+        BitField<29, 1, u32> system_ext;
+        BitField<30, 1, u32> system;
+    };
+};
+static_assert(sizeof(NpadStyleTag) == 4, "NpadStyleTag is an invalid size");
+
+// This is nn::hid::TouchAttribute
+struct TouchAttribute {
+    union {
+        u32 raw{};
+        BitField<0, 1, u32> start_touch;
+        BitField<1, 1, u32> end_touch;
+    };
+};
+static_assert(sizeof(TouchAttribute) == 0x4, "TouchAttribute is an invalid size");
+
+// This is nn::hid::TouchState
+struct TouchState {
+    u64_le delta_time;
+    TouchAttribute 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");
+
+// This is nn::hid::NpadControllerColor
+struct NpadControllerColor {
+    u32_le body;
+    u32_le button;
+};
+static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size");
+
+// This is nn::hid::AnalogStickState
+struct AnalogStickState {
+    s32_le x;
+    s32_le y;
+};
+static_assert(sizeof(AnalogStickState) == 8, "AnalogStickState is an invalid size");
+
+// This is nn::hid::server::NpadGcTriggerState
+struct NpadGcTriggerState {
+    s64_le sampling_number{};
+    s32_le left{};
+    s32_le right{};
+};
+static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
+
+// This is nn::hid::system::NpadBatteryLevel
+using BatteryLevel = u32;
+static_assert(sizeof(BatteryLevel) == 0x4, "BatteryLevel is an invalid size");
+
+// This is nn::hid::system::NpadPowerInfo
+struct NpadPowerInfo {
+    bool is_powered;
+    bool is_charging;
+    INSERT_PADDING_BYTES(0x6);
+    BatteryLevel battery_level;
+};
+static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
+
+// This is nn::hid::NpadButton
+enum class NpadButton : u64 {
+    None = 0,
+    A = 1U << 0,
+    B = 1U << 1,
+    X = 1U << 2,
+    Y = 1U << 3,
+    StickL = 1U << 4,
+    StickR = 1U << 5,
+    L = 1U << 6,
+    R = 1U << 7,
+    ZL = 1U << 8,
+    ZR = 1U << 9,
+    Plus = 1U << 10,
+    Minus = 1U << 11,
+
+    Left = 1U << 12,
+    Up = 1U << 13,
+    Right = 1U << 14,
+    Down = 1U << 15,
+
+    StickLLeft = 1U << 16,
+    StickLUp = 1U << 17,
+    StickLRight = 1U << 18,
+    StickLDown = 1U << 19,
+
+    StickRLeft = 1U << 20,
+    StickRUp = 1U << 21,
+    StickRRight = 1U << 22,
+    StickRDown = 1U << 23,
+
+    LeftSL = 1U << 24,
+    LeftSR = 1U << 25,
+
+    RightSL = 1U << 26,
+    RightSR = 1U << 27,
+
+    Palma = 1U << 28,
+    HandheldLeftB = 1U << 30,
+};
+DECLARE_ENUM_FLAG_OPERATORS(NpadButton);
+
+struct NpadButtonState {
+    union {
+        NpadButton raw{};
+
+        // Buttons
+        BitField<0, 1, u64> a;
+        BitField<1, 1, u64> b;
+        BitField<2, 1, u64> x;
+        BitField<3, 1, u64> y;
+        BitField<4, 1, u64> stick_l;
+        BitField<5, 1, u64> stick_r;
+        BitField<6, 1, u64> l;
+        BitField<7, 1, u64> r;
+        BitField<8, 1, u64> zl;
+        BitField<9, 1, u64> zr;
+        BitField<10, 1, u64> plus;
+        BitField<11, 1, u64> minus;
+
+        // D-Pad
+        BitField<12, 1, u64> left;
+        BitField<13, 1, u64> up;
+        BitField<14, 1, u64> right;
+        BitField<15, 1, u64> down;
+
+        // Left JoyStick
+        BitField<16, 1, u64> stick_l_left;
+        BitField<17, 1, u64> stick_l_up;
+        BitField<18, 1, u64> stick_l_right;
+        BitField<19, 1, u64> stick_l_down;
+
+        // Right JoyStick
+        BitField<20, 1, u64> stick_r_left;
+        BitField<21, 1, u64> stick_r_up;
+        BitField<22, 1, u64> stick_r_right;
+        BitField<23, 1, u64> stick_r_down;
+
+        BitField<24, 1, u64> left_sl;
+        BitField<25, 1, u64> left_sr;
+
+        BitField<26, 1, u64> right_sl;
+        BitField<27, 1, u64> right_sr;
+
+        BitField<28, 1, u64> palma;
+        BitField<30, 1, u64> handheld_left_b;
+    };
+};
+static_assert(sizeof(NpadButtonState) == 0x8, "NpadButtonState has incorrect size.");
+
+// This is nn::hid::DebugPadButton
+struct DebugPadButton {
+    union {
+        u32_le raw{};
+        BitField<0, 1, u32> a;
+        BitField<1, 1, u32> b;
+        BitField<2, 1, u32> x;
+        BitField<3, 1, u32> y;
+        BitField<4, 1, u32> l;
+        BitField<5, 1, u32> r;
+        BitField<6, 1, u32> zl;
+        BitField<7, 1, u32> zr;
+        BitField<8, 1, u32> plus;
+        BitField<9, 1, u32> minus;
+        BitField<10, 1, u32> d_left;
+        BitField<11, 1, u32> d_up;
+        BitField<12, 1, u32> d_right;
+        BitField<13, 1, u32> d_down;
+    };
+};
+static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size");
+
+// This is nn::hid::VibrationDeviceType
+enum class VibrationDeviceType : u32 {
+    Unknown = 0,
+    LinearResonantActuator = 1,
+    GcErm = 2,
+};
+
+// This is nn::hid::VibrationDevicePosition
+enum class VibrationDevicePosition : u32 {
+    None = 0,
+    Left = 1,
+    Right = 2,
+};
+
+// This is nn::hid::VibrationValue
+struct VibrationValue {
+    f32 low_amplitude;
+    f32 low_frequency;
+    f32 high_amplitude;
+    f32 high_frequency;
+};
+static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size.");
+
+// This is nn::hid::VibrationGcErmCommand
+enum class VibrationGcErmCommand : u64 {
+    Stop = 0,
+    Start = 1,
+    StopHard = 2,
+};
+
+// This is nn::hid::VibrationDeviceInfo
+struct VibrationDeviceInfo {
+    VibrationDeviceType type{};
+    VibrationDevicePosition position{};
+};
+static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size.");
+
+// This is nn::hid::KeyboardModifier
+struct KeyboardModifier {
+    union {
+        u32_le raw{};
+        BitField<0, 1, u32> control;
+        BitField<1, 1, u32> shift;
+        BitField<2, 1, u32> left_alt;
+        BitField<3, 1, u32> right_alt;
+        BitField<4, 1, u32> gui;
+        BitField<8, 1, u32> caps_lock;
+        BitField<9, 1, u32> scroll_lock;
+        BitField<10, 1, u32> num_lock;
+        BitField<11, 1, u32> katakana;
+        BitField<12, 1, u32> hiragana;
+    };
+};
+static_assert(sizeof(KeyboardModifier) == 0x4, "KeyboardModifier is an invalid size");
+
+// This is nn::hid::KeyboardKey
+struct KeyboardKey {
+    // This should be a 256 bit flag
+    std::array<u8, 32> key;
+};
+static_assert(sizeof(KeyboardKey) == 0x20, "KeyboardKey is an invalid size");
+
+// This is nn::hid::MouseButton
+struct MouseButton {
+    union {
+        u32_le raw{};
+        BitField<0, 1, u32> left;
+        BitField<1, 1, u32> right;
+        BitField<2, 1, u32> middle;
+        BitField<3, 1, u32> forward;
+        BitField<4, 1, u32> back;
+    };
+};
+static_assert(sizeof(MouseButton) == 0x4, "MouseButton is an invalid size");
+
+// This is nn::hid::MouseAttribute
+struct MouseAttribute {
+    union {
+        u32_le raw{};
+        BitField<0, 1, u32> transferable;
+        BitField<1, 1, u32> is_connected;
+    };
+};
+static_assert(sizeof(MouseAttribute) == 0x4, "MouseAttribute is an invalid size");
+
+// This is nn::hid::detail::MouseState
+struct MouseState {
+    s64_le sampling_number;
+    s32_le x;
+    s32_le y;
+    s32_le delta_x;
+    s32_le delta_y;
+    s32_le delta_wheel_x;
+    s32_le delta_wheel_y;
+    MouseButton button;
+    MouseAttribute attribute;
+};
+static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size");
+} // namespace Core::HID
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
new file mode 100644
index 0000000000..5834622e92
--- /dev/null
+++ b/src/core/hid/input_converter.cpp
@@ -0,0 +1,345 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#include <random>
+
+#include "common/input.h"
+#include "core/hid/input_converter.h"
+
+namespace Core::HID {
+
+Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback) {
+    Input::BatteryStatus battery{};
+    switch (callback.type) {
+    case Input::InputType::Analog:
+    case Input::InputType::Trigger: {
+        const auto value = TransformToTrigger(callback).analog.value;
+        battery = Input::BatteryLevel::Empty;
+        if (value > 0.2f) {
+            battery = Input::BatteryLevel::Critical;
+        }
+        if (value > 0.4f) {
+            battery = Input::BatteryLevel::Low;
+        }
+        if (value > 0.6f) {
+            battery = Input::BatteryLevel::Medium;
+        }
+        if (value > 0.8f) {
+            battery = Input::BatteryLevel::Full;
+        }
+        if (value >= 1.0f) {
+            battery = Input::BatteryLevel::Charging;
+        }
+        break;
+    }
+    case Input::InputType::Battery:
+        battery = callback.battery_status;
+        break;
+    default:
+        LOG_ERROR(Input, "Conversion from type {} to battery not implemented", callback.type);
+        break;
+    }
+
+    return battery;
+}
+
+Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback) {
+    Input::ButtonStatus status{};
+    switch (callback.type) {
+    case Input::InputType::Analog:
+    case Input::InputType::Trigger:
+        status.value = TransformToTrigger(callback).pressed;
+        break;
+    case Input::InputType::Button:
+        status = callback.button_status;
+        break;
+    default:
+        LOG_ERROR(Input, "Conversion from type {} to button not implemented", callback.type);
+        break;
+    }
+
+    if (status.inverted) {
+        status.value = !status.value;
+    }
+
+    return status;
+}
+
+Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback) {
+    Input::MotionStatus status{};
+    switch (callback.type) {
+    case Input::InputType::Button: {
+        if (TransformToButton(callback).value) {
+            std::random_device device;
+            std::mt19937 gen(device());
+            std::uniform_int_distribution<s16> distribution(-1000, 1000);
+            Input::AnalogProperties properties{
+                .deadzone = 0.0,
+                .range = 1.0f,
+                .offset = 0.0,
+            };
+            status.accel.x = {
+                .value = 0,
+                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
+                .properties = properties,
+            };
+            status.accel.y = {
+                .value = 0,
+                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
+                .properties = properties,
+            };
+            status.accel.z = {
+                .value = 0,
+                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
+                .properties = properties,
+            };
+            status.gyro.x = {
+                .value = 0,
+                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
+                .properties = properties,
+            };
+            status.gyro.y = {
+                .value = 0,
+                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
+                .properties = properties,
+            };
+            status.gyro.z = {
+                .value = 0,
+                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
+                .properties = properties,
+            };
+        }
+        break;
+    }
+    case Input::InputType::Motion:
+        status = callback.motion_status;
+        break;
+    default:
+        LOG_ERROR(Input, "Conversion from type {} to motion not implemented", callback.type);
+        break;
+    }
+    SanitizeAnalog(status.accel.x, false);
+    SanitizeAnalog(status.accel.y, false);
+    SanitizeAnalog(status.accel.z, false);
+    SanitizeAnalog(status.gyro.x, false);
+    SanitizeAnalog(status.gyro.y, false);
+    SanitizeAnalog(status.gyro.z, false);
+
+    return status;
+}
+
+Input::StickStatus TransformToStick(const Input::CallbackStatus& callback) {
+    Input::StickStatus status{};
+
+    switch (callback.type) {
+    case Input::InputType::Stick:
+        status = callback.stick_status;
+        break;
+    default:
+        LOG_ERROR(Input, "Conversion from type {} to stick not implemented", callback.type);
+        break;
+    }
+
+    SanitizeStick(status.x, status.y, true);
+    const Input::AnalogProperties& properties_x = status.x.properties;
+    const Input::AnalogProperties& properties_y = status.y.properties;
+    const float x = status.x.value;
+    const float y = status.y.value;
+
+    // Set directional buttons
+    status.right = x > properties_x.threshold;
+    status.left = x < -properties_x.threshold;
+    status.up = y > properties_y.threshold;
+    status.down = y < -properties_y.threshold;
+
+    return status;
+}
+
+Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback) {
+    Input::TouchStatus status{};
+
+    switch (callback.type) {
+    case Input::InputType::Touch:
+        status = callback.touch_status;
+        break;
+    default:
+        LOG_ERROR(Input, "Conversion from type {} to touch not implemented", callback.type);
+        break;
+    }
+
+    SanitizeAnalog(status.x, true);
+    SanitizeAnalog(status.y, true);
+    float& x = status.x.value;
+    float& y = status.y.value;
+
+    // Adjust if value is inverted
+    x = status.x.properties.inverted ? 1.0f + x : x;
+    y = status.y.properties.inverted ? 1.0f + y : y;
+
+    // clamp value
+    x = std::clamp(x, 0.0f, 1.0f);
+    y = std::clamp(y, 0.0f, 1.0f);
+
+    if (status.pressed.inverted) {
+        status.pressed.value = !status.pressed.value;
+    }
+
+    return status;
+}
+
+Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback) {
+    Input::TriggerStatus status{};
+    float& raw_value = status.analog.raw_value;
+    bool calculate_button_value = true;
+
+    switch (callback.type) {
+    case Input::InputType::Analog:
+        status.analog.properties = callback.analog_status.properties;
+        raw_value = callback.analog_status.raw_value;
+        break;
+    case Input::InputType::Button:
+        status.analog.properties.range = 1.0f;
+        status.analog.properties.inverted = callback.button_status.inverted;
+        raw_value = callback.button_status.value ? 1.0f : 0.0f;
+        break;
+    case Input::InputType::Trigger:
+        status = callback.trigger_status;
+        calculate_button_value = false;
+        break;
+    default:
+        LOG_ERROR(Input, "Conversion from type {} to trigger not implemented", callback.type);
+        break;
+    }
+
+    SanitizeAnalog(status.analog, true);
+    const Input::AnalogProperties& properties = status.analog.properties;
+    float& value = status.analog.value;
+
+    // Set button status
+    if (calculate_button_value) {
+        status.pressed = value > properties.threshold;
+    }
+
+    // Adjust if value is inverted
+    value = properties.inverted ? 1.0f + value : value;
+
+    // clamp value
+    value = std::clamp(value, 0.0f, 1.0f);
+
+    return status;
+}
+
+void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value) {
+    const Input::AnalogProperties& properties = analog.properties;
+    float& raw_value = analog.raw_value;
+    float& value = analog.value;
+
+    if (!std::isnormal(raw_value)) {
+        raw_value = 0;
+    }
+
+    // Apply center offset
+    raw_value -= properties.offset;
+
+    // Set initial values to be formated
+    value = raw_value;
+
+    // Calculate vector size
+    const float r = std::abs(value);
+
+    // Return zero if value is smaller than the deadzone
+    if (r <= properties.deadzone || properties.deadzone == 1.0f) {
+        analog.value = 0;
+        return;
+    }
+
+    // Adjust range of value
+    const float deadzone_factor =
+        1.0f / r * (r - properties.deadzone) / (1.0f - properties.deadzone);
+    value = value * deadzone_factor / properties.range;
+
+    // Invert direction if needed
+    if (properties.inverted) {
+        value = -value;
+    }
+
+    // Clamp value
+    if (clamp_value) {
+        value = std::clamp(value, -1.0f, 1.0f);
+    }
+}
+
+void SanitizeStick(Input::AnalogStatus& analog_x, Input::AnalogStatus& analog_y, bool clamp_value) {
+    const Input::AnalogProperties& properties_x = analog_x.properties;
+    const Input::AnalogProperties& properties_y = analog_y.properties;
+    float& raw_x = analog_x.raw_value;
+    float& raw_y = analog_y.raw_value;
+    float& x = analog_x.value;
+    float& y = analog_y.value;
+
+    if (!std::isnormal(raw_x)) {
+        raw_x = 0;
+    }
+    if (!std::isnormal(raw_y)) {
+        raw_y = 0;
+    }
+
+    // Apply center offset
+    raw_x += properties_x.offset;
+    raw_y += properties_y.offset;
+
+    // Apply X scale correction from offset
+    if (std::abs(properties_x.offset) < 0.5f) {
+        if (raw_x > 0) {
+            raw_x /= 1 + properties_x.offset;
+        } else {
+            raw_x /= 1 - properties_x.offset;
+        }
+    }
+
+    // Apply Y scale correction from offset
+    if (std::abs(properties_y.offset) < 0.5f) {
+        if (raw_y > 0) {
+            raw_y /= 1 + properties_y.offset;
+        } else {
+            raw_y /= 1 - properties_y.offset;
+        }
+    }
+
+    // Invert direction if needed
+    raw_x = properties_x.inverted ? -raw_x : raw_x;
+    raw_y = properties_y.inverted ? -raw_y : raw_y;
+
+    // Set initial values to be formated
+    x = raw_x;
+    y = raw_y;
+
+    // Calculate vector size
+    float r = x * x + y * y;
+    r = std::sqrt(r);
+
+    // TODO(German77): Use deadzone and range of both axis
+
+    // Return zero if values are smaller than the deadzone
+    if (r <= properties_x.deadzone || properties_x.deadzone >= 1.0f) {
+        x = 0;
+        y = 0;
+        return;
+    }
+
+    // Adjust range of joystick
+    const float deadzone_factor =
+        1.0f / r * (r - properties_x.deadzone) / (1.0f - properties_x.deadzone);
+    x = x * deadzone_factor / properties_x.range;
+    y = y * deadzone_factor / properties_x.range;
+    r = r * deadzone_factor / properties_x.range;
+
+    // Normalize joystick
+    if (clamp_value && r > 1.0f) {
+        x /= r;
+        y /= r;
+    }
+}
+
+} // namespace Core::HID
diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h
new file mode 100644
index 0000000000..3cc32e26a9
--- /dev/null
+++ b/src/core/hid/input_converter.h
@@ -0,0 +1,77 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#pragma once
+
+namespace Input {
+struct CallbackStatus;
+};
+
+namespace Core::HID {
+
+/**
+ * Converts raw input data into a valid battery status.
+ *
+ * @param Supported callbacks: Analog, Battery, Trigger.
+ * @return A valid BatteryStatus object.
+ */
+Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback);
+
+/**
+ * Converts raw input data into a valid button status. Applies invert properties to the output.
+ *
+ * @param Supported callbacks: Analog, Button, Trigger.
+ * @return A valid TouchStatus object.
+ */
+Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback);
+
+/**
+ * Converts raw input data into a valid motion status.
+ *
+ * @param Supported callbacks: Motion.
+ * @return A valid TouchStatus object.
+ */
+Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback);
+
+/**
+ * Converts raw input data into a valid stick status. Applies offset, deadzone, range and invert
+ * properties to the output.
+ *
+ * @param Supported callbacks: Stick.
+ * @return A valid StickStatus object.
+ */
+Input::StickStatus TransformToStick(const Input::CallbackStatus& callback);
+
+/**
+ * Converts raw input data into a valid touch status.
+ *
+ * @param Supported callbacks: Touch.
+ * @return A valid TouchStatus object.
+ */
+Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback);
+
+/**
+ * Converts raw input data into a valid trigger status. Applies offset, deadzone, range and
+ * invert properties to the output. Button status uses the threshold property if necessary.
+ *
+ * @param Supported callbacks: Analog, Button, Trigger.
+ * @return A valid TriggerStatus object.
+ */
+Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback);
+
+/**
+ * Converts raw analog data into a valid analog value
+ * @param An analog object containing raw data and properties, bool that determines if the value
+ * needs to be clamped between -1.0f and 1.0f.
+ */
+void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value);
+
+/**
+ * Converts raw stick data into a valid stick value
+ * @param Two analog objects containing raw data and properties, bool that determines if the value
+ * needs to be clamped into the unit circle.
+ */
+void SanitizeStick(Input::AnalogStatus& analog_x, Input::AnalogStatus& analog_y, bool clamp_value);
+
+} // namespace Core::HID
diff --git a/src/core/hid/motion_input.cpp b/src/core/hid/motion_input.cpp
new file mode 100644
index 0000000000..93f37b77bd
--- /dev/null
+++ b/src/core/hid/motion_input.cpp
@@ -0,0 +1,278 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#include "common/math_util.h"
+#include "core/hid/motion_input.h"
+
+namespace Core::HID {
+
+MotionInput::MotionInput() {
+    // Initialize PID constants with default values
+    SetPID(0.3f, 0.005f, 0.0f);
+}
+
+void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) {
+    kp = new_kp;
+    ki = new_ki;
+    kd = new_kd;
+}
+
+void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
+    accel = acceleration;
+}
+
+void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
+    gyro = gyroscope - gyro_drift;
+
+    // Auto adjust drift to minimize drift
+    if (!IsMoving(0.1f)) {
+        gyro_drift = (gyro_drift * 0.9999f) + (gyroscope * 0.0001f);
+    }
+
+    if (gyro.Length2() < gyro_threshold) {
+        gyro = {};
+    } else {
+        only_accelerometer = false;
+    }
+}
+
+void MotionInput::SetQuaternion(const Common::Quaternion<f32>& quaternion) {
+    quat = quaternion;
+}
+
+void MotionInput::SetGyroDrift(const Common::Vec3f& drift) {
+    gyro_drift = drift;
+}
+
+void MotionInput::SetGyroThreshold(f32 threshold) {
+    gyro_threshold = threshold;
+}
+
+void MotionInput::EnableReset(bool reset) {
+    reset_enabled = reset;
+}
+
+void MotionInput::ResetRotations() {
+    rotations = {};
+}
+
+bool MotionInput::IsMoving(f32 sensitivity) const {
+    return gyro.Length() >= sensitivity || accel.Length() <= 0.9f || accel.Length() >= 1.1f;
+}
+
+bool MotionInput::IsCalibrated(f32 sensitivity) const {
+    return real_error.Length() < sensitivity;
+}
+
+void MotionInput::UpdateRotation(u64 elapsed_time) {
+    const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f;
+    if (sample_period > 0.1f) {
+        return;
+    }
+    rotations += gyro * sample_period;
+}
+
+void MotionInput::UpdateOrientation(u64 elapsed_time) {
+    if (!IsCalibrated(0.1f)) {
+        ResetOrientation();
+    }
+    // Short name local variable for readability
+    f32 q1 = quat.w;
+    f32 q2 = quat.xyz[0];
+    f32 q3 = quat.xyz[1];
+    f32 q4 = quat.xyz[2];
+    const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f;
+
+    // Ignore invalid elapsed time
+    if (sample_period > 0.1f) {
+        return;
+    }
+
+    const auto normal_accel = accel.Normalized();
+    auto rad_gyro = gyro * Common::PI * 2;
+    const f32 swap = rad_gyro.x;
+    rad_gyro.x = rad_gyro.y;
+    rad_gyro.y = -swap;
+    rad_gyro.z = -rad_gyro.z;
+
+    // Clear gyro values if there is no gyro present
+    if (only_accelerometer) {
+        rad_gyro.x = 0;
+        rad_gyro.y = 0;
+        rad_gyro.z = 0;
+    }
+
+    // Ignore drift correction if acceleration is not reliable
+    if (accel.Length() >= 0.75f && accel.Length() <= 1.25f) {
+        const f32 ax = -normal_accel.x;
+        const f32 ay = normal_accel.y;
+        const f32 az = -normal_accel.z;
+
+        // Estimated direction of gravity
+        const f32 vx = 2.0f * (q2 * q4 - q1 * q3);
+        const f32 vy = 2.0f * (q1 * q2 + q3 * q4);
+        const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
+
+        // Error is cross product between estimated direction and measured direction of gravity
+        const Common::Vec3f new_real_error = {
+            az * vx - ax * vz,
+            ay * vz - az * vy,
+            ax * vy - ay * vx,
+        };
+
+        derivative_error = new_real_error - real_error;
+        real_error = new_real_error;
+
+        // Prevent integral windup
+        if (ki != 0.0f && !IsCalibrated(0.05f)) {
+            integral_error += real_error;
+        } else {
+            integral_error = {};
+        }
+
+        // Apply feedback terms
+        if (!only_accelerometer) {
+            rad_gyro += kp * real_error;
+            rad_gyro += ki * integral_error;
+            rad_gyro += kd * derivative_error;
+        } else {
+            // Give more weight to accelerometer values to compensate for the lack of gyro
+            rad_gyro += 35.0f * kp * real_error;
+            rad_gyro += 10.0f * ki * integral_error;
+            rad_gyro += 10.0f * kd * derivative_error;
+
+            // Emulate gyro values for games that need them
+            gyro.x = -rad_gyro.y;
+            gyro.y = rad_gyro.x;
+            gyro.z = -rad_gyro.z;
+            UpdateRotation(elapsed_time);
+        }
+    }
+
+    const f32 gx = rad_gyro.y;
+    const f32 gy = rad_gyro.x;
+    const f32 gz = rad_gyro.z;
+
+    // Integrate rate of change of quaternion
+    const f32 pa = q2;
+    const f32 pb = q3;
+    const f32 pc = q4;
+    q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period);
+    q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period);
+    q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period);
+    q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period);
+
+    quat.w = q1;
+    quat.xyz[0] = q2;
+    quat.xyz[1] = q3;
+    quat.xyz[2] = q4;
+    quat = quat.Normalized();
+}
+
+std::array<Common::Vec3f, 3> MotionInput::GetOrientation() const {
+    const Common::Quaternion<float> quad{
+        .xyz = {-quat.xyz[1], -quat.xyz[0], -quat.w},
+        .w = -quat.xyz[2],
+    };
+    const std::array<float, 16> matrix4x4 = quad.ToMatrix();
+
+    return {Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]),
+            Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]),
+            Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10])};
+}
+
+Common::Vec3f MotionInput::GetAcceleration() const {
+    return accel;
+}
+
+Common::Vec3f MotionInput::GetGyroscope() const {
+    return gyro;
+}
+
+Common::Quaternion<f32> MotionInput::GetQuaternion() const {
+    return quat;
+}
+
+Common::Vec3f MotionInput::GetRotations() const {
+    return rotations;
+}
+
+void MotionInput::ResetOrientation() {
+    if (!reset_enabled || only_accelerometer) {
+        return;
+    }
+    if (!IsMoving(0.5f) && accel.z <= -0.9f) {
+        ++reset_counter;
+        if (reset_counter > 900) {
+            quat.w = 0;
+            quat.xyz[0] = 0;
+            quat.xyz[1] = 0;
+            quat.xyz[2] = -1;
+            SetOrientationFromAccelerometer();
+            integral_error = {};
+            reset_counter = 0;
+        }
+    } else {
+        reset_counter = 0;
+    }
+}
+
+void MotionInput::SetOrientationFromAccelerometer() {
+    int iterations = 0;
+    const f32 sample_period = 0.015f;
+
+    const auto normal_accel = accel.Normalized();
+
+    while (!IsCalibrated(0.01f) && ++iterations < 100) {
+        // Short name local variable for readability
+        f32 q1 = quat.w;
+        f32 q2 = quat.xyz[0];
+        f32 q3 = quat.xyz[1];
+        f32 q4 = quat.xyz[2];
+
+        Common::Vec3f rad_gyro;
+        const f32 ax = -normal_accel.x;
+        const f32 ay = normal_accel.y;
+        const f32 az = -normal_accel.z;
+
+        // Estimated direction of gravity
+        const f32 vx = 2.0f * (q2 * q4 - q1 * q3);
+        const f32 vy = 2.0f * (q1 * q2 + q3 * q4);
+        const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
+
+        // Error is cross product between estimated direction and measured direction of gravity
+        const Common::Vec3f new_real_error = {
+            az * vx - ax * vz,
+            ay * vz - az * vy,
+            ax * vy - ay * vx,
+        };
+
+        derivative_error = new_real_error - real_error;
+        real_error = new_real_error;
+
+        rad_gyro += 10.0f * kp * real_error;
+        rad_gyro += 5.0f * ki * integral_error;
+        rad_gyro += 10.0f * kd * derivative_error;
+
+        const f32 gx = rad_gyro.y;
+        const f32 gy = rad_gyro.x;
+        const f32 gz = rad_gyro.z;
+
+        // Integrate rate of change of quaternion
+        const f32 pa = q2;
+        const f32 pb = q3;
+        const f32 pc = q4;
+        q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period);
+        q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period);
+        q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period);
+        q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period);
+
+        quat.w = q1;
+        quat.xyz[0] = q2;
+        quat.xyz[1] = q3;
+        quat.xyz[2] = q4;
+        quat = quat.Normalized();
+    }
+}
+} // namespace Core::HID
diff --git a/src/core/hid/motion_input.h b/src/core/hid/motion_input.h
new file mode 100644
index 0000000000..3deef5ac30
--- /dev/null
+++ b/src/core/hid/motion_input.h
@@ -0,0 +1,71 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#pragma once
+
+#include "common/common_types.h"
+#include "common/quaternion.h"
+#include "common/vector_math.h"
+
+namespace Core::HID {
+
+class MotionInput {
+public:
+    explicit MotionInput();
+
+    MotionInput(const MotionInput&) = default;
+    MotionInput& operator=(const MotionInput&) = default;
+
+    MotionInput(MotionInput&&) = default;
+    MotionInput& operator=(MotionInput&&) = default;
+
+    void SetPID(f32 new_kp, f32 new_ki, f32 new_kd);
+    void SetAcceleration(const Common::Vec3f& acceleration);
+    void SetGyroscope(const Common::Vec3f& gyroscope);
+    void SetQuaternion(const Common::Quaternion<f32>& quaternion);
+    void SetGyroDrift(const Common::Vec3f& drift);
+    void SetGyroThreshold(f32 threshold);
+
+    void EnableReset(bool reset);
+    void ResetRotations();
+
+    void UpdateRotation(u64 elapsed_time);
+    void UpdateOrientation(u64 elapsed_time);
+
+    [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const;
+    [[nodiscard]] Common::Vec3f GetAcceleration() const;
+    [[nodiscard]] Common::Vec3f GetGyroscope() const;
+    [[nodiscard]] Common::Vec3f GetRotations() const;
+    [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const;
+
+    [[nodiscard]] bool IsMoving(f32 sensitivity) const;
+    [[nodiscard]] bool IsCalibrated(f32 sensitivity) const;
+
+private:
+    void ResetOrientation();
+    void SetOrientationFromAccelerometer();
+
+    // PID constants
+    f32 kp;
+    f32 ki;
+    f32 kd;
+
+    // PID errors
+    Common::Vec3f real_error;
+    Common::Vec3f integral_error;
+    Common::Vec3f derivative_error;
+
+    Common::Quaternion<f32> quat{{0.0f, 0.0f, -1.0f}, 0.0f};
+    Common::Vec3f rotations;
+    Common::Vec3f accel;
+    Common::Vec3f gyro;
+    Common::Vec3f gyro_drift;
+
+    f32 gyro_threshold = 0.0f;
+    u32 reset_counter = 0;
+    bool reset_enabled = true;
+    bool only_accelerometer = true;
+};
+
+} // namespace Core::HID

From ea7b1fbc673e40d5e51f2d185ebe8542741164fa Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 16:34:05 -0500
Subject: [PATCH 04/88] input_common: Create input_engine

---
 src/input_common/input_engine.cpp | 361 ++++++++++++++++++++++++++++++
 src/input_common/input_engine.h   | 224 ++++++++++++++++++
 2 files changed, 585 insertions(+)
 create mode 100644 src/input_common/input_engine.cpp
 create mode 100644 src/input_common/input_engine.h

diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp
new file mode 100644
index 0000000000..1534f24b04
--- /dev/null
+++ b/src/input_common/input_engine.cpp
@@ -0,0 +1,361 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#include "common/logging/log.h"
+#include "common/param_package.h"
+#include "input_common/input_engine.h"
+
+namespace InputCommon {
+
+void InputEngine::PreSetController(const PadIdentifier& identifier) {
+    std::lock_guard lock{mutex};
+    if (!controller_list.contains(identifier)) {
+        controller_list.insert_or_assign(identifier, ControllerData{});
+    }
+}
+
+void InputEngine::PreSetButton(const PadIdentifier& identifier, int button) {
+    std::lock_guard lock{mutex};
+    ControllerData& controller = controller_list.at(identifier);
+    if (!controller.buttons.contains(button)) {
+        controller.buttons.insert_or_assign(button, false);
+    }
+}
+
+void InputEngine::PreSetHatButton(const PadIdentifier& identifier, int button) {
+    std::lock_guard lock{mutex};
+    ControllerData& controller = controller_list.at(identifier);
+    if (!controller.hat_buttons.contains(button)) {
+        controller.hat_buttons.insert_or_assign(button, u8{0});
+    }
+}
+
+void InputEngine::PreSetAxis(const PadIdentifier& identifier, int axis) {
+    std::lock_guard lock{mutex};
+    ControllerData& controller = controller_list.at(identifier);
+    if (!controller.axes.contains(axis)) {
+        controller.axes.insert_or_assign(axis, 0.0f);
+    }
+}
+
+void InputEngine::PreSetMotion(const PadIdentifier& identifier, int motion) {
+    std::lock_guard lock{mutex};
+    ControllerData& controller = controller_list.at(identifier);
+    if (!controller.motions.contains(motion)) {
+        controller.motions.insert_or_assign(motion, BasicMotion{});
+    }
+}
+
+void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool value) {
+    {
+        std::lock_guard lock{mutex};
+        ControllerData& controller = controller_list.at(identifier);
+        if (!configuring) {
+            controller.buttons.insert_or_assign(button, value);
+        }
+    }
+    TriggerOnButtonChange(identifier, button, value);
+}
+
+void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 value) {
+    {
+        std::lock_guard lock{mutex};
+        ControllerData& controller = controller_list.at(identifier);
+        if (!configuring) {
+            controller.hat_buttons.insert_or_assign(button, value);
+        }
+    }
+    TriggerOnHatButtonChange(identifier, button, value);
+}
+
+void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) {
+    {
+        std::lock_guard lock{mutex};
+        ControllerData& controller = controller_list.at(identifier);
+        if (!configuring) {
+            controller.axes.insert_or_assign(axis, value);
+        }
+    }
+    TriggerOnAxisChange(identifier, axis, value);
+}
+
+void InputEngine::SetBattery(const PadIdentifier& identifier, BatteryLevel value) {
+    {
+        std::lock_guard lock{mutex};
+        ControllerData& controller = controller_list.at(identifier);
+        if (!configuring) {
+            controller.battery = value;
+        }
+    }
+    TriggerOnBatteryChange(identifier, value);
+}
+
+void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, BasicMotion value) {
+    {
+        std::lock_guard lock{mutex};
+        ControllerData& controller = controller_list.at(identifier);
+        if (!configuring) {
+            controller.motions.insert_or_assign(motion, value);
+        }
+    }
+    TriggerOnMotionChange(identifier, motion, value);
+}
+
+bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const {
+    std::lock_guard lock{mutex};
+    if (!controller_list.contains(identifier)) {
+        LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
+                  identifier.pad, identifier.port);
+        return false;
+    }
+    ControllerData controller = controller_list.at(identifier);
+    if (!controller.buttons.contains(button)) {
+        LOG_ERROR(Input, "Invalid button {}", button);
+        return false;
+    }
+    return controller.buttons.at(button);
+}
+
+bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const {
+    std::lock_guard lock{mutex};
+    if (!controller_list.contains(identifier)) {
+        LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
+                  identifier.pad, identifier.port);
+        return false;
+    }
+    ControllerData controller = controller_list.at(identifier);
+    if (!controller.hat_buttons.contains(button)) {
+        LOG_ERROR(Input, "Invalid hat button {}", button);
+        return false;
+    }
+    return (controller.hat_buttons.at(button) & direction) != 0;
+}
+
+f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const {
+    std::lock_guard lock{mutex};
+    if (!controller_list.contains(identifier)) {
+        LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
+                  identifier.pad, identifier.port);
+        return 0.0f;
+    }
+    ControllerData controller = controller_list.at(identifier);
+    if (!controller.axes.contains(axis)) {
+        LOG_ERROR(Input, "Invalid axis {}", axis);
+        return 0.0f;
+    }
+    return controller.axes.at(axis);
+}
+
+BatteryLevel InputEngine::GetBattery(const PadIdentifier& identifier) const {
+    std::lock_guard lock{mutex};
+    if (!controller_list.contains(identifier)) {
+        LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
+                  identifier.pad, identifier.port);
+        return BatteryLevel::Charging;
+    }
+    ControllerData controller = controller_list.at(identifier);
+    return controller.battery;
+}
+
+BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) const {
+    std::lock_guard lock{mutex};
+    if (!controller_list.contains(identifier)) {
+        LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
+                  identifier.pad, identifier.port);
+        return {};
+    }
+    ControllerData controller = controller_list.at(identifier);
+    return controller.motions.at(motion);
+}
+
+void InputEngine::ResetButtonState() {
+    for (std::pair<PadIdentifier, ControllerData> controller : controller_list) {
+        for (std::pair<int, bool> button : controller.second.buttons) {
+            SetButton(controller.first, button.first, false);
+        }
+        for (std::pair<int, bool> button : controller.second.hat_buttons) {
+            SetHatButton(controller.first, button.first, false);
+        }
+    }
+}
+
+void InputEngine::ResetAnalogState() {
+    for (std::pair<PadIdentifier, ControllerData> controller : controller_list) {
+        for (std::pair<int, float> axis : controller.second.axes) {
+            SetAxis(controller.first, axis.first, 0.0);
+        }
+    }
+}
+
+void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value) {
+    std::lock_guard lock{mutex_callback};
+    for (const std::pair<int, InputIdentifier> poller_pair : callback_list) {
+        const InputIdentifier& poller = poller_pair.second;
+        if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Button, button)) {
+            continue;
+        }
+        if (poller.callback.on_change) {
+            poller.callback.on_change();
+        }
+    }
+    if (!configuring || !mapping_callback.on_data) {
+        return;
+    }
+    if (value == GetButton(identifier, button)) {
+        return;
+    }
+    mapping_callback.on_data(MappingData{
+        .engine = GetEngineName(),
+        .pad = identifier,
+        .type = EngineInputType::Button,
+        .index = button,
+        .button_value = value,
+    });
+}
+
+void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value) {
+    std::lock_guard lock{mutex_callback};
+    for (const std::pair<int, InputIdentifier> poller_pair : callback_list) {
+        const InputIdentifier& poller = poller_pair.second;
+        if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::HatButton, button)) {
+            continue;
+        }
+        if (poller.callback.on_change) {
+            poller.callback.on_change();
+        }
+    }
+    if (!configuring || !mapping_callback.on_data) {
+        return;
+    }
+    for (std::size_t index = 1; index < 0xff; index <<= 1) {
+        bool button_value = (value & index) != 0;
+        if (button_value == GetHatButton(identifier, button, static_cast<u8>(index))) {
+            continue;
+        }
+        mapping_callback.on_data(MappingData{
+            .engine = GetEngineName(),
+            .pad = identifier,
+            .type = EngineInputType::HatButton,
+            .index = button,
+            .hat_name = GetHatButtonName(static_cast<u8>(index)),
+        });
+    }
+}
+
+void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value) {
+    std::lock_guard lock{mutex_callback};
+    for (const std::pair<int, InputIdentifier> poller_pair : callback_list) {
+        const InputIdentifier& poller = poller_pair.second;
+        if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Analog, axis)) {
+            continue;
+        }
+        if (poller.callback.on_change) {
+            poller.callback.on_change();
+        }
+    }
+    if (!configuring || !mapping_callback.on_data) {
+        return;
+    }
+    if (std::abs(value - GetAxis(identifier, axis)) < 0.5f) {
+        return;
+    }
+    mapping_callback.on_data(MappingData{
+        .engine = GetEngineName(),
+        .pad = identifier,
+        .type = EngineInputType::Analog,
+        .index = axis,
+        .axis_value = value,
+    });
+}
+
+void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier,
+                                         [[maybe_unused]] BatteryLevel value) {
+    std::lock_guard lock{mutex_callback};
+    for (const std::pair<int, InputIdentifier> poller_pair : callback_list) {
+        const InputIdentifier& poller = poller_pair.second;
+        if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Battery, 0)) {
+            continue;
+        }
+        if (poller.callback.on_change) {
+            poller.callback.on_change();
+        }
+    }
+}
+
+void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int motion,
+                                        BasicMotion value) {
+    std::lock_guard lock{mutex_callback};
+    for (const std::pair<int, InputIdentifier> poller_pair : callback_list) {
+        const InputIdentifier& poller = poller_pair.second;
+        if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Motion, motion)) {
+            continue;
+        }
+        if (poller.callback.on_change) {
+            poller.callback.on_change();
+        }
+    }
+    if (!configuring || !mapping_callback.on_data) {
+        return;
+    }
+    if (std::abs(value.gyro_x) < 1.0f && std::abs(value.gyro_y) < 1.0f &&
+        std::abs(value.gyro_z) < 1.0f) {
+        return;
+    }
+    mapping_callback.on_data(MappingData{
+        .engine = GetEngineName(),
+        .pad = identifier,
+        .type = EngineInputType::Motion,
+        .index = motion,
+        .motion_value = value,
+    });
+}
+
+bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier,
+                                         const PadIdentifier& identifier, EngineInputType type,
+                                         std::size_t index) const {
+    if (input_identifier.type != type) {
+        return false;
+    }
+    if (input_identifier.index != index) {
+        return false;
+    }
+    if (input_identifier.identifier != identifier) {
+        return false;
+    }
+    return true;
+}
+
+void InputEngine::BeginConfiguration() {
+    configuring = true;
+}
+
+void InputEngine::EndConfiguration() {
+    configuring = false;
+}
+
+const std::string& InputEngine::GetEngineName() const {
+    return input_engine;
+}
+
+int InputEngine::SetCallback(InputIdentifier input_identifier) {
+    std::lock_guard lock{mutex_callback};
+    callback_list.insert_or_assign(last_callback_key, input_identifier);
+    return last_callback_key++;
+}
+
+void InputEngine::SetMappingCallback(MappingCallback callback) {
+    std::lock_guard lock{mutex_callback};
+    mapping_callback = std::move(callback);
+}
+
+void InputEngine::DeleteCallback(int key) {
+    std::lock_guard lock{mutex_callback};
+    if (!callback_list.contains(key)) {
+        LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
+        return;
+    }
+    callback_list.erase(key);
+}
+
+} // namespace InputCommon
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h
new file mode 100644
index 0000000000..86a8e00d8e
--- /dev/null
+++ b/src/input_common/input_engine.h
@@ -0,0 +1,224 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#pragma once
+
+#include <functional>
+#include <mutex>
+#include <unordered_map>
+
+#include "common/common_types.h"
+#include "common/input.h"
+#include "common/param_package.h"
+#include "common/uuid.h"
+#include "input_common/main.h"
+
+// Pad Identifier of data source
+struct PadIdentifier {
+    Common::UUID guid{};
+    std::size_t port{};
+    std::size_t pad{};
+
+    friend constexpr bool operator==(const PadIdentifier&, const PadIdentifier&) = default;
+};
+
+// Basic motion data containing data from the sensors and a timestamp in microsecons
+struct BasicMotion {
+    float gyro_x;
+    float gyro_y;
+    float gyro_z;
+    float accel_x;
+    float accel_y;
+    float accel_z;
+    u64 delta_timestamp;
+};
+
+// Stages of a battery charge
+enum class BatteryLevel {
+    Empty,
+    Critical,
+    Low,
+    Medium,
+    Full,
+    Charging,
+};
+
+// Types of input that are stored in the engine
+enum class EngineInputType {
+    None,
+    Button,
+    HatButton,
+    Analog,
+    Motion,
+    Battery,
+};
+
+namespace std {
+// Hash used to create lists from PadIdentifier data
+template <>
+struct hash<PadIdentifier> {
+    size_t operator()(const PadIdentifier& pad_id) const noexcept {
+        u64 hash_value = pad_id.guid.uuid[1] ^ pad_id.guid.uuid[0];
+        hash_value ^= (static_cast<u64>(pad_id.port) << 32);
+        hash_value ^= static_cast<u64>(pad_id.pad);
+        return static_cast<size_t>(hash_value);
+    }
+};
+
+} // namespace std
+
+namespace InputCommon {
+
+// Data from the engine and device needed for creating a ParamPackage
+struct MappingData {
+    std::string engine{};
+    PadIdentifier pad{};
+    EngineInputType type{};
+    int index{};
+    bool button_value{};
+    std::string hat_name{};
+    f32 axis_value{};
+    BasicMotion motion_value{};
+};
+
+// Triggered if data changed on the controller
+struct UpdateCallback {
+    std::function<void()> on_change;
+};
+
+// Triggered if data changed on the controller and the engine is on configuring mode
+struct MappingCallback {
+    std::function<void(MappingData)> on_data;
+};
+
+// Input Identifier of data source
+struct InputIdentifier {
+    PadIdentifier identifier;
+    EngineInputType type;
+    std::size_t index;
+    UpdateCallback callback;
+};
+
+class InputEngine {
+public:
+    explicit InputEngine(const std::string& input_engine_) : input_engine(input_engine_) {
+        callback_list.clear();
+    }
+
+    virtual ~InputEngine() = default;
+
+    // Enable configuring mode for mapping
+    void BeginConfiguration();
+
+    // Disable configuring mode for mapping
+    void EndConfiguration();
+
+    // Sets rumble to a controller
+    virtual bool SetRumble([[maybe_unused]] const PadIdentifier& identifier,
+                           [[maybe_unused]] const Input::VibrationStatus vibration) {
+        return false;
+    }
+
+    // Sets a led pattern for a controller
+    virtual void SetLeds([[maybe_unused]] const PadIdentifier& identifier,
+                         [[maybe_unused]] const Input::LedStatus led_status) {
+        return;
+    }
+
+    // Returns the engine name
+    [[nodiscard]] const std::string& GetEngineName() const;
+
+    /// Used for automapping features
+    virtual std::vector<Common::ParamPackage> GetInputDevices() const {
+        return {};
+    };
+
+    /// Retrieves the button mappings for the given device
+    virtual InputCommon::ButtonMapping GetButtonMappingForDevice(
+        [[maybe_unused]] const Common::ParamPackage& params) {
+        return {};
+    };
+
+    /// Retrieves the analog mappings for the given device
+    virtual InputCommon::AnalogMapping GetAnalogMappingForDevice(
+        [[maybe_unused]] const Common::ParamPackage& params) {
+        return {};
+    };
+
+    /// Retrieves the motion mappings for the given device
+    virtual InputCommon::MotionMapping GetMotionMappingForDevice(
+        [[maybe_unused]] const Common::ParamPackage& params) {
+        return {};
+    };
+
+    /// Retrieves the name of the given input.
+    virtual std::string GetUIName([[maybe_unused]] const Common::ParamPackage& params) const {
+        return GetEngineName();
+    };
+
+    /// Retrieves the index number of the given hat button direction
+    virtual u8 GetHatButtonId([[maybe_unused]] const std::string direction_name) const {
+        return 0;
+    };
+
+    void PreSetController(const PadIdentifier& identifier);
+    void PreSetButton(const PadIdentifier& identifier, int button);
+    void PreSetHatButton(const PadIdentifier& identifier, int button);
+    void PreSetAxis(const PadIdentifier& identifier, int axis);
+    void PreSetMotion(const PadIdentifier& identifier, int motion);
+    void ResetButtonState();
+    void ResetAnalogState();
+
+    bool GetButton(const PadIdentifier& identifier, int button) const;
+    bool GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const;
+    f32 GetAxis(const PadIdentifier& identifier, int axis) const;
+    BatteryLevel GetBattery(const PadIdentifier& identifier) const;
+    BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const;
+
+    int SetCallback(InputIdentifier input_identifier);
+    void SetMappingCallback(MappingCallback callback);
+    void DeleteCallback(int key);
+
+protected:
+    void SetButton(const PadIdentifier& identifier, int button, bool value);
+    void SetHatButton(const PadIdentifier& identifier, int button, u8 value);
+    void SetAxis(const PadIdentifier& identifier, int axis, f32 value);
+    void SetBattery(const PadIdentifier& identifier, BatteryLevel value);
+    void SetMotion(const PadIdentifier& identifier, int motion, BasicMotion value);
+
+    virtual std::string GetHatButtonName([[maybe_unused]] u8 direction_value) const {
+        return "Unknown";
+    }
+
+private:
+    struct ControllerData {
+        std::unordered_map<int, bool> buttons;
+        std::unordered_map<int, u8> hat_buttons;
+        std::unordered_map<int, float> axes;
+        std::unordered_map<int, BasicMotion> motions;
+        BatteryLevel battery;
+    };
+
+    void TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value);
+    void TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value);
+    void TriggerOnAxisChange(const PadIdentifier& identifier, int button, f32 value);
+    void TriggerOnBatteryChange(const PadIdentifier& identifier, BatteryLevel value);
+    void TriggerOnMotionChange(const PadIdentifier& identifier, int motion, BasicMotion value);
+
+    bool IsInputIdentifierEqual(const InputIdentifier& input_identifier,
+                                const PadIdentifier& identifier, EngineInputType type,
+                                std::size_t index) const;
+
+    mutable std::mutex mutex;
+    mutable std::mutex mutex_callback;
+    bool configuring{false};
+    bool is_callback_enabled{true};
+    const std::string input_engine;
+    int last_callback_key = 0;
+    std::unordered_map<PadIdentifier, ControllerData> controller_list;
+    std::unordered_map<int, InputIdentifier> callback_list;
+    MappingCallback mapping_callback;
+};
+
+} // namespace InputCommon

From 854c933716f0f5e1dbf62157c5a76e65213b30b2 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 16:41:15 -0500
Subject: [PATCH 05/88] input_common: Create input poller and mapping

---
 src/input_common/CMakeLists.txt    |   6 +
 src/input_common/input_mapping.cpp | 171 ++++++
 src/input_common/input_mapping.h   |  76 +++
 src/input_common/input_poller.cpp  | 860 +++++++++++++++++++++++++++++
 src/input_common/input_poller.h    | 189 +++++++
 src/input_common/main.h            |   3 +
 6 files changed, 1305 insertions(+)
 create mode 100644 src/input_common/input_mapping.cpp
 create mode 100644 src/input_common/input_mapping.h
 create mode 100644 src/input_common/input_poller.cpp
 create mode 100644 src/input_common/input_poller.h

diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index dd13d948f7..72f1e0f4ad 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -3,6 +3,12 @@ add_library(input_common STATIC
     analog_from_button.h
     keyboard.cpp
     keyboard.h
+    input_engine.cpp
+    input_engine.h
+    input_mapping.cpp
+    input_mapping.h
+    input_poller.cpp
+    input_poller.h
     main.cpp
     main.h
     motion_from_button.cpp
diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp
new file mode 100644
index 0000000000..0ffc710281
--- /dev/null
+++ b/src/input_common/input_mapping.cpp
@@ -0,0 +1,171 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#include "common/common_types.h"
+#include "input_common/input_engine.h"
+#include "input_common/input_mapping.h"
+
+namespace InputCommon {
+
+MappingFactory::MappingFactory() {}
+
+void MappingFactory::BeginMapping(Polling::InputType type) {
+    is_enabled = true;
+    input_type = type;
+    input_queue.Clear();
+    first_axis = -1;
+    second_axis = -1;
+}
+
+[[nodiscard]] const Common::ParamPackage MappingFactory::GetNextInput() {
+    Common::ParamPackage input;
+    input_queue.Pop(input);
+    return input;
+}
+
+void MappingFactory::RegisterInput(const MappingData& data) {
+    if (!is_enabled) {
+        return;
+    }
+    switch (input_type) {
+    case Polling::InputType::Button:
+        RegisterButton(data);
+        return;
+    case Polling::InputType::Stick:
+        RegisterStick(data);
+        return;
+    case Polling::InputType::Motion:
+        RegisterMotion(data);
+        return;
+    default:
+        return;
+    }
+}
+
+void MappingFactory::StopMapping() {
+    is_enabled = false;
+    input_type = Polling::InputType::None;
+    input_queue.Clear();
+}
+
+void MappingFactory::RegisterButton(const MappingData& data) {
+    Common::ParamPackage new_input;
+    new_input.Set("engine", data.engine);
+    if (data.pad.guid != Common::UUID{}) {
+        new_input.Set("guid", data.pad.guid.Format());
+    }
+    new_input.Set("port", static_cast<int>(data.pad.port));
+    new_input.Set("pad", static_cast<int>(data.pad.pad));
+    switch (data.type) {
+    case EngineInputType::Button:
+        // Workaround for old compatibility
+        if (data.engine == "keyboard") {
+            new_input.Set("code", data.index);
+            break;
+        }
+        new_input.Set("button", data.index);
+        break;
+    case EngineInputType::HatButton:
+        new_input.Set("hat", data.index);
+        new_input.Set("direction", data.hat_name);
+        break;
+    case EngineInputType::Analog:
+        new_input.Set("axis", data.index);
+        new_input.Set("threshold", 0.5f);
+        break;
+    default:
+        return;
+    }
+    input_queue.Push(new_input);
+}
+
+void MappingFactory::RegisterStick(const MappingData& data) {
+    Common::ParamPackage new_input;
+    new_input.Set("engine", data.engine);
+    if (data.pad.guid != Common::UUID{}) {
+        new_input.Set("guid", data.pad.guid.Format());
+    }
+    new_input.Set("port", static_cast<int>(data.pad.port));
+    new_input.Set("pad", static_cast<int>(data.pad.pad));
+
+    // If engine is mouse map the mouse position as a joystick
+    if (data.engine == "mouse") {
+        new_input.Set("axis_x", 0);
+        new_input.Set("axis_y", 1);
+        new_input.Set("threshold", 0.5f);
+        new_input.Set("range", 1.0f);
+        new_input.Set("deadzone", 0.0f);
+        input_queue.Push(new_input);
+        return;
+    }
+
+    switch (data.type) {
+    case EngineInputType::Button:
+    case EngineInputType::HatButton:
+        RegisterButton(data);
+        return;
+    case EngineInputType::Analog:
+        if (first_axis == data.index) {
+            return;
+        }
+        if (first_axis == -1) {
+            first_axis = data.index;
+            return;
+        }
+        new_input.Set("axis_x", first_axis);
+        new_input.Set("axis_y", data.index);
+        new_input.Set("threshold", 0.5f);
+        new_input.Set("range", 0.95f);
+        new_input.Set("deadzone", 0.15f);
+        break;
+    default:
+        return;
+    }
+    input_queue.Push(new_input);
+}
+
+void MappingFactory::RegisterMotion(const MappingData& data) {
+    Common::ParamPackage new_input;
+    new_input.Set("engine", data.engine);
+    if (data.pad.guid != Common::UUID{}) {
+        new_input.Set("guid", data.pad.guid.Format());
+    }
+    new_input.Set("port", static_cast<int>(data.pad.port));
+    new_input.Set("pad", static_cast<int>(data.pad.pad));
+    switch (data.type) {
+    case EngineInputType::Button:
+    case EngineInputType::HatButton:
+        RegisterButton(data);
+        return;
+    case EngineInputType::Analog:
+        if (first_axis == data.index) {
+            return;
+        }
+        if (second_axis == data.index) {
+            return;
+        }
+        if (first_axis == -1) {
+            first_axis = data.index;
+            return;
+        }
+        if (second_axis == -1) {
+            second_axis = data.index;
+            return;
+        }
+        new_input.Set("axis_x", first_axis);
+        new_input.Set("axis_y", second_axis);
+        new_input.Set("axis_z", data.index);
+        new_input.Set("range", 1.0f);
+        new_input.Set("deadzone", 0.20f);
+        break;
+    case EngineInputType::Motion:
+        new_input.Set("motion", data.index);
+        break;
+    default:
+        return;
+    }
+    input_queue.Push(new_input);
+}
+
+} // namespace InputCommon
diff --git a/src/input_common/input_mapping.h b/src/input_common/input_mapping.h
new file mode 100644
index 0000000000..2622dba70c
--- /dev/null
+++ b/src/input_common/input_mapping.h
@@ -0,0 +1,76 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#pragma once
+#include "common/threadsafe_queue.h"
+
+namespace InputCommon {
+class InputEngine;
+struct MappingData;
+
+class MappingFactory {
+public:
+    MappingFactory();
+
+    /**
+     * Resets all varables to beggin the mapping process
+     * @param "type": type of input desired to be returned
+     */
+    void BeginMapping(Polling::InputType type);
+
+    /// Returns an input event with mapping information from the input_queue
+    [[nodiscard]] const Common::ParamPackage GetNextInput();
+
+    /**
+     * Registers mapping input data from the driver
+     * @param "data": An struct containing all the information needed to create a proper
+     * ParamPackage
+     */
+    void RegisterInput(const MappingData& data);
+
+    /// Stop polling from all backends
+    void StopMapping();
+
+private:
+    /**
+     * If provided data satisfies the requeriments it will push an element to the input_queue
+     * Supported input:
+     *     - Button: Creates a basic button ParamPackage
+     *     - HatButton: Creates a basic hat button ParamPackage
+     *     - Analog: Creates a basic analog ParamPackage
+     * @param "data": An struct containing all the information needed to create a proper
+     * ParamPackage
+     */
+    void RegisterButton(const MappingData& data);
+
+    /**
+     * If provided data satisfies the requeriments it will push an element to the input_queue
+     * Supported input:
+     *     - Button, HatButton: Pass the data to RegisterButton
+     *     - Analog: Stores the first axis and on the second axis creates a basic stick ParamPackage
+     * @param "data": An struct containing all the information needed to create a proper
+     * ParamPackage
+     */
+    void RegisterStick(const MappingData& data);
+
+    /**
+     * If provided data satisfies the requeriments it will push an element to the input_queue
+     * Supported input:
+     *     - Button, HatButton: Pass the data to RegisterButton
+     *     - Analog: Stores the first two axis and on the third axis creates a basic Motion
+     * ParamPackage
+     *     - Motion: Creates a basic Motion ParamPackage
+     * @param "data": An struct containing all the information needed to create a proper
+     * ParamPackage
+     */
+    void RegisterMotion(const MappingData& data);
+
+    Common::SPSCQueue<Common::ParamPackage> input_queue;
+    Polling::InputType input_type{Polling::InputType::None};
+    bool is_enabled{};
+    int first_axis = -1;
+    int second_axis = -1;
+};
+
+} // namespace InputCommon
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
new file mode 100644
index 0000000000..46a7dd2761
--- /dev/null
+++ b/src/input_common/input_poller.cpp
@@ -0,0 +1,860 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#include "common/common_types.h"
+#include "common/input.h"
+
+#include "input_common/input_engine.h"
+#include "input_common/input_poller.h"
+
+namespace InputCommon {
+
+class DummyInput final : public Input::InputDevice {
+public:
+    explicit DummyInput() {}
+    ~DummyInput() {}
+};
+
+class InputFromButton final : public Input::InputDevice {
+public:
+    explicit InputFromButton(PadIdentifier identifier_, u32 button_, bool toggle_, bool inverted_,
+                             InputEngine* input_engine_)
+        : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_),
+          input_engine(input_engine_) {
+        UpdateCallback engine_callback{[this]() { OnChange(); }};
+        const InputIdentifier input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Button,
+            .index = button,
+            .callback = engine_callback,
+        };
+        last_button_value = false;
+        callback_key = input_engine->SetCallback(input_identifier);
+    }
+
+    ~InputFromButton() {
+        input_engine->DeleteCallback(callback_key);
+    }
+
+    Input::ButtonStatus GetStatus() const {
+        return {
+            .value = input_engine->GetButton(identifier, button),
+            .inverted = inverted,
+            .toggle = toggle,
+        };
+    }
+
+    void OnChange() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Button,
+            .button_status = GetStatus(),
+        };
+
+        if (status.button_status.value != last_button_value) {
+            last_button_value = status.button_status.value;
+            TriggerOnChange(status);
+        }
+    }
+
+private:
+    const PadIdentifier identifier;
+    const u32 button;
+    const bool toggle;
+    const bool inverted;
+    int callback_key;
+    bool last_button_value;
+    InputEngine* input_engine;
+};
+
+class InputFromHatButton final : public Input::InputDevice {
+public:
+    explicit InputFromHatButton(PadIdentifier identifier_, u32 button_, u8 direction_, bool toggle_,
+                                bool inverted_, InputEngine* input_engine_)
+        : identifier(identifier_), button(button_), direction(direction_), toggle(toggle_),
+          inverted(inverted_), input_engine(input_engine_) {
+        UpdateCallback engine_callback{[this]() { OnChange(); }};
+        const InputIdentifier input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::HatButton,
+            .index = button,
+            .callback = engine_callback,
+        };
+        last_button_value = false;
+        callback_key = input_engine->SetCallback(input_identifier);
+    }
+
+    ~InputFromHatButton() {
+        input_engine->DeleteCallback(callback_key);
+    }
+
+    Input::ButtonStatus GetStatus() const {
+        return {
+            .value = input_engine->GetHatButton(identifier, button, direction),
+            .inverted = inverted,
+            .toggle = toggle,
+        };
+    }
+
+    void OnChange() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Button,
+            .button_status = GetStatus(),
+        };
+
+        if (status.button_status.value != last_button_value) {
+            last_button_value = status.button_status.value;
+            TriggerOnChange(status);
+        }
+    }
+
+private:
+    const PadIdentifier identifier;
+    const u32 button;
+    const u8 direction;
+    const bool toggle;
+    const bool inverted;
+    int callback_key;
+    bool last_button_value;
+    InputEngine* input_engine;
+};
+
+class InputFromStick final : public Input::InputDevice {
+public:
+    explicit InputFromStick(PadIdentifier identifier_, u32 axis_x_, u32 axis_y_,
+                            Input::AnalogProperties properties_x_,
+                            Input::AnalogProperties properties_y_, InputEngine* input_engine_)
+        : identifier(identifier_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_),
+          properties_y(properties_y_), input_engine(input_engine_) {
+        UpdateCallback engine_callback{[this]() { OnChange(); }};
+        const InputIdentifier x_input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Analog,
+            .index = axis_x,
+            .callback = engine_callback,
+        };
+        const InputIdentifier y_input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Analog,
+            .index = axis_y,
+            .callback = engine_callback,
+        };
+        last_axis_x_value = 0.0f;
+        last_axis_y_value = 0.0f;
+        callback_key_x = input_engine->SetCallback(x_input_identifier);
+        callback_key_y = input_engine->SetCallback(y_input_identifier);
+    }
+
+    ~InputFromStick() {
+        input_engine->DeleteCallback(callback_key_x);
+        input_engine->DeleteCallback(callback_key_y);
+    }
+
+    Input::StickStatus GetStatus() const {
+        Input::StickStatus status;
+        status.x = {
+            .raw_value = input_engine->GetAxis(identifier, axis_x),
+            .properties = properties_x,
+        };
+        status.y = {
+            .raw_value = input_engine->GetAxis(identifier, axis_y),
+            .properties = properties_y,
+        };
+        return status;
+    }
+
+    void OnChange() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Stick,
+            .stick_status = GetStatus(),
+        };
+
+        if (status.stick_status.x.raw_value != last_axis_x_value ||
+            status.stick_status.y.raw_value != last_axis_y_value) {
+            last_axis_x_value = status.stick_status.x.raw_value;
+            last_axis_y_value = status.stick_status.y.raw_value;
+            TriggerOnChange(status);
+        }
+    }
+
+private:
+    const PadIdentifier identifier;
+    const u32 axis_x;
+    const u32 axis_y;
+    const Input::AnalogProperties properties_x;
+    const Input::AnalogProperties properties_y;
+    int callback_key_x;
+    int callback_key_y;
+    float last_axis_x_value;
+    float last_axis_y_value;
+    InputEngine* input_engine;
+};
+
+class InputFromTouch final : public Input::InputDevice {
+public:
+    explicit InputFromTouch(PadIdentifier identifier_, u32 touch_id_, u32 button_, bool toggle_,
+                            bool inverted_, u32 axis_x_, u32 axis_y_,
+                            Input::AnalogProperties properties_x_,
+                            Input::AnalogProperties properties_y_, InputEngine* input_engine_)
+        : identifier(identifier_), touch_id(touch_id_), button(button_), toggle(toggle_),
+          inverted(inverted_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_),
+          properties_y(properties_y_), input_engine(input_engine_) {
+        UpdateCallback engine_callback{[this]() { OnChange(); }};
+        const InputIdentifier button_input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Button,
+            .index = button,
+            .callback = engine_callback,
+        };
+        const InputIdentifier x_input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Analog,
+            .index = axis_x,
+            .callback = engine_callback,
+        };
+        const InputIdentifier y_input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Analog,
+            .index = axis_y,
+            .callback = engine_callback,
+        };
+        last_axis_x_value = 0.0f;
+        last_axis_y_value = 0.0f;
+        last_button_value = false;
+        callback_key_button = input_engine->SetCallback(button_input_identifier);
+        callback_key_x = input_engine->SetCallback(x_input_identifier);
+        callback_key_y = input_engine->SetCallback(y_input_identifier);
+    }
+
+    ~InputFromTouch() {
+        input_engine->DeleteCallback(callback_key_button);
+        input_engine->DeleteCallback(callback_key_x);
+        input_engine->DeleteCallback(callback_key_y);
+    }
+
+    Input::TouchStatus GetStatus() const {
+        Input::TouchStatus status;
+        status.id = touch_id;
+        status.pressed = {
+            .value = input_engine->GetButton(identifier, button),
+            .inverted = inverted,
+            .toggle = toggle,
+        };
+        status.x = {
+            .raw_value = input_engine->GetAxis(identifier, axis_x),
+            .properties = properties_x,
+        };
+        status.y = {
+            .raw_value = input_engine->GetAxis(identifier, axis_y),
+            .properties = properties_y,
+        };
+        return status;
+    }
+
+    void OnChange() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Touch,
+            .touch_status = GetStatus(),
+        };
+
+        if (status.touch_status.x.raw_value != last_axis_x_value ||
+            status.touch_status.y.raw_value != last_axis_y_value ||
+            status.touch_status.pressed.value != last_button_value) {
+            last_axis_x_value = status.touch_status.x.raw_value;
+            last_axis_y_value = status.touch_status.y.raw_value;
+            last_button_value = status.touch_status.pressed.value;
+            TriggerOnChange(status);
+        }
+    }
+
+private:
+    const PadIdentifier identifier;
+    const u32 touch_id;
+    const u32 button;
+    const bool toggle;
+    const bool inverted;
+    const u32 axis_x;
+    const u32 axis_y;
+    const Input::AnalogProperties properties_x;
+    const Input::AnalogProperties properties_y;
+    int callback_key_button;
+    int callback_key_x;
+    int callback_key_y;
+    bool last_button_value;
+    float last_axis_x_value;
+    float last_axis_y_value;
+    InputEngine* input_engine;
+};
+
+class InputFromTrigger final : public Input::InputDevice {
+public:
+    explicit InputFromTrigger(PadIdentifier identifier_, u32 button_, bool toggle_, bool inverted_,
+                              u32 axis_, Input::AnalogProperties properties_,
+                              InputEngine* input_engine_)
+        : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_),
+          axis(axis_), properties(properties_), input_engine(input_engine_) {
+        UpdateCallback engine_callback{[this]() { OnChange(); }};
+        const InputIdentifier button_input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Button,
+            .index = button,
+            .callback = engine_callback,
+        };
+        const InputIdentifier axis_input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Analog,
+            .index = axis,
+            .callback = engine_callback,
+        };
+        last_axis_value = 0.0f;
+        last_button_value = false;
+        callback_key_button = input_engine->SetCallback(button_input_identifier);
+        axis_callback_key = input_engine->SetCallback(axis_input_identifier);
+    }
+
+    ~InputFromTrigger() {
+        input_engine->DeleteCallback(callback_key_button);
+        input_engine->DeleteCallback(axis_callback_key);
+    }
+
+    Input::TriggerStatus GetStatus() const {
+        const Input::AnalogStatus analog_status{
+            .raw_value = input_engine->GetAxis(identifier, axis),
+            .properties = properties,
+        };
+        return {
+            .analog = analog_status,
+            .pressed = input_engine->GetButton(identifier, button),
+        };
+    }
+
+    void OnChange() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Trigger,
+            .trigger_status = GetStatus(),
+        };
+
+        if (status.trigger_status.analog.raw_value != last_axis_value ||
+            status.trigger_status.pressed != last_button_value) {
+            last_axis_value = status.trigger_status.analog.raw_value;
+            last_button_value = status.trigger_status.pressed;
+            TriggerOnChange(status);
+        }
+    }
+
+private:
+    const PadIdentifier identifier;
+    const u32 button;
+    const bool toggle;
+    const bool inverted;
+    const u32 axis;
+    const Input::AnalogProperties properties;
+    int callback_key_button;
+    int axis_callback_key;
+    bool last_button_value;
+    float last_axis_value;
+    InputEngine* input_engine;
+};
+
+class InputFromAnalog final : public Input::InputDevice {
+public:
+    explicit InputFromAnalog(PadIdentifier identifier_, u32 axis_,
+                             Input::AnalogProperties properties_, InputEngine* input_engine_)
+        : identifier(identifier_), axis(axis_), properties(properties_),
+          input_engine(input_engine_) {
+        UpdateCallback engine_callback{[this]() { OnChange(); }};
+        const InputIdentifier input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Analog,
+            .index = axis,
+            .callback = engine_callback,
+        };
+        last_axis_value = 0.0f;
+        callback_key = input_engine->SetCallback(input_identifier);
+    }
+
+    ~InputFromAnalog() {
+        input_engine->DeleteCallback(callback_key);
+    }
+
+    Input::AnalogStatus GetStatus() const {
+        return {
+            .raw_value = input_engine->GetAxis(identifier, axis),
+            .properties = properties,
+        };
+    }
+
+    void OnChange() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Analog,
+            .analog_status = GetStatus(),
+        };
+
+        if (status.analog_status.raw_value != last_axis_value) {
+            last_axis_value = status.analog_status.raw_value;
+            TriggerOnChange(status);
+        }
+    }
+
+private:
+    const PadIdentifier identifier;
+    const u32 axis;
+    const Input::AnalogProperties properties;
+    int callback_key;
+    float last_axis_value;
+    InputEngine* input_engine;
+};
+
+class InputFromBattery final : public Input::InputDevice {
+public:
+    explicit InputFromBattery(PadIdentifier identifier_, InputEngine* input_engine_)
+        : identifier(identifier_), input_engine(input_engine_) {
+        UpdateCallback engine_callback{[this]() { OnChange(); }};
+        const InputIdentifier input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Battery,
+            .index = 0,
+            .callback = engine_callback,
+        };
+        last_battery_value = Input::BatteryStatus::Charging;
+        callback_key = input_engine->SetCallback(input_identifier);
+    }
+
+    ~InputFromBattery() {
+        input_engine->DeleteCallback(callback_key);
+    }
+
+    Input::BatteryStatus GetStatus() const {
+        return static_cast<Input::BatteryLevel>(input_engine->GetBattery(identifier));
+    }
+
+    void OnChange() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Battery,
+            .battery_status = GetStatus(),
+        };
+
+        if (status.battery_status != last_battery_value) {
+            last_battery_value = status.battery_status;
+            TriggerOnChange(status);
+        }
+    }
+
+private:
+    const PadIdentifier identifier;
+    int callback_key;
+    Input::BatteryStatus last_battery_value;
+    InputEngine* input_engine;
+};
+
+class InputFromMotion final : public Input::InputDevice {
+public:
+    explicit InputFromMotion(PadIdentifier identifier_, u32 motion_sensor_,
+                             InputEngine* input_engine_)
+        : identifier(identifier_), motion_sensor(motion_sensor_), input_engine(input_engine_) {
+        UpdateCallback engine_callback{[this]() { OnChange(); }};
+        const InputIdentifier input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Motion,
+            .index = motion_sensor,
+            .callback = engine_callback,
+        };
+        callback_key = input_engine->SetCallback(input_identifier);
+    }
+
+    ~InputFromMotion() {
+        input_engine->DeleteCallback(callback_key);
+    }
+
+    Input::MotionStatus GetStatus() const {
+        const auto basic_motion = input_engine->GetMotion(identifier, motion_sensor);
+        Input::MotionStatus status{};
+        const Input::AnalogProperties properties = {
+            .deadzone = 0.001f,
+            .range = 1.0f,
+            .offset = 0.0f,
+        };
+        status.accel.x = {.raw_value = basic_motion.accel_x, .properties = properties};
+        status.accel.y = {.raw_value = basic_motion.accel_y, .properties = properties};
+        status.accel.z = {.raw_value = basic_motion.accel_z, .properties = properties};
+        status.gyro.x = {.raw_value = basic_motion.gyro_x, .properties = properties};
+        status.gyro.y = {.raw_value = basic_motion.gyro_y, .properties = properties};
+        status.gyro.z = {.raw_value = basic_motion.gyro_z, .properties = properties};
+        status.delta_timestamp = basic_motion.delta_timestamp;
+        return status;
+    }
+
+    void OnChange() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Motion,
+            .motion_status = GetStatus(),
+        };
+
+        TriggerOnChange(status);
+    }
+
+private:
+    const PadIdentifier identifier;
+    const u32 motion_sensor;
+    int callback_key;
+    InputEngine* input_engine;
+};
+
+class InputFromAxisMotion final : public Input::InputDevice {
+public:
+    explicit InputFromAxisMotion(PadIdentifier identifier_, u32 axis_x_, u32 axis_y_, u32 axis_z_,
+                                 Input::AnalogProperties properties_x_,
+                                 Input::AnalogProperties properties_y_,
+                                 Input::AnalogProperties properties_z_, InputEngine* input_engine_)
+        : identifier(identifier_), axis_x(axis_x_), axis_y(axis_y_), axis_z(axis_z_),
+          properties_x(properties_x_), properties_y(properties_y_), properties_z(properties_z_),
+          input_engine(input_engine_) {
+        UpdateCallback engine_callback{[this]() { OnChange(); }};
+        const InputIdentifier x_input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Analog,
+            .index = axis_x,
+            .callback = engine_callback,
+        };
+        const InputIdentifier y_input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Analog,
+            .index = axis_y,
+            .callback = engine_callback,
+        };
+        const InputIdentifier z_input_identifier{
+            .identifier = identifier,
+            .type = EngineInputType::Analog,
+            .index = axis_z,
+            .callback = engine_callback,
+        };
+        last_axis_x_value = 0.0f;
+        last_axis_y_value = 0.0f;
+        last_axis_z_value = 0.0f;
+        callback_key_x = input_engine->SetCallback(x_input_identifier);
+        callback_key_y = input_engine->SetCallback(y_input_identifier);
+        callback_key_z = input_engine->SetCallback(z_input_identifier);
+    }
+
+    ~InputFromAxisMotion() {
+        input_engine->DeleteCallback(callback_key_x);
+        input_engine->DeleteCallback(callback_key_y);
+        input_engine->DeleteCallback(callback_key_z);
+    }
+
+    Input::MotionStatus GetStatus() const {
+        Input::MotionStatus status{};
+        status.gyro.x = {
+            .raw_value = input_engine->GetAxis(identifier, axis_x),
+            .properties = properties_x,
+        };
+        status.gyro.y = {
+            .raw_value = input_engine->GetAxis(identifier, axis_y),
+            .properties = properties_y,
+        };
+        status.gyro.z = {
+            .raw_value = input_engine->GetAxis(identifier, axis_z),
+            .properties = properties_z,
+        };
+        return status;
+    }
+
+    void OnChange() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Motion,
+            .motion_status = GetStatus(),
+        };
+
+        if (status.motion_status.gyro.x.raw_value != last_axis_x_value ||
+            status.motion_status.gyro.y.raw_value != last_axis_y_value ||
+            status.motion_status.gyro.z.raw_value != last_axis_z_value) {
+            last_axis_x_value = status.motion_status.gyro.x.raw_value;
+            last_axis_y_value = status.motion_status.gyro.y.raw_value;
+            last_axis_z_value = status.motion_status.gyro.z.raw_value;
+            TriggerOnChange(status);
+        }
+    }
+
+private:
+    const PadIdentifier identifier;
+    const u32 axis_x;
+    const u32 axis_y;
+    const u32 axis_z;
+    const Input::AnalogProperties properties_x;
+    const Input::AnalogProperties properties_y;
+    const Input::AnalogProperties properties_z;
+    int callback_key_x;
+    int callback_key_y;
+    int callback_key_z;
+    float last_axis_x_value;
+    float last_axis_y_value;
+    float last_axis_z_value;
+    InputEngine* input_engine;
+};
+
+std::unique_ptr<Input::InputDevice> InputFactory::CreateButtonDevice(
+    const Common::ParamPackage& params) {
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{params.Get("guid", "")},
+        .port = static_cast<std::size_t>(params.Get("port", 0)),
+        .pad = static_cast<std::size_t>(params.Get("pad", 0)),
+    };
+
+    const auto button_id = static_cast<u32>(params.Get("button", 0));
+    const auto keyboard_key = static_cast<u32>(params.Get("code", 0));
+    const auto toggle = params.Get("toggle", false);
+    const auto inverted = params.Get("inverted", false);
+    input_engine->PreSetController(identifier);
+    input_engine->PreSetButton(identifier, button_id);
+    input_engine->PreSetButton(identifier, keyboard_key);
+    if (keyboard_key != 0) {
+        return std::make_unique<InputFromButton>(identifier, keyboard_key, toggle, inverted,
+                                                 input_engine.get());
+    }
+    return std::make_unique<InputFromButton>(identifier, button_id, toggle, inverted,
+                                             input_engine.get());
+}
+
+std::unique_ptr<Input::InputDevice> InputFactory::CreateHatButtonDevice(
+    const Common::ParamPackage& params) {
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{params.Get("guid", "")},
+        .port = static_cast<std::size_t>(params.Get("port", 0)),
+        .pad = static_cast<std::size_t>(params.Get("pad", 0)),
+    };
+
+    const auto button_id = static_cast<u32>(params.Get("hat", 0));
+    const auto direction = input_engine->GetHatButtonId(params.Get("direction", ""));
+    const auto toggle = params.Get("toggle", false);
+    const auto inverted = params.Get("inverted", false);
+
+    input_engine->PreSetController(identifier);
+    input_engine->PreSetHatButton(identifier, button_id);
+    return std::make_unique<InputFromHatButton>(identifier, button_id, direction, toggle, inverted,
+                                                input_engine.get());
+}
+
+std::unique_ptr<Input::InputDevice> InputFactory::CreateStickDevice(
+    const Common::ParamPackage& params) {
+    const auto deadzone = std::clamp(params.Get("deadzone", 0.15f), 0.0f, 1.0f);
+    const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f);
+    const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f);
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{params.Get("guid", "")},
+        .port = static_cast<std::size_t>(params.Get("port", 0)),
+        .pad = static_cast<std::size_t>(params.Get("pad", 0)),
+    };
+
+    const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
+    const Input::AnalogProperties properties_x = {
+        .deadzone = deadzone,
+        .range = range,
+        .threshold = threshold,
+        .offset = std::clamp(params.Get("offset_x", 0.0f), -1.0f, 1.0f),
+        .inverted = params.Get("invert_x", "+") == "-",
+    };
+
+    const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
+    const Input::AnalogProperties properties_y = {
+        .deadzone = deadzone,
+        .range = range,
+        .threshold = threshold,
+        .offset = std::clamp(params.Get("offset_y", 0.0f), -1.0f, 1.0f),
+        .inverted = params.Get("invert_y", "+") != "+",
+    };
+    input_engine->PreSetController(identifier);
+    input_engine->PreSetAxis(identifier, axis_x);
+    input_engine->PreSetAxis(identifier, axis_y);
+    return std::make_unique<InputFromStick>(identifier, axis_x, axis_y, properties_x, properties_y,
+                                            input_engine.get());
+}
+
+std::unique_ptr<Input::InputDevice> InputFactory::CreateAnalogDevice(
+    const Common::ParamPackage& params) {
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{params.Get("guid", "")},
+        .port = static_cast<std::size_t>(params.Get("port", 0)),
+        .pad = static_cast<std::size_t>(params.Get("pad", 0)),
+    };
+
+    const auto axis = static_cast<u32>(params.Get("axis", 0));
+    const Input::AnalogProperties properties = {
+        .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f),
+        .range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f),
+        .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f),
+        .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f),
+        .inverted = params.Get("invert", "+") == "-",
+    };
+    input_engine->PreSetController(identifier);
+    input_engine->PreSetAxis(identifier, axis);
+    return std::make_unique<InputFromAnalog>(identifier, axis, properties, input_engine.get());
+}
+
+std::unique_ptr<Input::InputDevice> InputFactory::CreateTriggerDevice(
+    const Common::ParamPackage& params) {
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{params.Get("guid", "")},
+        .port = static_cast<std::size_t>(params.Get("port", 0)),
+        .pad = static_cast<std::size_t>(params.Get("pad", 0)),
+    };
+
+    const auto button = static_cast<u32>(params.Get("button", 0));
+    const auto toggle = params.Get("toggle", false);
+    const auto inverted = params.Get("inverted", false);
+
+    const auto axis = static_cast<u32>(params.Get("axis", 0));
+    const Input::AnalogProperties properties = {
+        .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f),
+        .range = std::clamp(params.Get("range", 1.0f), 0.25f, 2.50f),
+        .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f),
+        .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f),
+        .inverted = params.Get("invert", false) != 0,
+    };
+    input_engine->PreSetController(identifier);
+    input_engine->PreSetAxis(identifier, axis);
+    input_engine->PreSetButton(identifier, button);
+    return std::make_unique<InputFromTrigger>(identifier, button, toggle, inverted, axis,
+                                              properties, input_engine.get());
+}
+
+std::unique_ptr<Input::InputDevice> InputFactory::CreateTouchDevice(
+    const Common::ParamPackage& params) {
+    const auto touch_id = params.Get("touch_id", 0);
+    const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
+    const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f);
+    const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f);
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{params.Get("guid", "")},
+        .port = static_cast<std::size_t>(params.Get("port", 0)),
+        .pad = static_cast<std::size_t>(params.Get("pad", 0)),
+    };
+
+    const auto button = static_cast<u32>(params.Get("button", 0));
+    const auto toggle = params.Get("toggle", false);
+    const auto inverted = params.Get("inverted", false);
+
+    const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
+    const Input::AnalogProperties properties_x = {
+        .deadzone = deadzone,
+        .range = range,
+        .threshold = threshold,
+        .offset = std::clamp(params.Get("offset_x", 0.0f), -1.0f, 1.0f),
+        .inverted = params.Get("invert_x", "+") == "-",
+    };
+
+    const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
+    const Input::AnalogProperties properties_y = {
+        .deadzone = deadzone,
+        .range = range,
+        .threshold = threshold,
+        .offset = std::clamp(params.Get("offset_y", 0.0f), -1.0f, 1.0f),
+        .inverted = params.Get("invert_y", false) != 0,
+    };
+    input_engine->PreSetController(identifier);
+    input_engine->PreSetAxis(identifier, axis_x);
+    input_engine->PreSetAxis(identifier, axis_y);
+    input_engine->PreSetButton(identifier, button);
+    return std::make_unique<InputFromTouch>(identifier, touch_id, button, toggle, inverted, axis_x,
+                                            axis_y, properties_x, properties_y, input_engine.get());
+}
+
+std::unique_ptr<Input::InputDevice> InputFactory::CreateBatteryDevice(
+    const Common::ParamPackage& params) {
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{params.Get("guid", "")},
+        .port = static_cast<std::size_t>(params.Get("port", 0)),
+        .pad = static_cast<std::size_t>(params.Get("pad", 0)),
+    };
+
+    input_engine->PreSetController(identifier);
+    return std::make_unique<InputFromBattery>(identifier, input_engine.get());
+}
+
+std::unique_ptr<Input::InputDevice> InputFactory::CreateMotionDevice(Common::ParamPackage params) {
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{params.Get("guid", "")},
+        .port = static_cast<std::size_t>(params.Get("port", 0)),
+        .pad = static_cast<std::size_t>(params.Get("pad", 0)),
+    };
+
+    if (params.Has("motion")) {
+        const auto motion_sensor = params.Get("motion", 0);
+        input_engine->PreSetController(identifier);
+        input_engine->PreSetMotion(identifier, motion_sensor);
+        return std::make_unique<InputFromMotion>(identifier, motion_sensor, input_engine.get());
+    }
+
+    const auto deadzone = std::clamp(params.Get("deadzone", 0.15f), 0.0f, 1.0f);
+    const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f);
+    const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f);
+
+    const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
+    const Input::AnalogProperties properties_x = {
+        .deadzone = deadzone,
+        .range = range,
+        .threshold = threshold,
+        .offset = std::clamp(params.Get("offset_x", 0.0f), -1.0f, 1.0f),
+        .inverted = params.Get("invert_x", "+") == "-",
+    };
+
+    const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
+    const Input::AnalogProperties properties_y = {
+        .deadzone = deadzone,
+        .range = range,
+        .threshold = threshold,
+        .offset = std::clamp(params.Get("offset_y", 0.0f), -1.0f, 1.0f),
+        .inverted = params.Get("invert_y", "+") != "+",
+    };
+
+    const auto axis_z = static_cast<u32>(params.Get("axis_z", 1));
+    const Input::AnalogProperties properties_z = {
+        .deadzone = deadzone,
+        .range = range,
+        .threshold = threshold,
+        .offset = std::clamp(params.Get("offset_z", 0.0f), -1.0f, 1.0f),
+        .inverted = params.Get("invert_z", "+") != "+",
+    };
+    input_engine->PreSetController(identifier);
+    input_engine->PreSetAxis(identifier, axis_x);
+    input_engine->PreSetAxis(identifier, axis_y);
+    input_engine->PreSetAxis(identifier, axis_z);
+    return std::make_unique<InputFromAxisMotion>(identifier, axis_x, axis_y, axis_z, properties_x,
+                                                 properties_y, properties_z, input_engine.get());
+}
+
+InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_)
+    : input_engine(std::move(input_engine_)) {}
+
+std::unique_ptr<Input::InputDevice> InputFactory::Create(const Common::ParamPackage& params) {
+    if (params.Has("button") && params.Has("axis")) {
+        return CreateTriggerDevice(params);
+    }
+    if (params.Has("button") && params.Has("axis_x") && params.Has("axis_y")) {
+        return CreateTouchDevice(params);
+    }
+    if (params.Has("button") || params.Has("code")) {
+        return CreateButtonDevice(params);
+    }
+    if (params.Has("hat")) {
+        return CreateHatButtonDevice(params);
+    }
+    if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) {
+        return CreateMotionDevice(params);
+    }
+    if (params.Has("motion")) {
+        return CreateMotionDevice(params);
+    }
+    if (params.Has("axis_x") && params.Has("axis_y")) {
+        return CreateStickDevice(params);
+    }
+    if (params.Has("axis")) {
+        return CreateAnalogDevice(params);
+    }
+    if (params.Has("battery")) {
+        return CreateBatteryDevice(params);
+    }
+    LOG_ERROR(Input, "Invalid parameters given");
+    return std::make_unique<DummyInput>();
+}
+
+} // namespace InputCommon
diff --git a/src/input_common/input_poller.h b/src/input_common/input_poller.h
new file mode 100644
index 0000000000..3c1e5b541f
--- /dev/null
+++ b/src/input_common/input_poller.h
@@ -0,0 +1,189 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#pragma once
+
+namespace Input {
+class InputDevice;
+
+template <typename InputDevice>
+class Factory;
+}; // namespace Input
+
+namespace InputCommon {
+class InputEngine;
+/**
+ * An Input factory. It receives input events and forward them to all input devices it created.
+ */
+class InputFactory final : public Input::Factory<Input::InputDevice> {
+public:
+    explicit InputFactory(std::shared_ptr<InputEngine> input_engine_);
+
+    /**
+     * Creates a input device from the parameters given. Identifies the type of input to be returned
+     * if it contains the following parameters:
+     * - button: Contains "button" or "code"
+     * - hat_button: Contains "hat"
+     * - analog: Contains "axis"
+     * - trigger: Contains "button" and  "axis"
+     * - stick: Contains "axis_x" and "axis_y"
+     * - motion: Contains "axis_x", "axis_y" and "axis_z"
+     * - motion: Contains "motion"
+     * - touch: Contains "button", "axis_x" and "axis_y"
+     * - battery: Contains "battery"
+     * @param params contains parameters for creating the device:
+     * @param    - "code": the code of the keyboard key to bind with the input
+     * @param    - "button": same as "code" but for controller buttons
+     * @param    - "hat": similar as "button" but it's a group of hat buttons from SDL
+     * @param    - "axis": the axis number of the axis to bind with the input
+     * @param    - "motion": the motion number of the motion to bind with the input
+     * @param    - "axis_x": same as axis but specifing horizontal direction
+     * @param    - "axis_y": same as axis but specifing vertical direction
+     * @param    - "axis_z": same as axis but specifing forward direction
+     * @param   - "battery": Only used as a placeholder to set the input type
+     * @return an unique input device with the parameters specified
+     */
+    std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
+
+private:
+    /**
+     * Creates a button device from the parameters given.
+     * @param params contains parameters for creating the device:
+     * @param    - "code": the code of the keyboard key to bind with the input
+     * @param    - "button": same as "code" but for controller buttons
+     * @param    - "toggle": press once to enable, press again to disable
+     * @param    - "inverted": inverts the output of the button
+     * @param    - "guid": text string for identifing controllers
+     * @param    - "port": port of the connected device
+     * @param    - "pad": slot of the connected controller
+     * @return an unique input device with the parameters specified
+     */
+    std::unique_ptr<Input::InputDevice> CreateButtonDevice(const Common::ParamPackage& params);
+
+    /**
+     * Creates a hat button device from the parameters given.
+     * @param params contains parameters for creating the device:
+     * @param    - "button": the controller hat id to bind with the input
+     * @param    - "direction": the direction id to be detected
+     * @param    - "toggle": press once to enable, press again to disable
+     * @param    - "inverted": inverts the output of the button
+     * @param    - "guid": text string for identifing controllers
+     * @param    - "port": port of the connected device
+     * @param    - "pad": slot of the connected controller
+     * @return an unique input device with the parameters specified
+     */
+    std::unique_ptr<Input::InputDevice> CreateHatButtonDevice(const Common::ParamPackage& params);
+
+    /**
+     * Creates a stick device from the parameters given.
+     * @param params contains parameters for creating the device:
+     * @param    - "axis_x": the controller horizontal axis id to bind with the input
+     * @param    - "axis_y": the controller vertical axis id to bind with the input
+     * @param    - "deadzone": the mimimum required value to be detected
+     * @param    - "range": the maximum value required to reach 100%
+     * @param    - "threshold": the mimimum required value to considered pressed
+     * @param    - "offset_x": the amount of offset in the x axis
+     * @param    - "offset_y": the amount of offset in the y axis
+     * @param    - "invert_x": inverts the sign of the horizontal axis
+     * @param    - "invert_y": inverts the sign of the vertical axis
+     * @param    - "guid": text string for identifing controllers
+     * @param    - "port": port of the connected device
+     * @param    - "pad": slot of the connected controller
+     * @return an unique input device with the parameters specified
+     */
+    std::unique_ptr<Input::InputDevice> CreateStickDevice(const Common::ParamPackage& params);
+
+    /**
+     * Creates an analog device from the parameters given.
+     * @param params contains parameters for creating the device:
+     * @param    - "axis": the controller axis id to bind with the input
+     * @param    - "deadzone": the mimimum required value to be detected
+     * @param    - "range": the maximum value required to reach 100%
+     * @param    - "threshold": the mimimum required value to considered pressed
+     * @param    - "offset": the amount of offset in the axis
+     * @param    - "invert": inverts the sign of the axis
+     * @param    - "guid": text string for identifing controllers
+     * @param    - "port": port of the connected device
+     * @param    - "pad": slot of the connected controller
+     * @return an unique input device with the parameters specified
+     */
+    std::unique_ptr<Input::InputDevice> CreateAnalogDevice(const Common::ParamPackage& params);
+
+    /**
+     * Creates a trigger device from the parameters given.
+     * @param params contains parameters for creating the device:
+     * @param    - "button": the controller hat id to bind with the input
+     * @param    - "direction": the direction id to be detected
+     * @param    - "toggle": press once to enable, press again to disable
+     * @param    - "inverted": inverts the output of the button
+     * @param    - "axis": the controller axis id to bind with the input
+     * @param    - "deadzone": the mimimum required value to be detected
+     * @param    - "range": the maximum value required to reach 100%
+     * @param    - "threshold": the mimimum required value to considered pressed
+     * @param    - "offset": the amount of offset in the axis
+     * @param    - "invert": inverts the sign of the axis
+     * @param    - "guid": text string for identifing controllers
+     * @param    - "port": port of the connected device
+     * @param    - "pad": slot of the connected controller
+     * @return an unique input device with the parameters specified
+     */
+    std::unique_ptr<Input::InputDevice> CreateTriggerDevice(const Common::ParamPackage& params);
+
+    /**
+     * Creates a touch device from the parameters given.
+     * @param params contains parameters for creating the device:
+     * @param    - "button": the controller hat id to bind with the input
+     * @param    - "direction": the direction id to be detected
+     * @param    - "toggle": press once to enable, press again to disable
+     * @param    - "inverted": inverts the output of the button
+     * @param    - "axis_x": the controller horizontal axis id to bind with the input
+     * @param    - "axis_y": the controller vertical axis id to bind with the input
+     * @param    - "deadzone": the mimimum required value to be detected
+     * @param    - "range": the maximum value required to reach 100%
+     * @param    - "threshold": the mimimum required value to considered pressed
+     * @param    - "offset_x": the amount of offset in the x axis
+     * @param    - "offset_y": the amount of offset in the y axis
+     * @param    - "invert_x": inverts the sign of the horizontal axis
+     * @param    - "invert_y": inverts the sign of the vertical axis
+     * @param    - "guid": text string for identifing controllers
+     * @param    - "port": port of the connected device
+     * @param    - "pad": slot of the connected controller
+     * @return an unique input device with the parameters specified
+     */
+    std::unique_ptr<Input::InputDevice> CreateTouchDevice(const Common::ParamPackage& params);
+
+    /**
+     * Creates a battery device from the parameters given.
+     * @param params contains parameters for creating the device:
+     * @param    - "guid": text string for identifing controllers
+     * @param    - "port": port of the connected device
+     * @param    - "pad": slot of the connected controller
+     * @return an unique input device with the parameters specified
+     */
+    std::unique_ptr<Input::InputDevice> CreateBatteryDevice(const Common::ParamPackage& params);
+
+    /**
+     * Creates a motion device from the parameters given.
+     * @param params contains parameters for creating the device:
+     * @param    - "axis_x": the controller horizontal axis id to bind with the input
+     * @param    - "axis_y": the controller vertical axis id to bind with the input
+     * @param    - "axis_z": the controller fordward axis id to bind with the input
+     * @param    - "deadzone": the mimimum required value to be detected
+     * @param    - "range": the maximum value required to reach 100%
+     * @param    - "offset_x": the amount of offset in the x axis
+     * @param    - "offset_y": the amount of offset in the y axis
+     * @param    - "offset_z": the amount of offset in the z axis
+     * @param    - "invert_x": inverts the sign of the horizontal axis
+     * @param    - "invert_y": inverts the sign of the vertical axis
+     * @param    - "invert_z": inverts the sign of the fordward axis
+     * @param    - "guid": text string for identifing controllers
+     * @param    - "port": port of the connected device
+     * @param    - "pad": slot of the connected controller
+     * @return an unique input device with the parameters specified
+     */
+    std::unique_ptr<Input::InputDevice> CreateMotionDevice(Common::ParamPackage params);
+
+    std::shared_ptr<InputEngine> input_engine;
+};
+} // namespace InputCommon
diff --git a/src/input_common/main.h b/src/input_common/main.h
index 6390d3f094..eb247e1641 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -38,6 +38,9 @@ namespace Polling {
 
 enum class DeviceType { Button, AnalogPreferred, Motion };
 
+/// Type of input desired for mapping purposes
+enum class InputType { None, Button, Stick, Motion, Touch };
+
 /**
  * A class that can be used to get inputs from an input device like controllers without having to
  * poll the device's status yourself

From 4c6f2c2547e1d97f12ebe708fac693a6183bbc45 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 16:57:55 -0500
Subject: [PATCH 06/88] input_common: Move touch and analog from button. Move
 udp protocol

---
 src/input_common/CMakeLists.txt               |  12 +-
 .../stick_from_buttons.cpp}                   | 144 +++++++++++-------
 .../stick_from_buttons.h}                     |   8 +-
 .../helpers/touch_from_buttons.cpp            |  70 +++++++++
 .../touch_from_buttons.h}                     |   7 +-
 .../protocol.cpp => helpers/udp_protocol.cpp} |   2 +-
 .../protocol.h => helpers/udp_protocol.h}     |   0
 src/input_common/main.cpp                     |   8 -
 src/input_common/touch_from_button.cpp        |  53 -------
 src/input_common/udp/client.cpp               |   2 +-
 10 files changed, 173 insertions(+), 133 deletions(-)
 rename src/input_common/{analog_from_button.cpp => helpers/stick_from_buttons.cpp} (56%)
 mode change 100755 => 100644
 rename src/input_common/{analog_from_button.h => helpers/stick_from_buttons.h} (82%)
 mode change 100755 => 100644
 create mode 100644 src/input_common/helpers/touch_from_buttons.cpp
 rename src/input_common/{touch_from_button.h => helpers/touch_from_buttons.h} (68%)
 rename src/input_common/{udp/protocol.cpp => helpers/udp_protocol.cpp} (98%)
 rename src/input_common/{udp/protocol.h => helpers/udp_protocol.h} (100%)
 delete mode 100644 src/input_common/touch_from_button.cpp

diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 72f1e0f4ad..90e7618cee 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -1,8 +1,12 @@
 add_library(input_common STATIC
-    analog_from_button.cpp
-    analog_from_button.h
     keyboard.cpp
     keyboard.h
+    helpers/stick_from_buttons.cpp
+    helpers/stick_from_buttons.h
+    helpers/touch_from_buttons.cpp
+    helpers/touch_from_buttons.h
+    helpers/udp_protocol.cpp
+    helpers/udp_protocol.h
     input_engine.cpp
     input_engine.h
     input_mapping.cpp
@@ -15,8 +19,6 @@ add_library(input_common STATIC
     motion_from_button.h
     motion_input.cpp
     motion_input.h
-    touch_from_button.cpp
-    touch_from_button.h
     gcadapter/gc_adapter.cpp
     gcadapter/gc_adapter.h
     gcadapter/gc_poller.cpp
@@ -33,8 +35,6 @@ add_library(input_common STATIC
     tas/tas_poller.h
     udp/client.cpp
     udp/client.h
-    udp/protocol.cpp
-    udp/protocol.h
     udp/udp.cpp
     udp/udp.h
 )
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/helpers/stick_from_buttons.cpp
old mode 100755
new mode 100644
similarity index 56%
rename from src/input_common/analog_from_button.cpp
rename to src/input_common/helpers/stick_from_buttons.cpp
index 2fafd077f7..38f1507462
--- a/src/input_common/analog_from_button.cpp
+++ b/src/input_common/helpers/stick_from_buttons.cpp
@@ -2,32 +2,38 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include <atomic>
 #include <chrono>
 #include <cmath>
-#include <thread>
 #include "common/math_util.h"
 #include "common/settings.h"
-#include "input_common/analog_from_button.h"
+#include "input_common/helpers/stick_from_buttons.h"
 
 namespace InputCommon {
 
-class Analog final : public Input::AnalogDevice {
+class Stick final : public Input::InputDevice {
 public:
-    using Button = std::unique_ptr<Input::ButtonDevice>;
+    using Button = std::unique_ptr<Input::InputDevice>;
 
-    Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_,
-           float modifier_scale_, float modifier_angle_)
+    Stick(Button up_, Button down_, Button left_, Button right_, Button modifier_,
+          float modifier_scale_, float modifier_angle_)
         : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)),
           right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_),
           modifier_angle(modifier_angle_) {
-        Input::InputCallback<bool> callbacks{
-            [this]([[maybe_unused]] bool status) { UpdateStatus(); }};
-        up->SetCallback(callbacks);
-        down->SetCallback(callbacks);
-        left->SetCallback(callbacks);
-        right->SetCallback(callbacks);
-        modifier->SetCallback(callbacks);
+        Input::InputCallback button_up_callback{
+            [this](Input::CallbackStatus callback_) { UpdateUpButtonStatus(callback_); }};
+        Input::InputCallback button_down_callback{
+            [this](Input::CallbackStatus callback_) { UpdateDownButtonStatus(callback_); }};
+        Input::InputCallback button_left_callback{
+            [this](Input::CallbackStatus callback_) { UpdateLeftButtonStatus(callback_); }};
+        Input::InputCallback button_right_callback{
+            [this](Input::CallbackStatus callback_) { UpdateRightButtonStatus(callback_); }};
+        Input::InputCallback button_modifier_callback{
+            [this](Input::CallbackStatus callback_) { UpdateModButtonStatus(callback_); }};
+        up->SetCallback(button_up_callback);
+        down->SetCallback(button_down_callback);
+        left->SetCallback(button_left_callback);
+        right->SetCallback(button_right_callback);
+        modifier->SetCallback(button_modifier_callback);
     }
 
     bool IsAngleGreater(float old_angle, float new_angle) const {
@@ -123,13 +129,38 @@ public:
         }
     }
 
-    void UpdateStatus() {
-        const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
+    void UpdateUpButtonStatus(Input::CallbackStatus button_callback) {
+        up_status = button_callback.button_status.value;
+        UpdateStatus();
+    }
 
-        bool r = right->GetStatus();
-        bool l = left->GetStatus();
-        bool u = up->GetStatus();
-        bool d = down->GetStatus();
+    void UpdateDownButtonStatus(Input::CallbackStatus button_callback) {
+        down_status = button_callback.button_status.value;
+        UpdateStatus();
+    }
+
+    void UpdateLeftButtonStatus(Input::CallbackStatus button_callback) {
+        left_status = button_callback.button_status.value;
+        UpdateStatus();
+    }
+
+    void UpdateRightButtonStatus(Input::CallbackStatus button_callback) {
+        right_status = button_callback.button_status.value;
+        UpdateStatus();
+    }
+
+    void UpdateModButtonStatus(Input::CallbackStatus button_callback) {
+        modifier_status = button_callback.button_status.value;
+        UpdateStatus();
+    }
+
+    void UpdateStatus() {
+        const float coef = modifier_status ? modifier_scale : 1.0f;
+
+        bool r = right_status;
+        bool l = left_status;
+        bool u = up_status;
+        bool d = down_status;
 
         // Eliminate contradictory movements
         if (r && l) {
@@ -162,49 +193,42 @@ public:
         }
 
         last_update = now;
+        Input::CallbackStatus status{
+            .type = Input::InputType::Stick,
+            .stick_status = GetStatus(),
+        };
+        TriggerOnChange(status);
     }
 
-    std::tuple<float, float> GetStatus() const override {
+    Input::StickStatus GetStatus() const {
+        Input::StickStatus status{};
+        status.x.properties = properties;
+        status.y.properties = properties;
         if (Settings::values.emulate_analog_keyboard) {
             const auto now = std::chrono::steady_clock::now();
             float angle_ = GetAngle(now);
-            return std::make_tuple(std::cos(angle_) * amplitude, std::sin(angle_) * amplitude);
+            status.x.raw_value = std::cos(angle_) * amplitude;
+            status.y.raw_value = std::sin(angle_) * amplitude;
+            return status;
         }
         constexpr float SQRT_HALF = 0.707106781f;
         int x = 0, y = 0;
-        if (right->GetStatus()) {
+        if (right_status) {
             ++x;
         }
-        if (left->GetStatus()) {
+        if (left_status) {
             --x;
         }
-        if (up->GetStatus()) {
+        if (up_status) {
             ++y;
         }
-        if (down->GetStatus()) {
+        if (down_status) {
             --y;
         }
-        const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
-        return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF),
-                               static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF));
-    }
-
-    Input::AnalogProperties GetAnalogProperties() const override {
-        return {modifier_scale, 1.0f, 0.5f};
-    }
-
-    bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
-        switch (direction) {
-        case Input::AnalogDirection::RIGHT:
-            return right->GetStatus();
-        case Input::AnalogDirection::LEFT:
-            return left->GetStatus();
-        case Input::AnalogDirection::UP:
-            return up->GetStatus();
-        case Input::AnalogDirection::DOWN:
-            return down->GetStatus();
-        }
-        return false;
+        const float coef = modifier_status ? modifier_scale : 1.0f;
+        status.x.raw_value = static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF);
+        status.y.raw_value = static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF);
+        return status;
     }
 
 private:
@@ -218,21 +242,29 @@ private:
     float angle{};
     float goal_angle{};
     float amplitude{};
+    bool up_status;
+    bool down_status;
+    bool left_status;
+    bool right_status;
+    bool modifier_status;
+    const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
     std::chrono::time_point<std::chrono::steady_clock> last_update;
 };
 
-std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) {
+std::unique_ptr<Input::InputDevice> StickFromButton::Create(const Common::ParamPackage& params) {
     const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
-    auto up = Input::CreateDevice<Input::ButtonDevice>(params.Get("up", null_engine));
-    auto down = Input::CreateDevice<Input::ButtonDevice>(params.Get("down", null_engine));
-    auto left = Input::CreateDevice<Input::ButtonDevice>(params.Get("left", null_engine));
-    auto right = Input::CreateDevice<Input::ButtonDevice>(params.Get("right", null_engine));
-    auto modifier = Input::CreateDevice<Input::ButtonDevice>(params.Get("modifier", null_engine));
+    auto up = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("up", null_engine));
+    auto down = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("down", null_engine));
+    auto left = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("left", null_engine));
+    auto right =
+        Input::CreateDeviceFromString<Input::InputDevice>(params.Get("right", null_engine));
+    auto modifier =
+        Input::CreateDeviceFromString<Input::InputDevice>(params.Get("modifier", null_engine));
     auto modifier_scale = params.Get("modifier_scale", 0.5f);
     auto modifier_angle = params.Get("modifier_angle", 5.5f);
-    return std::make_unique<Analog>(std::move(up), std::move(down), std::move(left),
-                                    std::move(right), std::move(modifier), modifier_scale,
-                                    modifier_angle);
+    return std::make_unique<Stick>(std::move(up), std::move(down), std::move(left),
+                                   std::move(right), std::move(modifier), modifier_scale,
+                                   modifier_angle);
 }
 
 } // namespace InputCommon
diff --git a/src/input_common/analog_from_button.h b/src/input_common/helpers/stick_from_buttons.h
old mode 100755
new mode 100644
similarity index 82%
rename from src/input_common/analog_from_button.h
rename to src/input_common/helpers/stick_from_buttons.h
index bbd583dd93..1d6e24c98e
--- a/src/input_common/analog_from_button.h
+++ b/src/input_common/helpers/stick_from_buttons.h
@@ -1,11 +1,11 @@
+
 // Copyright 2017 Citra Emulator Project
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
 #pragma once
 
-#include <memory>
-#include "core/frontend/input.h"
+#include "common/input.h"
 
 namespace InputCommon {
 
@@ -13,7 +13,7 @@ namespace InputCommon {
  * An analog device factory that takes direction button devices and combines them into a analog
  * device.
  */
-class AnalogFromButton final : public Input::Factory<Input::AnalogDevice> {
+class StickFromButton final : public Input::Factory<Input::InputDevice> {
 public:
     /**
      * Creates an analog device from direction button devices
@@ -25,7 +25,7 @@ public:
      *     - "modifier": a serialized ParamPackage for creating a button device as the modifier
      *     - "modifier_scale": a float for the multiplier the modifier gives to the position
      */
-    std::unique_ptr<Input::AnalogDevice> Create(const Common::ParamPackage& params) override;
+    std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
 };
 
 } // namespace InputCommon
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp
new file mode 100644
index 0000000000..2abfaf841d
--- /dev/null
+++ b/src/input_common/helpers/touch_from_buttons.cpp
@@ -0,0 +1,70 @@
+// Copyright 2020 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include "common/settings.h"
+#include "core/frontend/framebuffer_layout.h"
+#include "input_common/helpers/touch_from_buttons.h"
+
+namespace InputCommon {
+
+class TouchFromButtonDevice final : public Input::InputDevice {
+public:
+    using Button = std::unique_ptr<Input::InputDevice>;
+    TouchFromButtonDevice(Button button_, u32 touch_id_, float x_, float y_)
+        : button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) {
+        Input::InputCallback button_up_callback{
+            [this](Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }};
+        button->SetCallback(button_up_callback);
+    }
+
+    Input::TouchStatus GetStatus(bool pressed) const {
+        const Input::ButtonStatus button_status{
+            .value = pressed,
+        };
+        Input::TouchStatus status{
+            .pressed = button_status,
+            .x = {},
+            .y = {},
+            .id = touch_id,
+        };
+        status.x.properties = properties;
+        status.y.properties = properties;
+
+        if (!pressed) {
+            return status;
+        }
+
+        status.x.raw_value = x;
+        status.y.raw_value = y;
+        return status;
+    }
+
+    void UpdateButtonStatus(Input::CallbackStatus button_callback) {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Touch,
+            .touch_status = GetStatus(button_callback.button_status.value),
+        };
+        TriggerOnChange(status);
+    }
+
+private:
+    Button button;
+    const u32 touch_id;
+    const float x;
+    const float y;
+    const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
+};
+
+std::unique_ptr<Input::InputDevice> TouchFromButton::Create(const Common::ParamPackage& params) {
+    const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
+    auto button =
+        Input::CreateDeviceFromString<Input::InputDevice>(params.Get("button", null_engine));
+    const auto touch_id = params.Get("touch_id", 0);
+    const float x = params.Get("x", 0.0f) / 1280.0f;
+    const float y = params.Get("y", 0.0f) / 720.0f;
+    return std::make_unique<TouchFromButtonDevice>(std::move(button), touch_id, x, y);
+}
+
+} // namespace InputCommon
diff --git a/src/input_common/touch_from_button.h b/src/input_common/helpers/touch_from_buttons.h
similarity index 68%
rename from src/input_common/touch_from_button.h
rename to src/input_common/helpers/touch_from_buttons.h
index 8b4d1aa961..21b353728a 100644
--- a/src/input_common/touch_from_button.h
+++ b/src/input_common/helpers/touch_from_buttons.h
@@ -4,20 +4,19 @@
 
 #pragma once
 
-#include <memory>
-#include "core/frontend/input.h"
+#include "common/input.h"
 
 namespace InputCommon {
 
 /**
  * A touch device factory that takes a list of button devices and combines them into a touch device.
  */
-class TouchFromButtonFactory final : public Input::Factory<Input::TouchDevice> {
+class TouchFromButton final : public Input::Factory<Input::InputDevice> {
 public:
     /**
      * Creates a touch device from a list of button devices
      */
-    std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override;
+    std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
 };
 
 } // namespace InputCommon
diff --git a/src/input_common/udp/protocol.cpp b/src/input_common/helpers/udp_protocol.cpp
similarity index 98%
rename from src/input_common/udp/protocol.cpp
rename to src/input_common/helpers/udp_protocol.cpp
index 5e50bd6129..cdeab7e118 100644
--- a/src/input_common/udp/protocol.cpp
+++ b/src/input_common/helpers/udp_protocol.cpp
@@ -5,7 +5,7 @@
 #include <cstddef>
 #include <cstring>
 #include "common/logging/log.h"
-#include "input_common/udp/protocol.h"
+#include "input_common/helpers/udp_protocol.h"
 
 namespace InputCommon::CemuhookUDP {
 
diff --git a/src/input_common/udp/protocol.h b/src/input_common/helpers/udp_protocol.h
similarity index 100%
rename from src/input_common/udp/protocol.h
rename to src/input_common/helpers/udp_protocol.h
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index f3907c65ac..7a5c29b400 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -6,7 +6,6 @@
 #include <thread>
 #include "common/param_package.h"
 #include "common/settings.h"
-#include "input_common/analog_from_button.h"
 #include "input_common/gcadapter/gc_adapter.h"
 #include "input_common/gcadapter/gc_poller.h"
 #include "input_common/keyboard.h"
@@ -16,7 +15,6 @@
 #include "input_common/mouse/mouse_poller.h"
 #include "input_common/tas/tas_input.h"
 #include "input_common/tas/tas_poller.h"
-#include "input_common/touch_from_button.h"
 #include "input_common/udp/client.h"
 #include "input_common/udp/udp.h"
 #ifdef HAVE_SDL2
@@ -37,12 +35,8 @@ struct InputSubsystem::Impl {
 
         keyboard = std::make_shared<Keyboard>();
         Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
-        Input::RegisterFactory<Input::AnalogDevice>("analog_from_button",
-                                                    std::make_shared<AnalogFromButton>());
         Input::RegisterFactory<Input::MotionDevice>("keyboard",
                                                     std::make_shared<MotionFromButton>());
-        Input::RegisterFactory<Input::TouchDevice>("touch_from_button",
-                                                   std::make_shared<TouchFromButtonFactory>());
 
 #ifdef HAVE_SDL2
         sdl = SDL::Init();
@@ -75,8 +69,6 @@ struct InputSubsystem::Impl {
         Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
         Input::UnregisterFactory<Input::MotionDevice>("keyboard");
         keyboard.reset();
-        Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button");
-        Input::UnregisterFactory<Input::TouchDevice>("touch_from_button");
 #ifdef HAVE_SDL2
         sdl.reset();
 #endif
diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp
deleted file mode 100644
index 7878a56d77..0000000000
--- a/src/input_common/touch_from_button.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2020 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include "common/settings.h"
-#include "core/frontend/framebuffer_layout.h"
-#include "input_common/touch_from_button.h"
-
-namespace InputCommon {
-
-class TouchFromButtonDevice final : public Input::TouchDevice {
-public:
-    TouchFromButtonDevice() {
-        const auto button_index =
-            static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
-        const auto& buttons = Settings::values.touch_from_button_maps[button_index].buttons;
-
-        for (const auto& config_entry : buttons) {
-            const Common::ParamPackage package{config_entry};
-            map.emplace_back(
-                Input::CreateDevice<Input::ButtonDevice>(config_entry),
-                std::clamp(package.Get("x", 0), 0, static_cast<int>(Layout::ScreenUndocked::Width)),
-                std::clamp(package.Get("y", 0), 0,
-                           static_cast<int>(Layout::ScreenUndocked::Height)));
-        }
-    }
-
-    Input::TouchStatus GetStatus() const override {
-        Input::TouchStatus touch_status{};
-        for (std::size_t id = 0; id < map.size() && id < touch_status.size(); ++id) {
-            const bool state = std::get<0>(map[id])->GetStatus();
-            if (state) {
-                const float x = static_cast<float>(std::get<1>(map[id])) /
-                                static_cast<int>(Layout::ScreenUndocked::Width);
-                const float y = static_cast<float>(std::get<2>(map[id])) /
-                                static_cast<int>(Layout::ScreenUndocked::Height);
-                touch_status[id] = {x, y, true};
-            }
-        }
-        return touch_status;
-    }
-
-private:
-    // A vector of the mapped button, its x and its y-coordinate
-    std::vector<std::tuple<std::unique_ptr<Input::ButtonDevice>, int, int>> map;
-};
-
-std::unique_ptr<Input::TouchDevice> TouchFromButtonFactory::Create(const Common::ParamPackage&) {
-    return std::make_unique<TouchFromButtonDevice>();
-}
-
-} // namespace InputCommon
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index b9512aa2e9..bcc29c4e07 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -11,7 +11,7 @@
 #include "common/logging/log.h"
 #include "common/settings.h"
 #include "input_common/udp/client.h"
-#include "input_common/udp/protocol.h"
+#include "input_common/helpers/udp_protocol.h"
 
 using boost::asio::ip::udp;
 

From 5a785ed794fff8c944283271bf25cb835c11700a Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 17:18:40 -0500
Subject: [PATCH 07/88] input_common: Rewrite keyboard

---
 src/input_common/CMakeLists.txt               |   4 +-
 src/input_common/drivers/keyboard.cpp         |  35 +++
 src/input_common/{ => drivers}/keyboard.h     |  29 +-
 src/input_common/keyboard.cpp                 | 121 --------
 src/input_common/main.cpp                     | 263 +-----------------
 src/input_common/main.h                       |  89 ------
 src/yuzu/bootmanager.cpp                      |  56 ++--
 src/yuzu/bootmanager.h                        |   2 +-
 .../configuration/configure_input_player.cpp  |  83 +-----
 src/yuzu/debugger/controller.cpp              |   3 +-
 src/yuzu/main.cpp                             |  18 +-
 11 files changed, 92 insertions(+), 611 deletions(-)
 create mode 100644 src/input_common/drivers/keyboard.cpp
 rename src/input_common/{ => drivers}/keyboard.h (52%)
 delete mode 100644 src/input_common/keyboard.cpp

diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 90e7618cee..0fcf7a9d7b 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -1,6 +1,6 @@
 add_library(input_common STATIC
-    keyboard.cpp
-    keyboard.h
+    drivers/keyboard.cpp
+    drivers/keyboard.h
     helpers/stick_from_buttons.cpp
     helpers/stick_from_buttons.h
     helpers/touch_from_buttons.cpp
diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp
new file mode 100644
index 0000000000..b00a4b8d95
--- /dev/null
+++ b/src/input_common/drivers/keyboard.cpp
@@ -0,0 +1,35 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#include "common/param_package.h"
+#include "input_common/drivers/keyboard.h"
+
+namespace InputCommon {
+
+Keyboard::Keyboard(const std::string& input_engine_) : InputEngine(input_engine_) {
+    PreSetController(identifier);
+}
+
+void Keyboard::PressKey(int key_code) {
+    SetButton(identifier, key_code, true);
+}
+
+void Keyboard::ReleaseKey(int key_code) {
+    SetButton(identifier, key_code, false);
+}
+
+void Keyboard::ReleaseAllKeys() {
+    ResetButtonState();
+}
+
+std::vector<Common::ParamPackage> Keyboard::GetInputDevices() const {
+    std::vector<Common::ParamPackage> devices;
+    devices.emplace_back(Common::ParamPackage{
+        {"engine", "keyboard"},
+        {"display", "Keyboard Only"},
+    });
+    return devices;
+}
+
+} // namespace InputCommon
diff --git a/src/input_common/keyboard.h b/src/input_common/drivers/keyboard.h
similarity index 52%
rename from src/input_common/keyboard.h
rename to src/input_common/drivers/keyboard.h
index 8619504729..a3e0d8a617 100644
--- a/src/input_common/keyboard.h
+++ b/src/input_common/drivers/keyboard.h
@@ -1,30 +1,20 @@
-// Copyright 2017 Citra Emulator Project
+// Copyright 2021 yuzu Emulator Project
 // Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// Refer to the license.txt file included
 
 #pragma once
 
-#include <memory>
-#include "core/frontend/input.h"
+#include "input_common/input_engine.h"
 
 namespace InputCommon {
 
-class KeyButtonList;
-
 /**
  * A button device factory representing a keyboard. It receives keyboard events and forward them
  * to all button devices it created.
  */
-class Keyboard final : public Input::Factory<Input::ButtonDevice> {
+class Keyboard final : public InputCommon::InputEngine {
 public:
-    Keyboard();
-
-    /**
-     * Creates a button device from a keyboard key
-     * @param params contains parameters for creating the device:
-     *     - "code": the code of the key to bind with the button
-     */
-    std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override;
+    explicit Keyboard(const std::string& input_engine_);
 
     /**
      * Sets the status of all buttons bound with the key to pressed
@@ -40,8 +30,15 @@ public:
 
     void ReleaseAllKeys();
 
+    /// Used for automapping features
+    std::vector<Common::ParamPackage> GetInputDevices() const override;
+
 private:
-    std::shared_ptr<KeyButtonList> key_button_list;
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{""},
+        .port = 0,
+        .pad = 0,
+    };
 };
 
 } // namespace InputCommon
diff --git a/src/input_common/keyboard.cpp b/src/input_common/keyboard.cpp
deleted file mode 100644
index 8261e76fd7..0000000000
--- a/src/input_common/keyboard.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <atomic>
-#include <list>
-#include <mutex>
-#include <utility>
-#include "input_common/keyboard.h"
-
-namespace InputCommon {
-
-class KeyButton final : public Input::ButtonDevice {
-public:
-    explicit KeyButton(std::shared_ptr<KeyButtonList> key_button_list_, bool toggle_)
-        : key_button_list(std::move(key_button_list_)), toggle(toggle_) {}
-
-    ~KeyButton() override;
-
-    bool GetStatus() const override {
-        if (toggle) {
-            return toggled_status.load(std::memory_order_relaxed);
-        }
-        return status.load();
-    }
-
-    void ToggleButton() {
-        if (lock) {
-            return;
-        }
-        lock = true;
-        const bool old_toggle_status = toggled_status.load();
-        toggled_status.store(!old_toggle_status);
-    }
-
-    void UnlockButton() {
-        lock = false;
-    }
-
-    friend class KeyButtonList;
-
-private:
-    std::shared_ptr<KeyButtonList> key_button_list;
-    std::atomic<bool> status{false};
-    std::atomic<bool> toggled_status{false};
-    bool lock{false};
-    const bool toggle;
-};
-
-struct KeyButtonPair {
-    int key_code;
-    KeyButton* key_button;
-};
-
-class KeyButtonList {
-public:
-    void AddKeyButton(int key_code, KeyButton* key_button) {
-        std::lock_guard guard{mutex};
-        list.push_back(KeyButtonPair{key_code, key_button});
-    }
-
-    void RemoveKeyButton(const KeyButton* key_button) {
-        std::lock_guard guard{mutex};
-        list.remove_if(
-            [key_button](const KeyButtonPair& pair) { return pair.key_button == key_button; });
-    }
-
-    void ChangeKeyStatus(int key_code, bool pressed) {
-        std::lock_guard guard{mutex};
-        for (const KeyButtonPair& pair : list) {
-            if (pair.key_code == key_code) {
-                pair.key_button->status.store(pressed);
-                if (pressed) {
-                    pair.key_button->ToggleButton();
-                } else {
-                    pair.key_button->UnlockButton();
-                }
-                pair.key_button->TriggerOnChange();
-            }
-        }
-    }
-
-    void ChangeAllKeyStatus(bool pressed) {
-        std::lock_guard guard{mutex};
-        for (const KeyButtonPair& pair : list) {
-            pair.key_button->status.store(pressed);
-        }
-    }
-
-private:
-    std::mutex mutex;
-    std::list<KeyButtonPair> list;
-};
-
-Keyboard::Keyboard() : key_button_list{std::make_shared<KeyButtonList>()} {}
-
-KeyButton::~KeyButton() {
-    key_button_list->RemoveKeyButton(this);
-}
-
-std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage& params) {
-    const int key_code = params.Get("code", 0);
-    const bool toggle = params.Get("toggle", false);
-    std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list, toggle);
-    key_button_list->AddKeyButton(key_code, button.get());
-    return button;
-}
-
-void Keyboard::PressKey(int key_code) {
-    key_button_list->ChangeKeyStatus(key_code, true);
-}
-
-void Keyboard::ReleaseKey(int key_code) {
-    key_button_list->ChangeKeyStatus(key_code, false);
-}
-
-void Keyboard::ReleaseAllKeys() {
-    key_button_list->ChangeAllKeyStatus(false);
-}
-
-} // namespace InputCommon
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 7a5c29b400..da501b6ccb 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -6,17 +6,7 @@
 #include <thread>
 #include "common/param_package.h"
 #include "common/settings.h"
-#include "input_common/gcadapter/gc_adapter.h"
-#include "input_common/gcadapter/gc_poller.h"
-#include "input_common/keyboard.h"
 #include "input_common/main.h"
-#include "input_common/motion_from_button.h"
-#include "input_common/mouse/mouse_input.h"
-#include "input_common/mouse/mouse_poller.h"
-#include "input_common/tas/tas_input.h"
-#include "input_common/tas/tas_poller.h"
-#include "input_common/udp/client.h"
-#include "input_common/udp/udp.h"
 #ifdef HAVE_SDL2
 #include "input_common/sdl/sdl.h"
 #endif
@@ -25,82 +15,9 @@ namespace InputCommon {
 
 struct InputSubsystem::Impl {
     void Initialize() {
-        gcadapter = std::make_shared<GCAdapter::Adapter>();
-        gcbuttons = std::make_shared<GCButtonFactory>(gcadapter);
-        Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons);
-        gcanalog = std::make_shared<GCAnalogFactory>(gcadapter);
-        Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog);
-        gcvibration = std::make_shared<GCVibrationFactory>(gcadapter);
-        Input::RegisterFactory<Input::VibrationDevice>("gcpad", gcvibration);
-
-        keyboard = std::make_shared<Keyboard>();
-        Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
-        Input::RegisterFactory<Input::MotionDevice>("keyboard",
-                                                    std::make_shared<MotionFromButton>());
-
-#ifdef HAVE_SDL2
-        sdl = SDL::Init();
-#endif
-
-        udp = std::make_shared<InputCommon::CemuhookUDP::Client>();
-        udpmotion = std::make_shared<UDPMotionFactory>(udp);
-        Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", udpmotion);
-        udptouch = std::make_shared<UDPTouchFactory>(udp);
-        Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", udptouch);
-
-        mouse = std::make_shared<MouseInput::Mouse>();
-        mousebuttons = std::make_shared<MouseButtonFactory>(mouse);
-        Input::RegisterFactory<Input::ButtonDevice>("mouse", mousebuttons);
-        mouseanalog = std::make_shared<MouseAnalogFactory>(mouse);
-        Input::RegisterFactory<Input::AnalogDevice>("mouse", mouseanalog);
-        mousemotion = std::make_shared<MouseMotionFactory>(mouse);
-        Input::RegisterFactory<Input::MotionDevice>("mouse", mousemotion);
-        mousetouch = std::make_shared<MouseTouchFactory>(mouse);
-        Input::RegisterFactory<Input::TouchDevice>("mouse", mousetouch);
-
-        tas = std::make_shared<TasInput::Tas>();
-        tasbuttons = std::make_shared<TasButtonFactory>(tas);
-        Input::RegisterFactory<Input::ButtonDevice>("tas", tasbuttons);
-        tasanalog = std::make_shared<TasAnalogFactory>(tas);
-        Input::RegisterFactory<Input::AnalogDevice>("tas", tasanalog);
     }
 
     void Shutdown() {
-        Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
-        Input::UnregisterFactory<Input::MotionDevice>("keyboard");
-        keyboard.reset();
-#ifdef HAVE_SDL2
-        sdl.reset();
-#endif
-        Input::UnregisterFactory<Input::ButtonDevice>("gcpad");
-        Input::UnregisterFactory<Input::AnalogDevice>("gcpad");
-        Input::UnregisterFactory<Input::VibrationDevice>("gcpad");
-
-        gcbuttons.reset();
-        gcanalog.reset();
-        gcvibration.reset();
-
-        Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
-        Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp");
-
-        udpmotion.reset();
-        udptouch.reset();
-
-        Input::UnregisterFactory<Input::ButtonDevice>("mouse");
-        Input::UnregisterFactory<Input::AnalogDevice>("mouse");
-        Input::UnregisterFactory<Input::MotionDevice>("mouse");
-        Input::UnregisterFactory<Input::TouchDevice>("mouse");
-
-        mousebuttons.reset();
-        mouseanalog.reset();
-        mousemotion.reset();
-        mousetouch.reset();
-
-        Input::UnregisterFactory<Input::ButtonDevice>("tas");
-        Input::UnregisterFactory<Input::AnalogDevice>("tas");
-
-        tasbuttons.reset();
-        tasanalog.reset();
     }
 
     [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
@@ -108,19 +25,7 @@ struct InputSubsystem::Impl {
             Common::ParamPackage{{"display", "Any"}, {"class", "any"}},
             Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "keyboard"}},
         };
-        if (Settings::values.tas_enable) {
-            devices.emplace_back(
-                Common::ParamPackage{{"display", "TAS Controller"}, {"class", "tas"}});
-        }
-#ifdef HAVE_SDL2
-        auto sdl_devices = sdl->GetInputDevices();
-        devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
-#endif
-        auto udp_devices = udp->GetInputDevices();
-        devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
-        auto gcpad_devices = gcadapter->GetInputDevices();
-        devices.insert(devices.end(), gcpad_devices.begin(), gcpad_devices.end());
-        return devices;
+        return {};
     }
 
     [[nodiscard]] AnalogMapping GetAnalogMappingForDevice(
@@ -128,17 +33,6 @@ struct InputSubsystem::Impl {
         if (!params.Has("class") || params.Get("class", "") == "any") {
             return {};
         }
-        if (params.Get("class", "") == "gcpad") {
-            return gcadapter->GetAnalogMappingForDevice(params);
-        }
-        if (params.Get("class", "") == "tas") {
-            return tas->GetAnalogMappingForDevice(params);
-        }
-#ifdef HAVE_SDL2
-        if (params.Get("class", "") == "sdl") {
-            return sdl->GetAnalogMappingForDevice(params);
-        }
-#endif
         return {};
     }
 
@@ -147,17 +41,6 @@ struct InputSubsystem::Impl {
         if (!params.Has("class") || params.Get("class", "") == "any") {
             return {};
         }
-        if (params.Get("class", "") == "gcpad") {
-            return gcadapter->GetButtonMappingForDevice(params);
-        }
-        if (params.Get("class", "") == "tas") {
-            return tas->GetButtonMappingForDevice(params);
-        }
-#ifdef HAVE_SDL2
-        if (params.Get("class", "") == "sdl") {
-            return sdl->GetButtonMappingForDevice(params);
-        }
-#endif
         return {};
     }
 
@@ -166,37 +49,9 @@ struct InputSubsystem::Impl {
         if (!params.Has("class") || params.Get("class", "") == "any") {
             return {};
         }
-        if (params.Get("class", "") == "cemuhookudp") {
-            // TODO return the correct motion device
-            return {};
-        }
-#ifdef HAVE_SDL2
-        if (params.Get("class", "") == "sdl") {
-            return sdl->GetMotionMappingForDevice(params);
-        }
-#endif
         return {};
     }
 
-    std::shared_ptr<Keyboard> keyboard;
-#ifdef HAVE_SDL2
-    std::unique_ptr<SDL::State> sdl;
-#endif
-    std::shared_ptr<GCButtonFactory> gcbuttons;
-    std::shared_ptr<GCAnalogFactory> gcanalog;
-    std::shared_ptr<GCVibrationFactory> gcvibration;
-    std::shared_ptr<UDPMotionFactory> udpmotion;
-    std::shared_ptr<UDPTouchFactory> udptouch;
-    std::shared_ptr<MouseButtonFactory> mousebuttons;
-    std::shared_ptr<MouseAnalogFactory> mouseanalog;
-    std::shared_ptr<MouseMotionFactory> mousemotion;
-    std::shared_ptr<MouseTouchFactory> mousetouch;
-    std::shared_ptr<TasButtonFactory> tasbuttons;
-    std::shared_ptr<TasAnalogFactory> tasanalog;
-    std::shared_ptr<CemuhookUDP::Client> udp;
-    std::shared_ptr<GCAdapter::Adapter> gcadapter;
-    std::shared_ptr<MouseInput::Mouse> mouse;
-    std::shared_ptr<TasInput::Tas> tas;
 };
 
 InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {}
@@ -211,30 +66,6 @@ void InputSubsystem::Shutdown() {
     impl->Shutdown();
 }
 
-Keyboard* InputSubsystem::GetKeyboard() {
-    return impl->keyboard.get();
-}
-
-const Keyboard* InputSubsystem::GetKeyboard() const {
-    return impl->keyboard.get();
-}
-
-MouseInput::Mouse* InputSubsystem::GetMouse() {
-    return impl->mouse.get();
-}
-
-const MouseInput::Mouse* InputSubsystem::GetMouse() const {
-    return impl->mouse.get();
-}
-
-TasInput::Tas* InputSubsystem::GetTas() {
-    return impl->tas.get();
-}
-
-const TasInput::Tas* InputSubsystem::GetTas() const {
-    return impl->tas.get();
-}
-
 std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const {
     return impl->GetInputDevices();
 }
@@ -251,100 +82,12 @@ MotionMapping InputSubsystem::GetMotionMappingForDevice(const Common::ParamPacka
     return impl->GetMotionMappingForDevice(device);
 }
 
-GCAnalogFactory* InputSubsystem::GetGCAnalogs() {
-    return impl->gcanalog.get();
-}
-
-const GCAnalogFactory* InputSubsystem::GetGCAnalogs() const {
-    return impl->gcanalog.get();
-}
-
-GCButtonFactory* InputSubsystem::GetGCButtons() {
-    return impl->gcbuttons.get();
-}
-
-const GCButtonFactory* InputSubsystem::GetGCButtons() const {
-    return impl->gcbuttons.get();
-}
-
-UDPMotionFactory* InputSubsystem::GetUDPMotions() {
-    return impl->udpmotion.get();
-}
-
-const UDPMotionFactory* InputSubsystem::GetUDPMotions() const {
-    return impl->udpmotion.get();
-}
-
-UDPTouchFactory* InputSubsystem::GetUDPTouch() {
-    return impl->udptouch.get();
-}
-
-const UDPTouchFactory* InputSubsystem::GetUDPTouch() const {
-    return impl->udptouch.get();
-}
-
-MouseButtonFactory* InputSubsystem::GetMouseButtons() {
-    return impl->mousebuttons.get();
-}
-
-const MouseButtonFactory* InputSubsystem::GetMouseButtons() const {
-    return impl->mousebuttons.get();
-}
-
-MouseAnalogFactory* InputSubsystem::GetMouseAnalogs() {
-    return impl->mouseanalog.get();
-}
-
-const MouseAnalogFactory* InputSubsystem::GetMouseAnalogs() const {
-    return impl->mouseanalog.get();
-}
-
-MouseMotionFactory* InputSubsystem::GetMouseMotions() {
-    return impl->mousemotion.get();
-}
-
-const MouseMotionFactory* InputSubsystem::GetMouseMotions() const {
-    return impl->mousemotion.get();
-}
-
-MouseTouchFactory* InputSubsystem::GetMouseTouch() {
-    return impl->mousetouch.get();
-}
-
-const MouseTouchFactory* InputSubsystem::GetMouseTouch() const {
-    return impl->mousetouch.get();
-}
-
-TasButtonFactory* InputSubsystem::GetTasButtons() {
-    return impl->tasbuttons.get();
-}
-
-const TasButtonFactory* InputSubsystem::GetTasButtons() const {
-    return impl->tasbuttons.get();
-}
-
-TasAnalogFactory* InputSubsystem::GetTasAnalogs() {
-    return impl->tasanalog.get();
-}
-
-const TasAnalogFactory* InputSubsystem::GetTasAnalogs() const {
-    return impl->tasanalog.get();
-}
-
 void InputSubsystem::ReloadInputDevices() {
-    if (!impl->udp) {
-        return;
-    }
-    impl->udp->ReloadSockets();
 }
 
-std::vector<std::unique_ptr<Polling::DevicePoller>> InputSubsystem::GetPollers(
-    [[maybe_unused]] Polling::DeviceType type) const {
-#ifdef HAVE_SDL2
-    return impl->sdl->GetPollers(type);
-#else
+std::vector<std::unique_ptr<Polling::DevicePoller>> InputSubsystem::GetPollers([
+    [maybe_unused]] Polling::DeviceType type) const {
     return {};
-#endif
 }
 
 std::string GenerateKeyboardParam(int key_code) {
diff --git a/src/input_common/main.h b/src/input_common/main.h
index eb247e1641..b504ebe54a 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -63,18 +63,6 @@ public:
 };
 } // namespace Polling
 
-class GCAnalogFactory;
-class GCButtonFactory;
-class UDPMotionFactory;
-class UDPTouchFactory;
-class MouseButtonFactory;
-class MouseAnalogFactory;
-class MouseMotionFactory;
-class MouseTouchFactory;
-class TasButtonFactory;
-class TasAnalogFactory;
-class Keyboard;
-
 /**
  * Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default
  * mapping for the device. This is currently only implemented for the SDL backend devices.
@@ -100,23 +88,6 @@ public:
     /// Unregisters all built-in input device factories and shuts them down.
     void Shutdown();
 
-    /// Retrieves the underlying keyboard device.
-    [[nodiscard]] Keyboard* GetKeyboard();
-
-    /// Retrieves the underlying keyboard device.
-    [[nodiscard]] const Keyboard* GetKeyboard() const;
-
-    /// Retrieves the underlying mouse device.
-    [[nodiscard]] MouseInput::Mouse* GetMouse();
-
-    /// Retrieves the underlying mouse device.
-    [[nodiscard]] const MouseInput::Mouse* GetMouse() const;
-
-    /// Retrieves the underlying tas device.
-    [[nodiscard]] TasInput::Tas* GetTas();
-
-    /// Retrieves the underlying tas device.
-    [[nodiscard]] const TasInput::Tas* GetTas() const;
     /**
      * Returns all available input devices that this Factory can create a new device with.
      * Each returned ParamPackage should have a `display` field used for display, a class field for
@@ -134,66 +105,6 @@ public:
     /// Retrieves the motion mappings for the given device.
     [[nodiscard]] MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& device) const;
 
-    /// Retrieves the underlying GameCube analog handler.
-    [[nodiscard]] GCAnalogFactory* GetGCAnalogs();
-
-    /// Retrieves the underlying GameCube analog handler.
-    [[nodiscard]] const GCAnalogFactory* GetGCAnalogs() const;
-
-    /// Retrieves the underlying GameCube button handler.
-    [[nodiscard]] GCButtonFactory* GetGCButtons();
-
-    /// Retrieves the underlying GameCube button handler.
-    [[nodiscard]] const GCButtonFactory* GetGCButtons() const;
-
-    /// Retrieves the underlying udp motion handler.
-    [[nodiscard]] UDPMotionFactory* GetUDPMotions();
-
-    /// Retrieves the underlying udp motion handler.
-    [[nodiscard]] const UDPMotionFactory* GetUDPMotions() const;
-
-    /// Retrieves the underlying udp touch handler.
-    [[nodiscard]] UDPTouchFactory* GetUDPTouch();
-
-    /// Retrieves the underlying udp touch handler.
-    [[nodiscard]] const UDPTouchFactory* GetUDPTouch() const;
-
-    /// Retrieves the underlying mouse button handler.
-    [[nodiscard]] MouseButtonFactory* GetMouseButtons();
-
-    /// Retrieves the underlying mouse button handler.
-    [[nodiscard]] const MouseButtonFactory* GetMouseButtons() const;
-
-    /// Retrieves the underlying mouse analog handler.
-    [[nodiscard]] MouseAnalogFactory* GetMouseAnalogs();
-
-    /// Retrieves the underlying mouse analog handler.
-    [[nodiscard]] const MouseAnalogFactory* GetMouseAnalogs() const;
-
-    /// Retrieves the underlying mouse motion handler.
-    [[nodiscard]] MouseMotionFactory* GetMouseMotions();
-
-    /// Retrieves the underlying mouse motion handler.
-    [[nodiscard]] const MouseMotionFactory* GetMouseMotions() const;
-
-    /// Retrieves the underlying mouse touch handler.
-    [[nodiscard]] MouseTouchFactory* GetMouseTouch();
-
-    /// Retrieves the underlying mouse touch handler.
-    [[nodiscard]] const MouseTouchFactory* GetMouseTouch() const;
-
-    /// Retrieves the underlying tas button handler.
-    [[nodiscard]] TasButtonFactory* GetTasButtons();
-
-    /// Retrieves the underlying tas button handler.
-    [[nodiscard]] const TasButtonFactory* GetTasButtons() const;
-
-    /// Retrieves the underlying tas analogs handler.
-    [[nodiscard]] TasAnalogFactory* GetTasAnalogs();
-
-    /// Retrieves the underlying tas analogs handler.
-    [[nodiscard]] const TasAnalogFactory* GetTasAnalogs() const;
-
     /// Reloads the input devices
     void ReloadInputDevices();
 
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index fd0a130a3a..8a0ea90f9d 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -34,8 +34,6 @@
 #include "core/frontend/framebuffer_layout.h"
 #include "input_common/keyboard.h"
 #include "input_common/main.h"
-#include "input_common/mouse/mouse_input.h"
-#include "input_common/tas/tas_input.h"
 #include "video_core/renderer_base.h"
 #include "video_core/video_core.h"
 #include "yuzu/bootmanager.h"
@@ -394,34 +392,34 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
 
 void GRenderWindow::keyPressEvent(QKeyEvent* event) {
     if (!event->isAutoRepeat()) {
-        input_subsystem->GetKeyboard()->PressKey(event->key());
+       // input_subsystem->GetKeyboard()->PressKey(event->key());
     }
 }
 
 void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
     if (!event->isAutoRepeat()) {
-        input_subsystem->GetKeyboard()->ReleaseKey(event->key());
+       // input_subsystem->GetKeyboard()->ReleaseKey(event->key());
     }
 }
 
-MouseInput::MouseButton GRenderWindow::QtButtonToMouseButton(Qt::MouseButton button) {
-    switch (button) {
-    case Qt::LeftButton:
-        return MouseInput::MouseButton::Left;
-    case Qt::RightButton:
-        return MouseInput::MouseButton::Right;
-    case Qt::MiddleButton:
-        return MouseInput::MouseButton::Wheel;
-    case Qt::BackButton:
-        return MouseInput::MouseButton::Backward;
-    case Qt::ForwardButton:
-        return MouseInput::MouseButton::Forward;
-    case Qt::TaskButton:
-        return MouseInput::MouseButton::Task;
-    default:
-        return MouseInput::MouseButton::Extra;
-    }
-}
+//MouseInput::MouseButton GRenderWindow::QtButtonToMouseButton(Qt::MouseButton button) {
+//    switch (button) {
+//    case Qt::LeftButton:
+//        return MouseInput::MouseButton::Left;
+//    case Qt::RightButton:
+//        return MouseInput::MouseButton::Right;
+//    case Qt::MiddleButton:
+//        return MouseInput::MouseButton::Wheel;
+//    case Qt::BackButton:
+//        return MouseInput::MouseButton::Backward;
+//    case Qt::ForwardButton:
+//        return MouseInput::MouseButton::Forward;
+//    case Qt::TaskButton:
+//        return MouseInput::MouseButton::Task;
+//    default:
+//        return MouseInput::MouseButton::Extra;
+//    }
+//}
 
 void GRenderWindow::mousePressEvent(QMouseEvent* event) {
     // Touch input is handled in TouchBeginEvent
@@ -432,8 +430,8 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
     // coordinates and map them to the current render area
     const auto pos = mapFromGlobal(QCursor::pos());
     const auto [x, y] = ScaleTouch(pos);
-    const auto button = QtButtonToMouseButton(event->button());
-    input_subsystem->GetMouse()->PressButton(x, y, button);
+    //const auto button = QtButtonToMouseButton(event->button());
+    //input_subsystem->GetMouse()->PressButton(x, y, button);
 
     if (event->button() == Qt::LeftButton) {
         this->TouchPressed(x, y, 0);
@@ -453,7 +451,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
     const auto [x, y] = ScaleTouch(pos);
     const int center_x = width() / 2;
     const int center_y = height() / 2;
-    input_subsystem->GetMouse()->MouseMove(x, y, center_x, center_y);
+    //input_subsystem->GetMouse()->MouseMove(x, y, center_x, center_y);
     this->TouchMoved(x, y, 0);
 
     if (Settings::values.mouse_panning) {
@@ -469,8 +467,8 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
         return;
     }
 
-    const auto button = QtButtonToMouseButton(event->button());
-    input_subsystem->GetMouse()->ReleaseButton(button);
+    //const auto button = QtButtonToMouseButton(event->button());
+    //input_subsystem->GetMouse()->ReleaseButton(button);
 
     if (event->button() == Qt::LeftButton) {
         this->TouchReleased(0);
@@ -558,8 +556,8 @@ bool GRenderWindow::event(QEvent* event) {
 
 void GRenderWindow::focusOutEvent(QFocusEvent* event) {
     QWidget::focusOutEvent(event);
-    input_subsystem->GetKeyboard()->ReleaseAllKeys();
-    input_subsystem->GetMouse()->ReleaseAllButtons();
+    //input_subsystem->GetKeyboard()->ReleaseAllKeys();
+    //input_subsystem->GetMouse()->ReleaseAllButtons();
     this->TouchReleased(0);
 }
 
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 061e3605f3..f0784046bd 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -165,7 +165,7 @@ public:
     void keyReleaseEvent(QKeyEvent* event) override;
 
     /// Converts a Qt mouse button into MouseInput mouse button
-    static MouseInput::MouseButton QtButtonToMouseButton(Qt::MouseButton button);
+    // static MouseInput::MouseButton QtButtonToMouseButton(Qt::MouseButton button);
 
     void mousePressEvent(QMouseEvent* event) override;
     void mouseMoveEvent(QMouseEvent* event) override;
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 3aab5d5f8f..09f0b219bf 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -16,10 +16,7 @@
 #include "core/hle/service/hid/controllers/npad.h"
 #include "core/hle/service/hid/hid.h"
 #include "core/hle/service/sm/sm.h"
-#include "input_common/gcadapter/gc_poller.h"
 #include "input_common/main.h"
-#include "input_common/mouse/mouse_poller.h"
-#include "input_common/udp/udp.h"
 #include "ui_configure_input_player.h"
 #include "yuzu/bootmanager.h"
 #include "yuzu/configuration/config.h"
@@ -564,55 +561,6 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
 
     connect(poll_timer.get(), &QTimer::timeout, [this] {
         Common::ParamPackage params;
-        if (input_subsystem->GetGCButtons()->IsPolling()) {
-            params = input_subsystem->GetGCButtons()->GetNextInput();
-            if (params.Has("engine") && IsInputAcceptable(params)) {
-                SetPollingResult(params, false);
-                return;
-            }
-        }
-        if (input_subsystem->GetGCAnalogs()->IsPolling()) {
-            params = input_subsystem->GetGCAnalogs()->GetNextInput();
-            if (params.Has("engine") && IsInputAcceptable(params)) {
-                SetPollingResult(params, false);
-                return;
-            }
-        }
-        if (input_subsystem->GetUDPMotions()->IsPolling()) {
-            params = input_subsystem->GetUDPMotions()->GetNextInput();
-            if (params.Has("engine")) {
-                SetPollingResult(params, false);
-                return;
-            }
-        }
-        if (input_subsystem->GetMouseButtons()->IsPolling()) {
-            params = input_subsystem->GetMouseButtons()->GetNextInput();
-            if (params.Has("engine") && IsInputAcceptable(params)) {
-                SetPollingResult(params, false);
-                return;
-            }
-        }
-        if (input_subsystem->GetMouseAnalogs()->IsPolling()) {
-            params = input_subsystem->GetMouseAnalogs()->GetNextInput();
-            if (params.Has("engine") && IsInputAcceptable(params)) {
-                SetPollingResult(params, false);
-                return;
-            }
-        }
-        if (input_subsystem->GetMouseMotions()->IsPolling()) {
-            params = input_subsystem->GetMouseMotions()->GetNextInput();
-            if (params.Has("engine") && IsInputAcceptable(params)) {
-                SetPollingResult(params, false);
-                return;
-            }
-        }
-        if (input_subsystem->GetMouseTouch()->IsPolling()) {
-            params = input_subsystem->GetMouseTouch()->GetNextInput();
-            if (params.Has("engine") && IsInputAcceptable(params)) {
-                SetPollingResult(params, false);
-                return;
-            }
-        }
         for (auto& poller : device_pollers) {
             params = poller->GetNextInput();
             if (params.Has("engine") && IsInputAcceptable(params)) {
@@ -1353,25 +1301,6 @@ void ConfigureInputPlayer::HandleClick(
     QWidget::grabMouse();
     QWidget::grabKeyboard();
 
-    if (type == InputCommon::Polling::DeviceType::Button) {
-        input_subsystem->GetGCButtons()->BeginConfiguration();
-    } else {
-        input_subsystem->GetGCAnalogs()->BeginConfiguration();
-    }
-
-    if (type == InputCommon::Polling::DeviceType::Motion) {
-        input_subsystem->GetUDPMotions()->BeginConfiguration();
-    }
-
-    if (type == InputCommon::Polling::DeviceType::Button) {
-        input_subsystem->GetMouseButtons()->BeginConfiguration();
-    } else if (type == InputCommon::Polling::DeviceType::AnalogPreferred) {
-        input_subsystem->GetMouseAnalogs()->BeginConfiguration();
-    } else if (type == InputCommon::Polling::DeviceType::Motion) {
-        input_subsystem->GetMouseMotions()->BeginConfiguration();
-    } else {
-        input_subsystem->GetMouseTouch()->BeginConfiguration();
-    }
 
     if (type == InputCommon::Polling::DeviceType::Button) {
         ui->controllerFrame->BeginMappingButton(button_id);
@@ -1393,15 +1322,6 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params,
     QWidget::releaseMouse();
     QWidget::releaseKeyboard();
 
-    input_subsystem->GetGCButtons()->EndConfiguration();
-    input_subsystem->GetGCAnalogs()->EndConfiguration();
-
-    input_subsystem->GetUDPMotions()->EndConfiguration();
-
-    input_subsystem->GetMouseButtons()->EndConfiguration();
-    input_subsystem->GetMouseAnalogs()->EndConfiguration();
-    input_subsystem->GetMouseMotions()->EndConfiguration();
-    input_subsystem->GetMouseTouch()->EndConfiguration();
 
     if (!abort) {
         (*input_setter)(params);
@@ -1435,8 +1355,7 @@ void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
         return;
     }
 
-    const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
-    input_subsystem->GetMouse()->PressButton(0, 0, button);
+    //const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
 }
 
 void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
index 5a844409b1..0e190a3d58 100644
--- a/src/yuzu/debugger/controller.cpp
+++ b/src/yuzu/debugger/controller.cpp
@@ -7,7 +7,6 @@
 #include <QString>
 #include "common/settings.h"
 #include "input_common/main.h"
-#include "input_common/tas/tas_input.h"
 #include "yuzu/configuration/configure_input_player_widget.h"
 #include "yuzu/debugger/controller.h"
 
@@ -81,5 +80,5 @@ void ControllerDialog::InputController(ControllerInput input) {
         buttons |= (btn ? 1U : 0U) << index;
         index++;
     }
-    input_subsystem->GetTas()->RecordInput(buttons, input.axis_values);
+    //input_subsystem->GetTas()->RecordInput(buttons, input.axis_values);
 }
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 88e84e8f74..663760a1ea 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2969,15 +2969,15 @@ void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_vie
 }
 
 QString GMainWindow::GetTasStateDescription() const {
-    auto [tas_status, current_tas_frame, total_tas_frames] = input_subsystem->GetTas()->GetStatus();
-    switch (tas_status) {
-    case TasInput::TasState::Running:
-        return tr("TAS state: Running %1/%2").arg(current_tas_frame).arg(total_tas_frames);
-    case TasInput::TasState::Recording:
-        return tr("TAS state: Recording %1").arg(total_tas_frames);
-    case TasInput::TasState::Stopped:
-        return tr("TAS state: Idle %1/%2").arg(current_tas_frame).arg(total_tas_frames);
-    default:
+    //auto [tas_status, current_tas_frame, total_tas_frames] = input_subsystem->GetTas()->GetStatus();
+    //switch (tas_status) {
+    //case TasInput::TasState::Running:
+    //    return tr("TAS state: Running %1/%2").arg(current_tas_frame).arg(total_tas_frames);
+    //case TasInput::TasState::Recording:
+    //    return tr("TAS state: Recording %1").arg(total_tas_frames);
+    //case TasInput::TasState::Stopped:
+    //    return tr("TAS state: Idle %1/%2").arg(current_tas_frame).arg(total_tas_frames);
+    //default:
         return tr("TAS State: Invalid");
     }
 }

From 00834b84dd954f6aea2354e07de2054a99f53fa4 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 17:19:55 -0500
Subject: [PATCH 08/88] input_common: Rewrite mouse

---
 src/input_common/CMakeLists.txt         |   6 +-
 src/input_common/drivers/mouse.cpp      | 138 +++++++++++
 src/input_common/drivers/mouse.h        |  77 ++++++
 src/input_common/mouse/mouse_input.cpp  | 223 ------------------
 src/input_common/mouse/mouse_input.h    | 116 ---------
 src/input_common/mouse/mouse_poller.cpp | 299 ------------------------
 src/input_common/mouse/mouse_poller.h   | 109 ---------
 7 files changed, 217 insertions(+), 751 deletions(-)
 create mode 100644 src/input_common/drivers/mouse.cpp
 create mode 100644 src/input_common/drivers/mouse.h
 delete mode 100644 src/input_common/mouse/mouse_input.cpp
 delete mode 100644 src/input_common/mouse/mouse_input.h
 delete mode 100644 src/input_common/mouse/mouse_poller.cpp
 delete mode 100644 src/input_common/mouse/mouse_poller.h

diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 0fcf7a9d7b..34b41ce01b 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -1,6 +1,8 @@
 add_library(input_common STATIC
     drivers/keyboard.cpp
     drivers/keyboard.h
+    drivers/mouse.cpp
+    drivers/mouse.h
     helpers/stick_from_buttons.cpp
     helpers/stick_from_buttons.h
     helpers/touch_from_buttons.cpp
@@ -23,10 +25,6 @@ add_library(input_common STATIC
     gcadapter/gc_adapter.h
     gcadapter/gc_poller.cpp
     gcadapter/gc_poller.h
-    mouse/mouse_input.cpp
-    mouse/mouse_input.h
-    mouse/mouse_poller.cpp
-    mouse/mouse_poller.h
     sdl/sdl.cpp
     sdl/sdl.h
     tas/tas_input.cpp
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
new file mode 100644
index 0000000000..2c2432fb72
--- /dev/null
+++ b/src/input_common/drivers/mouse.cpp
@@ -0,0 +1,138 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#include <stop_token>
+#include <thread>
+#include <fmt/format.h>
+
+#include "common/param_package.h"
+#include "common/settings.h"
+#include "common/thread.h"
+#include "input_common/drivers/mouse.h"
+
+namespace InputCommon {
+constexpr int touch_axis_x = 10;
+constexpr int touch_axis_y = 11;
+
+Mouse::Mouse(const std::string input_engine_) : InputEngine(input_engine_) {
+    PreSetController(identifier);
+    update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); });
+}
+
+void Mouse::UpdateThread(std::stop_token stop_token) {
+    Common::SetCurrentThreadName("yuzu:input:Mouse");
+    constexpr int update_time = 10;
+    while (!stop_token.stop_requested()) {
+        if (Settings::values.mouse_panning) {
+            // Slow movement by 4%
+            last_mouse_change *= 0.96f;
+            const float sensitivity =
+                Settings::values.mouse_panning_sensitivity.GetValue() * 0.022f;
+            SetAxis(identifier, 0, last_mouse_change.x * sensitivity);
+            SetAxis(identifier, 1, -last_mouse_change.y * sensitivity);
+        }
+
+        if (mouse_panning_timout++ > 20) {
+            StopPanning();
+        }
+        std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
+    }
+}
+
+void Mouse::MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int center_y) {
+    SetAxis(identifier, touch_axis_x, touch_x);
+    SetAxis(identifier, touch_axis_y, touch_y);
+
+    if (Settings::values.mouse_panning) {
+        auto mouse_change =
+            (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>();
+        mouse_panning_timout = 0;
+
+        const auto move_distance = mouse_change.Length();
+        if (move_distance == 0) {
+            return;
+        }
+
+        // Make slow movements at least 3 units on lenght
+        if (move_distance < 3.0f) {
+            // Normalize value
+            mouse_change /= move_distance;
+            mouse_change *= 3.0f;
+        }
+
+        // Average mouse movements
+        last_mouse_change = (last_mouse_change * 0.91f) + (mouse_change * 0.09f);
+
+        const auto last_move_distance = last_mouse_change.Length();
+
+        // Make fast movements clamp to 8 units on lenght
+        if (last_move_distance > 8.0f) {
+            // Normalize value
+            last_mouse_change /= last_move_distance;
+            last_mouse_change *= 8.0f;
+        }
+
+        // Ignore average if it's less than 1 unit and use current movement value
+        if (last_move_distance < 1.0f) {
+            last_mouse_change = mouse_change / mouse_change.Length();
+        }
+
+        return;
+    }
+
+    if (button_pressed) {
+        const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin;
+        const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.0012f;
+        SetAxis(identifier, 0, static_cast<float>(mouse_move.x) * sensitivity);
+        SetAxis(identifier, 1, static_cast<float>(-mouse_move.y) * sensitivity);
+    }
+}
+
+void Mouse::PressButton(int x, int y, f32 touch_x, f32 touch_y, MouseButton button) {
+    SetAxis(identifier, touch_axis_x, touch_x);
+    SetAxis(identifier, touch_axis_y, touch_y);
+    SetButton(identifier, static_cast<int>(button), true);
+    // Set initial analog parameters
+    mouse_origin = {x, y};
+    last_mouse_position = {x, y};
+    button_pressed = true;
+}
+
+void Mouse::ReleaseButton(MouseButton button) {
+    SetButton(identifier, static_cast<int>(button), false);
+
+    if (!Settings::values.mouse_panning) {
+        SetAxis(identifier, 0, 0);
+        SetAxis(identifier, 1, 0);
+    }
+    button_pressed = false;
+}
+
+void Mouse::ReleaseAllButtons() {
+    ResetButtonState();
+    button_pressed = false;
+}
+
+void Mouse::StopPanning() {
+    last_mouse_change = {};
+}
+
+std::vector<Common::ParamPackage> Mouse::GetInputDevices() const {
+    std::vector<Common::ParamPackage> devices;
+    devices.emplace_back(Common::ParamPackage{
+        {"engine", "keyboard"},
+        {"display", "Keyboard/Mouse"},
+    });
+    return devices;
+}
+
+std::string Mouse::GetUIName(const Common::ParamPackage& params) const {
+    if (params.Has("button")) {
+        return fmt::format("Mouse {}", params.Get("button", 0));
+    }
+
+    return "Bad Mouse";
+}
+
+} // namespace InputCommon
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
new file mode 100644
index 0000000000..e8355751a4
--- /dev/null
+++ b/src/input_common/drivers/mouse.h
@@ -0,0 +1,77 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#pragma once
+
+#include <stop_token>
+#include <thread>
+
+#include "common/vector_math.h"
+#include "input_common/input_engine.h"
+
+namespace InputCommon {
+
+enum class MouseButton {
+    Left,
+    Right,
+    Wheel,
+    Backward,
+    Forward,
+    Task,
+    Extra,
+    Undefined,
+};
+
+/**
+ * A button device factory representing a keyboard. It receives keyboard events and forward them
+ * to all button devices it created.
+ */
+class Mouse final : public InputCommon::InputEngine {
+public:
+    explicit Mouse(const std::string input_engine_);
+
+    /**
+     * Signals that mouse has moved.
+     * @param x the x-coordinate of the cursor
+     * @param y the y-coordinate of the cursor
+     * @param center_x the x-coordinate of the middle of the screen
+     * @param center_y the y-coordinate of the middle of the screen
+     */
+    void MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int center_y);
+
+    /**
+     * Sets the status of all buttons bound with the key to pressed
+     * @param key_code the code of the key to press
+     */
+    void PressButton(int x, int y, f32 touch_x, f32 touch_y, MouseButton button);
+
+    /**
+     * Sets the status of all buttons bound with the key to released
+     * @param key_code the code of the key to release
+     */
+    void ReleaseButton(MouseButton button);
+
+    void ReleaseAllButtons();
+
+    std::vector<Common::ParamPackage> GetInputDevices() const override;
+    std::string GetUIName(const Common::ParamPackage& params) const override;
+
+private:
+    void UpdateThread(std::stop_token stop_token);
+    void StopPanning();
+
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{""},
+        .port = 0,
+        .pad = 0,
+    };
+    Common::Vec2<int> mouse_origin;
+    Common::Vec2<int> last_mouse_position;
+    Common::Vec2<float> last_mouse_change;
+    bool button_pressed;
+    int mouse_panning_timout{};
+    std::jthread update_thread;
+};
+
+} // namespace InputCommon
diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp
deleted file mode 100644
index 3b052ffb22..0000000000
--- a/src/input_common/mouse/mouse_input.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#include <stop_token>
-#include <thread>
-
-#include "common/settings.h"
-#include "input_common/mouse/mouse_input.h"
-
-namespace MouseInput {
-
-Mouse::Mouse() {
-    update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); });
-}
-
-Mouse::~Mouse() = default;
-
-void Mouse::UpdateThread(std::stop_token stop_token) {
-    constexpr int update_time = 10;
-    while (!stop_token.stop_requested()) {
-        for (MouseInfo& info : mouse_info) {
-            const Common::Vec3f angular_direction{
-                -info.tilt_direction.y,
-                0.0f,
-                -info.tilt_direction.x,
-            };
-
-            info.motion.SetGyroscope(angular_direction * info.tilt_speed);
-            info.motion.UpdateRotation(update_time * 1000);
-            info.motion.UpdateOrientation(update_time * 1000);
-            info.tilt_speed = 0;
-            info.data.motion = info.motion.GetMotion();
-            if (Settings::values.mouse_panning) {
-                info.last_mouse_change *= 0.96f;
-                info.data.axis = {static_cast<int>(16 * info.last_mouse_change.x),
-                                  static_cast<int>(16 * -info.last_mouse_change.y)};
-            }
-        }
-        if (configuring) {
-            UpdateYuzuSettings();
-        }
-        if (mouse_panning_timout++ > 20) {
-            StopPanning();
-        }
-        std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
-    }
-}
-
-void Mouse::UpdateYuzuSettings() {
-    if (buttons == 0) {
-        return;
-    }
-
-    mouse_queue.Push(MouseStatus{
-        .button = last_button,
-    });
-}
-
-void Mouse::PressButton(int x, int y, MouseButton button_) {
-    const auto button_index = static_cast<std::size_t>(button_);
-    if (button_index >= mouse_info.size()) {
-        return;
-    }
-
-    const auto button = 1U << button_index;
-    buttons |= static_cast<u16>(button);
-    last_button = button_;
-
-    mouse_info[button_index].mouse_origin = Common::MakeVec(x, y);
-    mouse_info[button_index].last_mouse_position = Common::MakeVec(x, y);
-    mouse_info[button_index].data.pressed = true;
-}
-
-void Mouse::StopPanning() {
-    for (MouseInfo& info : mouse_info) {
-        if (Settings::values.mouse_panning) {
-            info.data.axis = {};
-            info.tilt_speed = 0;
-            info.last_mouse_change = {};
-        }
-    }
-}
-
-void Mouse::MouseMove(int x, int y, int center_x, int center_y) {
-    for (MouseInfo& info : mouse_info) {
-        if (Settings::values.mouse_panning) {
-            auto mouse_change =
-                (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>();
-            mouse_panning_timout = 0;
-
-            if (mouse_change.y == 0 && mouse_change.x == 0) {
-                continue;
-            }
-            const auto mouse_change_length = mouse_change.Length();
-            if (mouse_change_length < 3.0f) {
-                mouse_change /= mouse_change_length / 3.0f;
-            }
-
-            info.last_mouse_change = (info.last_mouse_change * 0.91f) + (mouse_change * 0.09f);
-
-            const auto last_mouse_change_length = info.last_mouse_change.Length();
-            if (last_mouse_change_length > 8.0f) {
-                info.last_mouse_change /= last_mouse_change_length / 8.0f;
-            } else if (last_mouse_change_length < 1.0f) {
-                info.last_mouse_change = mouse_change / mouse_change.Length();
-            }
-
-            info.tilt_direction = info.last_mouse_change;
-            info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity;
-            continue;
-        }
-
-        if (info.data.pressed) {
-            const auto mouse_move = Common::MakeVec(x, y) - info.mouse_origin;
-            const auto mouse_change = Common::MakeVec(x, y) - info.last_mouse_position;
-            info.last_mouse_position = Common::MakeVec(x, y);
-            info.data.axis = {mouse_move.x, -mouse_move.y};
-
-            if (mouse_change.x == 0 && mouse_change.y == 0) {
-                info.tilt_speed = 0;
-            } else {
-                info.tilt_direction = mouse_change.Cast<float>();
-                info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity;
-            }
-        }
-    }
-}
-
-void Mouse::ReleaseButton(MouseButton button_) {
-    const auto button_index = static_cast<std::size_t>(button_);
-    if (button_index >= mouse_info.size()) {
-        return;
-    }
-
-    const auto button = 1U << button_index;
-    buttons &= static_cast<u16>(0xFF - button);
-
-    mouse_info[button_index].tilt_speed = 0;
-    mouse_info[button_index].data.pressed = false;
-    mouse_info[button_index].data.axis = {0, 0};
-}
-
-void Mouse::ReleaseAllButtons() {
-    buttons = 0;
-    for (auto& info : mouse_info) {
-        info.tilt_speed = 0;
-        info.data.pressed = false;
-        info.data.axis = {0, 0};
-    }
-}
-
-void Mouse::BeginConfiguration() {
-    buttons = 0;
-    last_button = MouseButton::Undefined;
-    mouse_queue.Clear();
-    configuring = true;
-}
-
-void Mouse::EndConfiguration() {
-    buttons = 0;
-    for (MouseInfo& info : mouse_info) {
-        info.tilt_speed = 0;
-        info.data.pressed = false;
-        info.data.axis = {0, 0};
-    }
-    last_button = MouseButton::Undefined;
-    mouse_queue.Clear();
-    configuring = false;
-}
-
-bool Mouse::ToggleButton(std::size_t button_) {
-    if (button_ >= mouse_info.size()) {
-        return false;
-    }
-    const auto button = 1U << button_;
-    const bool button_state = (toggle_buttons & button) != 0;
-    const bool button_lock = (lock_buttons & button) != 0;
-
-    if (button_lock) {
-        return button_state;
-    }
-
-    lock_buttons |= static_cast<u16>(button);
-
-    if (button_state) {
-        toggle_buttons &= static_cast<u16>(0xFF - button);
-    } else {
-        toggle_buttons |= static_cast<u16>(button);
-    }
-
-    return !button_state;
-}
-
-bool Mouse::UnlockButton(std::size_t button_) {
-    if (button_ >= mouse_info.size()) {
-        return false;
-    }
-
-    const auto button = 1U << button_;
-    const bool button_state = (toggle_buttons & button) != 0;
-
-    lock_buttons &= static_cast<u16>(0xFF - button);
-
-    return button_state;
-}
-
-Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() {
-    return mouse_queue;
-}
-
-const Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() const {
-    return mouse_queue;
-}
-
-MouseData& Mouse::GetMouseState(std::size_t button) {
-    return mouse_info[button].data;
-}
-
-const MouseData& Mouse::GetMouseState(std::size_t button) const {
-    return mouse_info[button].data;
-}
-} // namespace MouseInput
diff --git a/src/input_common/mouse/mouse_input.h b/src/input_common/mouse/mouse_input.h
deleted file mode 100644
index c8bae99c14..0000000000
--- a/src/input_common/mouse/mouse_input.h
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <array>
-#include <mutex>
-#include <stop_token>
-#include <thread>
-
-#include "common/common_types.h"
-#include "common/threadsafe_queue.h"
-#include "common/vector_math.h"
-#include "core/frontend/input.h"
-#include "input_common/motion_input.h"
-
-namespace MouseInput {
-
-enum class MouseButton {
-    Left,
-    Right,
-    Wheel,
-    Backward,
-    Forward,
-    Task,
-    Extra,
-    Undefined,
-};
-
-struct MouseStatus {
-    MouseButton button{MouseButton::Undefined};
-};
-
-struct MouseData {
-    bool pressed{};
-    std::array<int, 2> axis{};
-    Input::MotionStatus motion{};
-    Input::TouchStatus touch{};
-};
-
-class Mouse {
-public:
-    Mouse();
-    ~Mouse();
-
-    /// Used for polling
-    void BeginConfiguration();
-    void EndConfiguration();
-
-    /**
-     * Signals that a button is pressed.
-     * @param x the x-coordinate of the cursor
-     * @param y the y-coordinate of the cursor
-     * @param button_ the button pressed
-     */
-    void PressButton(int x, int y, MouseButton button_);
-
-    /**
-     * Signals that mouse has moved.
-     * @param x the x-coordinate of the cursor
-     * @param y the y-coordinate of the cursor
-     * @param center_x the x-coordinate of the middle of the screen
-     * @param center_y the y-coordinate of the middle of the screen
-     */
-    void MouseMove(int x, int y, int center_x, int center_y);
-
-    /**
-     * Signals that a button is released.
-     * @param button_ the button pressed
-     */
-    void ReleaseButton(MouseButton button_);
-
-    /**
-     * Signals that all buttons are released
-     */
-    void ReleaseAllButtons();
-
-    [[nodiscard]] bool ToggleButton(std::size_t button_);
-    [[nodiscard]] bool UnlockButton(std::size_t button_);
-
-    [[nodiscard]] Common::SPSCQueue<MouseStatus>& GetMouseQueue();
-    [[nodiscard]] const Common::SPSCQueue<MouseStatus>& GetMouseQueue() const;
-
-    [[nodiscard]] MouseData& GetMouseState(std::size_t button);
-    [[nodiscard]] const MouseData& GetMouseState(std::size_t button) const;
-
-private:
-    void UpdateThread(std::stop_token stop_token);
-    void UpdateYuzuSettings();
-    void StopPanning();
-
-    struct MouseInfo {
-        InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f};
-        Common::Vec2<int> mouse_origin;
-        Common::Vec2<int> last_mouse_position;
-        Common::Vec2<float> last_mouse_change;
-        bool is_tilting = false;
-        float sensitivity{0.120f};
-
-        float tilt_speed = 0;
-        Common::Vec2<float> tilt_direction;
-        MouseData data;
-    };
-
-    u16 buttons{};
-    u16 toggle_buttons{};
-    u16 lock_buttons{};
-    std::jthread update_thread;
-    MouseButton last_button{MouseButton::Undefined};
-    std::array<MouseInfo, 7> mouse_info;
-    Common::SPSCQueue<MouseStatus> mouse_queue;
-    bool configuring{false};
-    int mouse_panning_timout{};
-};
-} // namespace MouseInput
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp
deleted file mode 100644
index 090b26972d..0000000000
--- a/src/input_common/mouse/mouse_poller.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <memory>
-#include <mutex>
-#include <utility>
-
-#include "common/settings.h"
-#include "common/threadsafe_queue.h"
-#include "input_common/mouse/mouse_input.h"
-#include "input_common/mouse/mouse_poller.h"
-
-namespace InputCommon {
-
-class MouseButton final : public Input::ButtonDevice {
-public:
-    explicit MouseButton(u32 button_, bool toggle_, MouseInput::Mouse* mouse_input_)
-        : button(button_), toggle(toggle_), mouse_input(mouse_input_) {}
-
-    bool GetStatus() const override {
-        const bool button_state = mouse_input->GetMouseState(button).pressed;
-        if (!toggle) {
-            return button_state;
-        }
-
-        if (button_state) {
-            return mouse_input->ToggleButton(button);
-        }
-        return mouse_input->UnlockButton(button);
-    }
-
-private:
-    const u32 button;
-    const bool toggle;
-    MouseInput::Mouse* mouse_input;
-};
-
-MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
-    : mouse_input(std::move(mouse_input_)) {}
-
-std::unique_ptr<Input::ButtonDevice> MouseButtonFactory::Create(
-    const Common::ParamPackage& params) {
-    const auto button_id = params.Get("button", 0);
-    const auto toggle = params.Get("toggle", false);
-
-    return std::make_unique<MouseButton>(button_id, toggle, mouse_input.get());
-}
-
-Common::ParamPackage MouseButtonFactory::GetNextInput() const {
-    MouseInput::MouseStatus pad;
-    Common::ParamPackage params;
-    auto& queue = mouse_input->GetMouseQueue();
-    while (queue.Pop(pad)) {
-        // This while loop will break on the earliest detected button
-        if (pad.button != MouseInput::MouseButton::Undefined) {
-            params.Set("engine", "mouse");
-            params.Set("button", static_cast<u16>(pad.button));
-            params.Set("toggle", false);
-            return params;
-        }
-    }
-    return params;
-}
-
-void MouseButtonFactory::BeginConfiguration() {
-    polling = true;
-    mouse_input->BeginConfiguration();
-}
-
-void MouseButtonFactory::EndConfiguration() {
-    polling = false;
-    mouse_input->EndConfiguration();
-}
-
-class MouseAnalog final : public Input::AnalogDevice {
-public:
-    explicit MouseAnalog(u32 port_, u32 axis_x_, u32 axis_y_, bool invert_x_, bool invert_y_,
-                         float deadzone_, float range_, const MouseInput::Mouse* mouse_input_)
-        : button(port_), axis_x(axis_x_), axis_y(axis_y_), invert_x(invert_x_), invert_y(invert_y_),
-          deadzone(deadzone_), range(range_), mouse_input(mouse_input_) {}
-
-    float GetAxis(u32 axis) const {
-        std::lock_guard lock{mutex};
-        const auto axis_value =
-            static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis));
-        const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.10f;
-        return axis_value * sensitivity / (100.0f * range);
-    }
-
-    std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
-        float x = GetAxis(analog_axis_x);
-        float y = GetAxis(analog_axis_y);
-        if (invert_x) {
-            x = -x;
-        }
-        if (invert_y) {
-            y = -y;
-        }
-
-        // Make sure the coordinates are in the unit circle,
-        // otherwise normalize it.
-        float r = x * x + y * y;
-        if (r > 1.0f) {
-            r = std::sqrt(r);
-            x /= r;
-            y /= r;
-        }
-
-        return {x, y};
-    }
-
-    std::tuple<float, float> GetStatus() const override {
-        const auto [x, y] = GetAnalog(axis_x, axis_y);
-        const float r = std::sqrt((x * x) + (y * y));
-        if (r > deadzone) {
-            return {x / r * (r - deadzone) / (1 - deadzone),
-                    y / r * (r - deadzone) / (1 - deadzone)};
-        }
-        return {0.0f, 0.0f};
-    }
-
-    std::tuple<float, float> GetRawStatus() const override {
-        const float x = GetAxis(axis_x);
-        const float y = GetAxis(axis_y);
-        return {x, y};
-    }
-
-    Input::AnalogProperties GetAnalogProperties() const override {
-        return {deadzone, range, 0.5f};
-    }
-
-private:
-    const u32 button;
-    const u32 axis_x;
-    const u32 axis_y;
-    const bool invert_x;
-    const bool invert_y;
-    const float deadzone;
-    const float range;
-    const MouseInput::Mouse* mouse_input;
-    mutable std::mutex mutex;
-};
-
-/// An analog device factory that creates analog devices from GC Adapter
-MouseAnalogFactory::MouseAnalogFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
-    : mouse_input(std::move(mouse_input_)) {}
-
-/**
- * Creates analog device from joystick axes
- * @param params contains parameters for creating the device:
- *     - "port": the nth gcpad on the adapter
- *     - "axis_x": the index of the axis to be bind as x-axis
- *     - "axis_y": the index of the axis to be bind as y-axis
- */
-std::unique_ptr<Input::AnalogDevice> MouseAnalogFactory::Create(
-    const Common::ParamPackage& params) {
-    const auto port = static_cast<u32>(params.Get("port", 0));
-    const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
-    const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
-    const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
-    const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
-    const std::string invert_x_value = params.Get("invert_x", "+");
-    const std::string invert_y_value = params.Get("invert_y", "+");
-    const bool invert_x = invert_x_value == "-";
-    const bool invert_y = invert_y_value == "-";
-
-    return std::make_unique<MouseAnalog>(port, axis_x, axis_y, invert_x, invert_y, deadzone, range,
-                                         mouse_input.get());
-}
-
-void MouseAnalogFactory::BeginConfiguration() {
-    polling = true;
-    mouse_input->BeginConfiguration();
-}
-
-void MouseAnalogFactory::EndConfiguration() {
-    polling = false;
-    mouse_input->EndConfiguration();
-}
-
-Common::ParamPackage MouseAnalogFactory::GetNextInput() const {
-    MouseInput::MouseStatus pad;
-    Common::ParamPackage params;
-    auto& queue = mouse_input->GetMouseQueue();
-    while (queue.Pop(pad)) {
-        // This while loop will break on the earliest detected button
-        if (pad.button != MouseInput::MouseButton::Undefined) {
-            params.Set("engine", "mouse");
-            params.Set("port", static_cast<u16>(pad.button));
-            params.Set("axis_x", 0);
-            params.Set("axis_y", 1);
-            params.Set("invert_x", "+");
-            params.Set("invert_y", "+");
-            return params;
-        }
-    }
-    return params;
-}
-
-class MouseMotion final : public Input::MotionDevice {
-public:
-    explicit MouseMotion(u32 button_, const MouseInput::Mouse* mouse_input_)
-        : button(button_), mouse_input(mouse_input_) {}
-
-    Input::MotionStatus GetStatus() const override {
-        return mouse_input->GetMouseState(button).motion;
-    }
-
-private:
-    const u32 button;
-    const MouseInput::Mouse* mouse_input;
-};
-
-MouseMotionFactory::MouseMotionFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
-    : mouse_input(std::move(mouse_input_)) {}
-
-std::unique_ptr<Input::MotionDevice> MouseMotionFactory::Create(
-    const Common::ParamPackage& params) {
-    const auto button_id = params.Get("button", 0);
-
-    return std::make_unique<MouseMotion>(button_id, mouse_input.get());
-}
-
-Common::ParamPackage MouseMotionFactory::GetNextInput() const {
-    MouseInput::MouseStatus pad;
-    Common::ParamPackage params;
-    auto& queue = mouse_input->GetMouseQueue();
-    while (queue.Pop(pad)) {
-        // This while loop will break on the earliest detected button
-        if (pad.button != MouseInput::MouseButton::Undefined) {
-            params.Set("engine", "mouse");
-            params.Set("button", static_cast<u16>(pad.button));
-            return params;
-        }
-    }
-    return params;
-}
-
-void MouseMotionFactory::BeginConfiguration() {
-    polling = true;
-    mouse_input->BeginConfiguration();
-}
-
-void MouseMotionFactory::EndConfiguration() {
-    polling = false;
-    mouse_input->EndConfiguration();
-}
-
-class MouseTouch final : public Input::TouchDevice {
-public:
-    explicit MouseTouch(u32 button_, const MouseInput::Mouse* mouse_input_)
-        : button(button_), mouse_input(mouse_input_) {}
-
-    Input::TouchStatus GetStatus() const override {
-        return mouse_input->GetMouseState(button).touch;
-    }
-
-private:
-    const u32 button;
-    const MouseInput::Mouse* mouse_input;
-};
-
-MouseTouchFactory::MouseTouchFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
-    : mouse_input(std::move(mouse_input_)) {}
-
-std::unique_ptr<Input::TouchDevice> MouseTouchFactory::Create(const Common::ParamPackage& params) {
-    const auto button_id = params.Get("button", 0);
-
-    return std::make_unique<MouseTouch>(button_id, mouse_input.get());
-}
-
-Common::ParamPackage MouseTouchFactory::GetNextInput() const {
-    MouseInput::MouseStatus pad;
-    Common::ParamPackage params;
-    auto& queue = mouse_input->GetMouseQueue();
-    while (queue.Pop(pad)) {
-        // This while loop will break on the earliest detected button
-        if (pad.button != MouseInput::MouseButton::Undefined) {
-            params.Set("engine", "mouse");
-            params.Set("button", static_cast<u16>(pad.button));
-            return params;
-        }
-    }
-    return params;
-}
-
-void MouseTouchFactory::BeginConfiguration() {
-    polling = true;
-    mouse_input->BeginConfiguration();
-}
-
-void MouseTouchFactory::EndConfiguration() {
-    polling = false;
-    mouse_input->EndConfiguration();
-}
-
-} // namespace InputCommon
diff --git a/src/input_common/mouse/mouse_poller.h b/src/input_common/mouse/mouse_poller.h
deleted file mode 100644
index cf331293b8..0000000000
--- a/src/input_common/mouse/mouse_poller.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include "core/frontend/input.h"
-#include "input_common/mouse/mouse_input.h"
-
-namespace InputCommon {
-
-/**
- * A button device factory representing a mouse. It receives mouse events and forward them
- * to all button devices it created.
- */
-class MouseButtonFactory final : public Input::Factory<Input::ButtonDevice> {
-public:
-    explicit MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
-
-    /**
-     * Creates a button device from a button press
-     * @param params contains parameters for creating the device:
-     *     - "code": the code of the key to bind with the button
-     */
-    std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override;
-
-    Common::ParamPackage GetNextInput() const;
-
-    /// For device input configuration/polling
-    void BeginConfiguration();
-    void EndConfiguration();
-
-    bool IsPolling() const {
-        return polling;
-    }
-
-private:
-    std::shared_ptr<MouseInput::Mouse> mouse_input;
-    bool polling = false;
-};
-
-/// An analog device factory that creates analog devices from mouse
-class MouseAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
-public:
-    explicit MouseAnalogFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
-
-    std::unique_ptr<Input::AnalogDevice> Create(const Common::ParamPackage& params) override;
-
-    Common::ParamPackage GetNextInput() const;
-
-    /// For device input configuration/polling
-    void BeginConfiguration();
-    void EndConfiguration();
-
-    bool IsPolling() const {
-        return polling;
-    }
-
-private:
-    std::shared_ptr<MouseInput::Mouse> mouse_input;
-    bool polling = false;
-};
-
-/// A motion device factory that creates motion devices from mouse
-class MouseMotionFactory final : public Input::Factory<Input::MotionDevice> {
-public:
-    explicit MouseMotionFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
-
-    std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
-
-    Common::ParamPackage GetNextInput() const;
-
-    /// For device input configuration/polling
-    void BeginConfiguration();
-    void EndConfiguration();
-
-    bool IsPolling() const {
-        return polling;
-    }
-
-private:
-    std::shared_ptr<MouseInput::Mouse> mouse_input;
-    bool polling = false;
-};
-
-/// An touch device factory that creates touch devices from mouse
-class MouseTouchFactory final : public Input::Factory<Input::TouchDevice> {
-public:
-    explicit MouseTouchFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
-
-    std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override;
-
-    Common::ParamPackage GetNextInput() const;
-
-    /// For device input configuration/polling
-    void BeginConfiguration();
-    void EndConfiguration();
-
-    bool IsPolling() const {
-        return polling;
-    }
-
-private:
-    std::shared_ptr<MouseInput::Mouse> mouse_input;
-    bool polling = false;
-};
-
-} // namespace InputCommon

From fa8e23b84281022bf6b4e8916231a17e9997e5aa Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 17:20:56 -0500
Subject: [PATCH 09/88] input_common: Rewrite touch

---
 src/input_common/CMakeLists.txt           |  2 +
 src/input_common/drivers/touch_screen.cpp | 47 +++++++++++++++++++++
 src/input_common/drivers/touch_screen.h   | 50 +++++++++++++++++++++++
 3 files changed, 99 insertions(+)
 create mode 100644 src/input_common/drivers/touch_screen.cpp
 create mode 100644 src/input_common/drivers/touch_screen.h

diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 34b41ce01b..71091767da 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -3,6 +3,8 @@ add_library(input_common STATIC
     drivers/keyboard.h
     drivers/mouse.cpp
     drivers/mouse.h
+    drivers/touch_screen.cpp
+    drivers/touch_screen.h
     helpers/stick_from_buttons.cpp
     helpers/stick_from_buttons.h
     helpers/touch_from_buttons.cpp
diff --git a/src/input_common/drivers/touch_screen.cpp b/src/input_common/drivers/touch_screen.cpp
new file mode 100644
index 0000000000..e13835e9f3
--- /dev/null
+++ b/src/input_common/drivers/touch_screen.cpp
@@ -0,0 +1,47 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#include "common/param_package.h"
+#include "input_common/drivers/touch_screen.h"
+
+namespace InputCommon {
+
+TouchScreen::TouchScreen(const std::string input_engine_) : InputEngine(input_engine_) {
+    PreSetController(identifier);
+}
+
+void TouchScreen::TouchMoved(float x, float y, std::size_t finger) {
+    if (finger >= 16) {
+        return;
+    }
+    TouchPressed(x, y, finger);
+}
+
+void TouchScreen::TouchPressed(float x, float y, std::size_t finger) {
+    if (finger >= 16) {
+        return;
+    }
+    SetButton(identifier, static_cast<int>(finger), true);
+    SetAxis(identifier, static_cast<int>(finger * 2), x);
+    SetAxis(identifier, static_cast<int>(finger * 2 + 1), y);
+}
+
+void TouchScreen::TouchReleased(std::size_t finger) {
+    if (finger >= 16) {
+        return;
+    }
+    SetButton(identifier, static_cast<int>(finger), false);
+    SetAxis(identifier, static_cast<int>(finger * 2), 0.0f);
+    SetAxis(identifier, static_cast<int>(finger * 2 + 1), 0.0f);
+}
+
+void TouchScreen::ReleaseAllTouch() {
+    for (int index = 0; index < 16; ++index) {
+        SetButton(identifier, index, false);
+        SetAxis(identifier, index * 2, 0.0f);
+        SetAxis(identifier, index * 2 + 1, 0.0f);
+    }
+}
+
+} // namespace InputCommon
diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h
new file mode 100644
index 0000000000..5fbb2f47ff
--- /dev/null
+++ b/src/input_common/drivers/touch_screen.h
@@ -0,0 +1,50 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#pragma once
+
+#include "input_common/input_engine.h"
+
+namespace InputCommon {
+
+/**
+ * A button device factory representing a keyboard. It receives keyboard events and forward them
+ * to all button devices it created.
+ */
+class TouchScreen final : public InputCommon::InputEngine {
+public:
+    explicit TouchScreen(const std::string input_engine_);
+
+    /**
+     * Signals that mouse has moved.
+     * @param x the x-coordinate of the cursor
+     * @param y the y-coordinate of the cursor
+     * @param center_x the x-coordinate of the middle of the screen
+     * @param center_y the y-coordinate of the middle of the screen
+     */
+    void TouchMoved(float x, float y, std::size_t finger);
+
+    /**
+     * Sets the status of all buttons bound with the key to pressed
+     * @param key_code the code of the key to press
+     */
+    void TouchPressed(float x, float y, std::size_t finger);
+
+    /**
+     * Sets the status of all buttons bound with the key to released
+     * @param key_code the code of the key to release
+     */
+    void TouchReleased(std::size_t finger);
+
+    void ReleaseAllTouch();
+
+private:
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{""},
+        .port = 0,
+        .pad = 0,
+    };
+};
+
+} // namespace InputCommon

From 395e9a449d338e56ade9ea88ffeed297a7d86b10 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 17:22:07 -0500
Subject: [PATCH 10/88] input_common: Rewrite gc_adapter

---
 src/input_common/CMakeLists.txt               |   6 +-
 .../{gcadapter => drivers}/gc_adapter.cpp     | 427 +++++++++---------
 src/input_common/drivers/gc_adapter.h         | 128 ++++++
 src/input_common/drivers/tas_input.cpp        | 320 +++++++++++++
 src/input_common/drivers/tas_input.h          | 200 ++++++++
 src/input_common/gcadapter/gc_adapter.h       | 168 -------
 src/input_common/gcadapter/gc_poller.cpp      | 356 ---------------
 src/input_common/gcadapter/gc_poller.h        |  78 ----
 8 files changed, 852 insertions(+), 831 deletions(-)
 rename src/input_common/{gcadapter => drivers}/gc_adapter.cpp (61%)
 create mode 100644 src/input_common/drivers/gc_adapter.h
 create mode 100644 src/input_common/drivers/tas_input.cpp
 create mode 100644 src/input_common/drivers/tas_input.h
 delete mode 100644 src/input_common/gcadapter/gc_adapter.h
 delete mode 100644 src/input_common/gcadapter/gc_poller.cpp
 delete mode 100644 src/input_common/gcadapter/gc_poller.h

diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 71091767da..c8871513ce 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -1,4 +1,6 @@
 add_library(input_common STATIC
+    drivers/gc_adapter.cpp
+    drivers/gc_adapter.h
     drivers/keyboard.cpp
     drivers/keyboard.h
     drivers/mouse.cpp
@@ -23,10 +25,6 @@ add_library(input_common STATIC
     motion_from_button.h
     motion_input.cpp
     motion_input.h
-    gcadapter/gc_adapter.cpp
-    gcadapter/gc_adapter.h
-    gcadapter/gc_poller.cpp
-    gcadapter/gc_poller.h
     sdl/sdl.cpp
     sdl/sdl.h
     tas/tas_input.cpp
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp
similarity index 61%
rename from src/input_common/gcadapter/gc_adapter.cpp
rename to src/input_common/drivers/gc_adapter.cpp
index a2f1bb67c8..6721ba4f7b 100644
--- a/src/input_common/gcadapter/gc_adapter.cpp
+++ b/src/input_common/drivers/gc_adapter.cpp
@@ -2,47 +2,103 @@
 // Licensed under GPLv2+
 // Refer to the license.txt file included.
 
-#include <chrono>
-#include <thread>
-
+#include <fmt/format.h>
 #include <libusb.h>
 
 #include "common/logging/log.h"
 #include "common/param_package.h"
 #include "common/settings_input.h"
-#include "input_common/gcadapter/gc_adapter.h"
+#include "common/thread.h"
+#include "input_common/drivers/gc_adapter.h"
 
-namespace GCAdapter {
+namespace InputCommon {
 
-Adapter::Adapter() {
-    if (usb_adapter_handle != nullptr) {
+class LibUSBContext {
+public:
+    explicit LibUSBContext() {
+        init_result = libusb_init(&ctx);
+    }
+
+    ~LibUSBContext() {
+        libusb_exit(ctx);
+    }
+
+    LibUSBContext& operator=(const LibUSBContext&) = delete;
+    LibUSBContext(const LibUSBContext&) = delete;
+
+    LibUSBContext& operator=(LibUSBContext&&) noexcept = delete;
+    LibUSBContext(LibUSBContext&&) noexcept = delete;
+
+    [[nodiscard]] int InitResult() const noexcept {
+        return init_result;
+    }
+
+    [[nodiscard]] libusb_context* get() noexcept {
+        return ctx;
+    }
+
+private:
+    libusb_context* ctx;
+    int init_result{};
+};
+
+class LibUSBDeviceHandle {
+public:
+    explicit LibUSBDeviceHandle(libusb_context* ctx, uint16_t vid, uint16_t pid) noexcept {
+        handle = libusb_open_device_with_vid_pid(ctx, vid, pid);
+    }
+
+    ~LibUSBDeviceHandle() noexcept {
+        if (handle) {
+            libusb_release_interface(handle, 1);
+            libusb_close(handle);
+        }
+    }
+
+    LibUSBDeviceHandle& operator=(const LibUSBDeviceHandle&) = delete;
+    LibUSBDeviceHandle(const LibUSBDeviceHandle&) = delete;
+
+    LibUSBDeviceHandle& operator=(LibUSBDeviceHandle&&) noexcept = delete;
+    LibUSBDeviceHandle(LibUSBDeviceHandle&&) noexcept = delete;
+
+    [[nodiscard]] libusb_device_handle* get() noexcept {
+        return handle;
+    }
+
+private:
+    libusb_device_handle* handle{};
+};
+
+GCAdapter::GCAdapter(const std::string input_engine_) : InputEngine(input_engine_) {
+    if (usb_adapter_handle) {
         return;
     }
     LOG_INFO(Input, "GC Adapter Initialization started");
 
-    const int init_res = libusb_init(&libusb_ctx);
+    libusb_ctx = std::make_unique<LibUSBContext>();
+    const int init_res = libusb_ctx->InitResult();
     if (init_res == LIBUSB_SUCCESS) {
-        adapter_scan_thread = std::thread(&Adapter::AdapterScanThread, this);
+        adapter_scan_thread =
+            std::jthread([this](std::stop_token stop_token) { AdapterScanThread(stop_token); });
     } else {
         LOG_ERROR(Input, "libusb could not be initialized. failed with error = {}", init_res);
     }
 }
 
-Adapter::~Adapter() {
+GCAdapter::~GCAdapter() {
     Reset();
 }
 
-void Adapter::AdapterInputThread() {
+void GCAdapter::AdapterInputThread(std::stop_token stop_token) {
     LOG_DEBUG(Input, "GC Adapter input thread started");
+    Common::SetCurrentThreadName("yuzu:input:GCAdapter");
     s32 payload_size{};
     AdapterPayload adapter_payload{};
 
-    if (adapter_scan_thread.joinable()) {
-        adapter_scan_thread.join();
-    }
+    adapter_scan_thread = {};
 
-    while (adapter_input_thread_running) {
-        libusb_interrupt_transfer(usb_adapter_handle, input_endpoint, adapter_payload.data(),
+    while (!stop_token.stop_requested()) {
+        libusb_interrupt_transfer(usb_adapter_handle->get(), input_endpoint, adapter_payload.data(),
                                   static_cast<s32>(adapter_payload.size()), &payload_size, 16);
         if (IsPayloadCorrect(adapter_payload, payload_size)) {
             UpdateControllers(adapter_payload);
@@ -52,19 +108,20 @@ void Adapter::AdapterInputThread() {
     }
 
     if (restart_scan_thread) {
-        adapter_scan_thread = std::thread(&Adapter::AdapterScanThread, this);
+        adapter_scan_thread =
+            std::jthread([this](std::stop_token token) { AdapterScanThread(token); });
         restart_scan_thread = false;
     }
 }
 
-bool Adapter::IsPayloadCorrect(const AdapterPayload& adapter_payload, s32 payload_size) {
+bool GCAdapter::IsPayloadCorrect(const AdapterPayload& adapter_payload, s32 payload_size) {
     if (payload_size != static_cast<s32>(adapter_payload.size()) ||
         adapter_payload[0] != LIBUSB_DT_HID) {
         LOG_DEBUG(Input, "Error reading payload (size: {}, type: {:02x})", payload_size,
                   adapter_payload[0]);
         if (input_error_counter++ > 20) {
             LOG_ERROR(Input, "GC adapter timeout, Is the adapter connected?");
-            adapter_input_thread_running = false;
+            adapter_input_thread.request_stop();
             restart_scan_thread = true;
         }
         return false;
@@ -74,7 +131,7 @@ bool Adapter::IsPayloadCorrect(const AdapterPayload& adapter_payload, s32 payloa
     return true;
 }
 
-void Adapter::UpdateControllers(const AdapterPayload& adapter_payload) {
+void GCAdapter::UpdateControllers(const AdapterPayload& adapter_payload) {
     for (std::size_t port = 0; port < pads.size(); ++port) {
         const std::size_t offset = 1 + (9 * port);
         const auto type = static_cast<ControllerTypes>(adapter_payload[offset] >> 4);
@@ -84,23 +141,21 @@ void Adapter::UpdateControllers(const AdapterPayload& adapter_payload) {
             const u8 b2 = adapter_payload[offset + 2];
             UpdateStateButtons(port, b1, b2);
             UpdateStateAxes(port, adapter_payload);
-            if (configuring) {
-                UpdateYuzuSettings(port);
-            }
         }
     }
 }
 
-void Adapter::UpdatePadType(std::size_t port, ControllerTypes pad_type) {
+void GCAdapter::UpdatePadType(std::size_t port, ControllerTypes pad_type) {
     if (pads[port].type == pad_type) {
         return;
     }
     // Device changed reset device and set new type
-    ResetDevice(port);
+    pads[port] = {};
     pads[port].type = pad_type;
 }
 
-void Adapter::UpdateStateButtons(std::size_t port, u8 b1, u8 b2) {
+void GCAdapter::UpdateStateButtons(std::size_t port, [[maybe_unused]] u8 b1,
+                                   [[maybe_unused]] u8 b2) {
     if (port >= pads.size()) {
         return;
     }
@@ -116,25 +171,21 @@ void Adapter::UpdateStateButtons(std::size_t port, u8 b1, u8 b2) {
         PadButton::TriggerR,
         PadButton::TriggerL,
     };
-    pads[port].buttons = 0;
+
     for (std::size_t i = 0; i < b1_buttons.size(); ++i) {
-        if ((b1 & (1U << i)) != 0) {
-            pads[port].buttons =
-                static_cast<u16>(pads[port].buttons | static_cast<u16>(b1_buttons[i]));
-            pads[port].last_button = b1_buttons[i];
-        }
+        const bool button_status = (b1 & (1U << i)) != 0;
+        const int button = static_cast<int>(b1_buttons[i]);
+        SetButton(pads[port].identifier, button, button_status);
     }
 
     for (std::size_t j = 0; j < b2_buttons.size(); ++j) {
-        if ((b2 & (1U << j)) != 0) {
-            pads[port].buttons =
-                static_cast<u16>(pads[port].buttons | static_cast<u16>(b2_buttons[j]));
-            pads[port].last_button = b2_buttons[j];
-        }
+        const bool button_status = (b2 & (1U << j)) != 0;
+        const int button = static_cast<int>(b2_buttons[j]);
+        SetButton(pads[port].identifier, button, button_status);
     }
 }
 
-void Adapter::UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_payload) {
+void GCAdapter::UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_payload) {
     if (port >= pads.size()) {
         return;
     }
@@ -155,134 +206,70 @@ void Adapter::UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_pa
             pads[port].axis_origin[index] = axis_value;
             pads[port].reset_origin_counter++;
         }
-        pads[port].axis_values[index] =
-            static_cast<s16>(axis_value - pads[port].axis_origin[index]);
+        const f32 axis_status = (axis_value - pads[port].axis_origin[index]) / 110.0f;
+        SetAxis(pads[port].identifier, static_cast<int>(index), axis_status);
     }
 }
 
-void Adapter::UpdateYuzuSettings(std::size_t port) {
-    if (port >= pads.size()) {
-        return;
-    }
-
-    constexpr u8 axis_threshold = 50;
-    GCPadStatus pad_status = {.port = port};
-
-    if (pads[port].buttons != 0) {
-        pad_status.button = pads[port].last_button;
-        pad_queue.Push(pad_status);
-    }
-
-    // Accounting for a threshold here to ensure an intentional press
-    for (std::size_t i = 0; i < pads[port].axis_values.size(); ++i) {
-        const s16 value = pads[port].axis_values[i];
-
-        if (value > axis_threshold || value < -axis_threshold) {
-            pad_status.axis = static_cast<PadAxes>(i);
-            pad_status.axis_value = value;
-            pad_status.axis_threshold = axis_threshold;
-            pad_queue.Push(pad_status);
-        }
+void GCAdapter::AdapterScanThread(std::stop_token stop_token) {
+    Common::SetCurrentThreadName("yuzu:input:ScanGCAdapter");
+    usb_adapter_handle = nullptr;
+    pads = {};
+    while (!stop_token.stop_requested() && !Setup()) {
+        std::this_thread::sleep_for(std::chrono::seconds(2));
     }
 }
 
-void Adapter::UpdateVibrations() {
-    // Use 8 states to keep the switching between on/off fast enough for
-    // a human to not notice the difference between switching from on/off
-    // More states = more rumble strengths = slower update time
-    constexpr u8 vibration_states = 8;
-
-    vibration_counter = (vibration_counter + 1) % vibration_states;
-
-    for (GCController& pad : pads) {
-        const bool vibrate = pad.rumble_amplitude > vibration_counter;
-        vibration_changed |= vibrate != pad.enable_vibration;
-        pad.enable_vibration = vibrate;
-    }
-    SendVibrations();
-}
-
-void Adapter::SendVibrations() {
-    if (!rumble_enabled || !vibration_changed) {
-        return;
-    }
-    s32 size{};
-    constexpr u8 rumble_command = 0x11;
-    const u8 p1 = pads[0].enable_vibration;
-    const u8 p2 = pads[1].enable_vibration;
-    const u8 p3 = pads[2].enable_vibration;
-    const u8 p4 = pads[3].enable_vibration;
-    std::array<u8, 5> payload = {rumble_command, p1, p2, p3, p4};
-    const int err = libusb_interrupt_transfer(usb_adapter_handle, output_endpoint, payload.data(),
-                                              static_cast<s32>(payload.size()), &size, 16);
-    if (err) {
-        LOG_DEBUG(Input, "Adapter libusb write failed: {}", libusb_error_name(err));
-        if (output_error_counter++ > 5) {
-            LOG_ERROR(Input, "GC adapter output timeout, Rumble disabled");
-            rumble_enabled = false;
-        }
-        return;
-    }
-    output_error_counter = 0;
-    vibration_changed = false;
-}
-
-bool Adapter::RumblePlay(std::size_t port, u8 amplitude) {
-    pads[port].rumble_amplitude = amplitude;
-
-    return rumble_enabled;
-}
-
-void Adapter::AdapterScanThread() {
-    adapter_scan_thread_running = true;
-    adapter_input_thread_running = false;
-    if (adapter_input_thread.joinable()) {
-        adapter_input_thread.join();
-    }
-    ClearLibusbHandle();
-    ResetDevices();
-    while (adapter_scan_thread_running && !adapter_input_thread_running) {
-        Setup();
-        std::this_thread::sleep_for(std::chrono::seconds(1));
-    }
-}
-
-void Adapter::Setup() {
-    usb_adapter_handle = libusb_open_device_with_vid_pid(libusb_ctx, 0x057e, 0x0337);
-
-    if (usb_adapter_handle == NULL) {
-        return;
+bool GCAdapter::Setup() {
+    constexpr u16 nintendo_vid = 0x057e;
+    constexpr u16 gc_adapter_pid = 0x0337;
+    usb_adapter_handle =
+        std::make_unique<LibUSBDeviceHandle>(libusb_ctx->get(), nintendo_vid, gc_adapter_pid);
+    if (!usb_adapter_handle->get()) {
+        return false;
     }
     if (!CheckDeviceAccess()) {
-        ClearLibusbHandle();
-        return;
+        usb_adapter_handle = nullptr;
+        return false;
     }
 
-    libusb_device* device = libusb_get_device(usb_adapter_handle);
+    libusb_device* const device = libusb_get_device(usb_adapter_handle->get());
 
     LOG_INFO(Input, "GC adapter is now connected");
     // GC Adapter found and accessible, registering it
     if (GetGCEndpoint(device)) {
-        adapter_scan_thread_running = false;
-        adapter_input_thread_running = true;
         rumble_enabled = true;
         input_error_counter = 0;
         output_error_counter = 0;
-        adapter_input_thread = std::thread(&Adapter::AdapterInputThread, this);
+
+        std::size_t port = 0;
+        for (GCController& pad : pads) {
+            pad.identifier = {
+                .guid = Common::UUID{""},
+                .port = port++,
+                .pad = 0,
+            };
+            PreSetController(pad.identifier);
+        }
+
+        adapter_input_thread =
+            std::jthread([this](std::stop_token stop_token) { AdapterInputThread(stop_token); });
+        return true;
     }
+    return false;
 }
 
-bool Adapter::CheckDeviceAccess() {
+bool GCAdapter::CheckDeviceAccess() {
     // This fixes payload problems from offbrand GCAdapters
     const s32 control_transfer_error =
-        libusb_control_transfer(usb_adapter_handle, 0x21, 11, 0x0001, 0, nullptr, 0, 1000);
+        libusb_control_transfer(usb_adapter_handle->get(), 0x21, 11, 0x0001, 0, nullptr, 0, 1000);
     if (control_transfer_error < 0) {
         LOG_ERROR(Input, "libusb_control_transfer failed with error= {}", control_transfer_error);
     }
 
-    s32 kernel_driver_error = libusb_kernel_driver_active(usb_adapter_handle, 0);
+    s32 kernel_driver_error = libusb_kernel_driver_active(usb_adapter_handle->get(), 0);
     if (kernel_driver_error == 1) {
-        kernel_driver_error = libusb_detach_kernel_driver(usb_adapter_handle, 0);
+        kernel_driver_error = libusb_detach_kernel_driver(usb_adapter_handle->get(), 0);
         if (kernel_driver_error != 0 && kernel_driver_error != LIBUSB_ERROR_NOT_SUPPORTED) {
             LOG_ERROR(Input, "libusb_detach_kernel_driver failed with error = {}",
                       kernel_driver_error);
@@ -290,15 +277,13 @@ bool Adapter::CheckDeviceAccess() {
     }
 
     if (kernel_driver_error && kernel_driver_error != LIBUSB_ERROR_NOT_SUPPORTED) {
-        libusb_close(usb_adapter_handle);
         usb_adapter_handle = nullptr;
         return false;
     }
 
-    const int interface_claim_error = libusb_claim_interface(usb_adapter_handle, 0);
+    const int interface_claim_error = libusb_claim_interface(usb_adapter_handle->get(), 0);
     if (interface_claim_error) {
         LOG_ERROR(Input, "libusb_claim_interface failed with error = {}", interface_claim_error);
-        libusb_close(usb_adapter_handle);
         usb_adapter_handle = nullptr;
         return false;
     }
@@ -306,7 +291,7 @@ bool Adapter::CheckDeviceAccess() {
     return true;
 }
 
-bool Adapter::GetGCEndpoint(libusb_device* device) {
+bool GCAdapter::GetGCEndpoint(libusb_device* device) {
     libusb_config_descriptor* config = nullptr;
     const int config_descriptor_return = libusb_get_config_descriptor(device, 0, &config);
     if (config_descriptor_return != LIBUSB_SUCCESS) {
@@ -332,68 +317,83 @@ bool Adapter::GetGCEndpoint(libusb_device* device) {
     // This transfer seems to be responsible for clearing the state of the adapter
     // Used to clear the "busy" state of when the device is unexpectedly unplugged
     unsigned char clear_payload = 0x13;
-    libusb_interrupt_transfer(usb_adapter_handle, output_endpoint, &clear_payload,
+    libusb_interrupt_transfer(usb_adapter_handle->get(), output_endpoint, &clear_payload,
                               sizeof(clear_payload), nullptr, 16);
     return true;
 }
 
-void Adapter::JoinThreads() {
-    restart_scan_thread = false;
-    adapter_input_thread_running = false;
-    adapter_scan_thread_running = false;
+bool GCAdapter::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) {
+    const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f;
+    const auto processed_amplitude =
+        static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8);
 
-    if (adapter_scan_thread.joinable()) {
-        adapter_scan_thread.join();
-    }
-
-    if (adapter_input_thread.joinable()) {
-        adapter_input_thread.join();
-    }
+    pads[identifier.port].rumble_amplitude = processed_amplitude;
+    return rumble_enabled;
 }
 
-void Adapter::ClearLibusbHandle() {
-    if (usb_adapter_handle) {
-        libusb_release_interface(usb_adapter_handle, 1);
-        libusb_close(usb_adapter_handle);
-        usb_adapter_handle = nullptr;
+void GCAdapter::UpdateVibrations() {
+    // Use 8 states to keep the switching between on/off fast enough for
+    // a human to feel different vibration strenght
+    // More states == more rumble strengths == slower update time
+    constexpr u8 vibration_states = 8;
+
+    vibration_counter = (vibration_counter + 1) % vibration_states;
+
+    for (GCController& pad : pads) {
+        const bool vibrate = pad.rumble_amplitude > vibration_counter;
+        vibration_changed |= vibrate != pad.enable_vibration;
+        pad.enable_vibration = vibrate;
     }
+    SendVibrations();
 }
 
-void Adapter::ResetDevices() {
-    for (std::size_t i = 0; i < pads.size(); ++i) {
-        ResetDevice(i);
+void GCAdapter::SendVibrations() {
+    if (!rumble_enabled || !vibration_changed) {
+        return;
     }
-}
-
-void Adapter::ResetDevice(std::size_t port) {
-    pads[port].type = ControllerTypes::None;
-    pads[port].enable_vibration = false;
-    pads[port].rumble_amplitude = 0;
-    pads[port].buttons = 0;
-    pads[port].last_button = PadButton::Undefined;
-    pads[port].axis_values.fill(0);
-    pads[port].reset_origin_counter = 0;
-}
-
-void Adapter::Reset() {
-    JoinThreads();
-    ClearLibusbHandle();
-    ResetDevices();
-
-    if (libusb_ctx) {
-        libusb_exit(libusb_ctx);
+    s32 size{};
+    constexpr u8 rumble_command = 0x11;
+    const u8 p1 = pads[0].enable_vibration;
+    const u8 p2 = pads[1].enable_vibration;
+    const u8 p3 = pads[2].enable_vibration;
+    const u8 p4 = pads[3].enable_vibration;
+    std::array<u8, 5> payload = {rumble_command, p1, p2, p3, p4};
+    const int err =
+        libusb_interrupt_transfer(usb_adapter_handle->get(), output_endpoint, payload.data(),
+                                  static_cast<s32>(payload.size()), &size, 16);
+    if (err) {
+        LOG_DEBUG(Input, "Adapter libusb write failed: {}", libusb_error_name(err));
+        if (output_error_counter++ > 5) {
+            LOG_ERROR(Input, "GC adapter output timeout, Rumble disabled");
+            rumble_enabled = false;
+        }
+        return;
     }
+    output_error_counter = 0;
+    vibration_changed = false;
 }
 
-std::vector<Common::ParamPackage> Adapter::GetInputDevices() const {
+bool GCAdapter::DeviceConnected(std::size_t port) const {
+    return pads[port].type != ControllerTypes::None;
+}
+
+void GCAdapter::Reset() {
+    adapter_scan_thread = {};
+    adapter_input_thread = {};
+    usb_adapter_handle = nullptr;
+    pads = {};
+    libusb_ctx = nullptr;
+}
+
+std::vector<Common::ParamPackage> GCAdapter::GetInputDevices() const {
     std::vector<Common::ParamPackage> devices;
     for (std::size_t port = 0; port < pads.size(); ++port) {
         if (!DeviceConnected(port)) {
             continue;
         }
-        std::string name = fmt::format("Gamecube Controller {}", port + 1);
+        const std::string name = fmt::format("Gamecube Controller {}", port + 1);
         devices.emplace_back(Common::ParamPackage{
-            {"class", "gcpad"},
+            {"engine", "gcpad"},
             {"display", std::move(name)},
             {"port", std::to_string(port)},
         });
@@ -401,8 +401,7 @@ std::vector<Common::ParamPackage> Adapter::GetInputDevices() const {
     return devices;
 }
 
-InputCommon::ButtonMapping Adapter::GetButtonMappingForDevice(
-    const Common::ParamPackage& params) const {
+ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& params) {
     // This list is missing ZL/ZR since those are not considered buttons.
     // We will add those afterwards
     // This list also excludes any button that can't be really mapped
@@ -425,7 +424,7 @@ InputCommon::ButtonMapping Adapter::GetButtonMappingForDevice(
         return {};
     }
 
-    InputCommon::ButtonMapping mapping{};
+    ButtonMapping mapping{};
     for (const auto& [switch_button, gcadapter_button] : switch_to_gcadapter_button) {
         Common::ParamPackage button_params({{"engine", "gcpad"}});
         button_params.Set("port", params.Get("port", 0));
@@ -434,30 +433,30 @@ InputCommon::ButtonMapping Adapter::GetButtonMappingForDevice(
     }
 
     // Add the missing bindings for ZL/ZR
-    static constexpr std::array<std::pair<Settings::NativeButton::Values, PadAxes>, 2>
+    static constexpr std::array<std::tuple<Settings::NativeButton::Values, PadButton, PadAxes>, 2>
         switch_to_gcadapter_axis = {
-            std::pair{Settings::NativeButton::ZL, PadAxes::TriggerLeft},
-            {Settings::NativeButton::ZR, PadAxes::TriggerRight},
+            std::tuple{Settings::NativeButton::ZL, PadButton::TriggerL, PadAxes::TriggerLeft},
+            {Settings::NativeButton::ZR, PadButton::TriggerR, PadAxes::TriggerRight},
         };
-    for (const auto& [switch_button, gcadapter_axis] : switch_to_gcadapter_axis) {
+    for (const auto& [switch_button, gcadapter_buton, gcadapter_axis] : switch_to_gcadapter_axis) {
         Common::ParamPackage button_params({{"engine", "gcpad"}});
         button_params.Set("port", params.Get("port", 0));
-        button_params.Set("button", static_cast<s32>(PadButton::Stick));
+        button_params.Set("button", static_cast<s32>(gcadapter_buton));
         button_params.Set("axis", static_cast<s32>(gcadapter_axis));
         button_params.Set("threshold", 0.5f);
+        button_params.Set("range", 1.9f);
         button_params.Set("direction", "+");
         mapping.insert_or_assign(switch_button, std::move(button_params));
     }
     return mapping;
 }
 
-InputCommon::AnalogMapping Adapter::GetAnalogMappingForDevice(
-    const Common::ParamPackage& params) const {
+AnalogMapping GCAdapter::GetAnalogMappingForDevice(const Common::ParamPackage& params) {
     if (!params.Has("port")) {
         return {};
     }
 
-    InputCommon::AnalogMapping mapping = {};
+    AnalogMapping mapping = {};
     Common::ParamPackage left_analog_params;
     left_analog_params.Set("engine", "gcpad");
     left_analog_params.Set("port", params.Get("port", 0));
@@ -473,34 +472,12 @@ InputCommon::AnalogMapping Adapter::GetAnalogMappingForDevice(
     return mapping;
 }
 
-bool Adapter::DeviceConnected(std::size_t port) const {
-    return pads[port].type != ControllerTypes::None;
+std::string GCAdapter::GetUIName(const Common::ParamPackage& params) const {
+    if (params.Has("button")) {
+        return fmt::format("Button {}", params.Get("button", 0));
+    }
+
+    return "Bad GC Adapter";
 }
 
-void Adapter::BeginConfiguration() {
-    pad_queue.Clear();
-    configuring = true;
-}
-
-void Adapter::EndConfiguration() {
-    pad_queue.Clear();
-    configuring = false;
-}
-
-Common::SPSCQueue<GCPadStatus>& Adapter::GetPadQueue() {
-    return pad_queue;
-}
-
-const Common::SPSCQueue<GCPadStatus>& Adapter::GetPadQueue() const {
-    return pad_queue;
-}
-
-GCController& Adapter::GetPadState(std::size_t port) {
-    return pads.at(port);
-}
-
-const GCController& Adapter::GetPadState(std::size_t port) const {
-    return pads.at(port);
-}
-
-} // namespace GCAdapter
+} // namespace InputCommon
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h
new file mode 100644
index 0000000000..c0bf1ed7ae
--- /dev/null
+++ b/src/input_common/drivers/gc_adapter.h
@@ -0,0 +1,128 @@
+// Copyright 2014 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <mutex>
+#include <stop_token>
+#include <thread>
+
+#include "input_common/input_engine.h"
+
+struct libusb_context;
+struct libusb_device;
+struct libusb_device_handle;
+
+namespace InputCommon {
+
+class LibUSBContext;
+class LibUSBDeviceHandle;
+
+class GCAdapter : public InputCommon::InputEngine {
+public:
+    explicit GCAdapter(const std::string input_engine_);
+    ~GCAdapter();
+
+    bool SetRumble(const PadIdentifier& identifier,
+                   const Input::VibrationStatus vibration) override;
+
+    /// Used for automapping features
+    std::vector<Common::ParamPackage> GetInputDevices() const override;
+    ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override;
+    AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
+    std::string GetUIName(const Common::ParamPackage& params) const override;
+
+private:
+    enum class PadButton {
+        Undefined = 0x0000,
+        ButtonLeft = 0x0001,
+        ButtonRight = 0x0002,
+        ButtonDown = 0x0004,
+        ButtonUp = 0x0008,
+        TriggerZ = 0x0010,
+        TriggerR = 0x0020,
+        TriggerL = 0x0040,
+        ButtonA = 0x0100,
+        ButtonB = 0x0200,
+        ButtonX = 0x0400,
+        ButtonY = 0x0800,
+        ButtonStart = 0x1000,
+    };
+
+    enum class PadAxes : u8 {
+        StickX,
+        StickY,
+        SubstickX,
+        SubstickY,
+        TriggerLeft,
+        TriggerRight,
+        Undefined,
+    };
+
+    enum class ControllerTypes {
+        None,
+        Wired,
+        Wireless,
+    };
+
+    struct GCController {
+        ControllerTypes type = ControllerTypes::None;
+        PadIdentifier identifier{};
+        bool enable_vibration = false;
+        u8 rumble_amplitude{};
+        std::array<u8, 6> axis_origin{};
+        u8 reset_origin_counter{};
+    };
+
+    using AdapterPayload = std::array<u8, 37>;
+
+    void UpdatePadType(std::size_t port, ControllerTypes pad_type);
+    void UpdateControllers(const AdapterPayload& adapter_payload);
+    void UpdateStateButtons(std::size_t port, u8 b1, u8 b2);
+    void UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_payload);
+
+    void AdapterInputThread(std::stop_token stop_token);
+
+    void AdapterScanThread(std::stop_token stop_token);
+
+    bool IsPayloadCorrect(const AdapterPayload& adapter_payload, s32 payload_size);
+
+    /// For use in initialization, querying devices to find the adapter
+    bool Setup();
+
+    /// Returns true if we successfully gain access to GC Adapter
+    bool CheckDeviceAccess();
+
+    /// Captures GC Adapter endpoint address
+    /// Returns true if the endpoint was set correctly
+    bool GetGCEndpoint(libusb_device* device);
+
+    /// Returns true if there is a device connected to port
+    bool DeviceConnected(std::size_t port) const;
+
+    /// For shutting down, clear all data, join all threads, release usb
+    void Reset();
+
+    void UpdateVibrations();
+    // Updates vibration state of all controllers
+    void SendVibrations();
+    std::unique_ptr<LibUSBDeviceHandle> usb_adapter_handle;
+    std::array<GCController, 4> pads;
+
+    std::jthread adapter_input_thread;
+    std::jthread adapter_scan_thread;
+    bool restart_scan_thread{};
+
+    std::unique_ptr<LibUSBContext> libusb_ctx;
+
+    u8 input_endpoint{0};
+    u8 output_endpoint{0};
+    u8 input_error_counter{0};
+    u8 output_error_counter{0};
+    int vibration_counter{0};
+
+    bool rumble_enabled{true};
+    bool vibration_changed{true};
+};
+} // namespace InputCommon
diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp
new file mode 100644
index 0000000000..5e2101b27d
--- /dev/null
+++ b/src/input_common/drivers/tas_input.cpp
@@ -0,0 +1,320 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include <cstring>
+#include <regex>
+#include <fmt/format.h>
+
+#include "common/fs/file.h"
+#include "common/fs/fs_types.h"
+#include "common/fs/path_util.h"
+#include "common/logging/log.h"
+#include "common/settings.h"
+#include "input_common/drivers/tas_input.h"
+
+namespace InputCommon::TasInput {
+
+enum TasAxes : u8 {
+    StickX,
+    StickY,
+    SubstickX,
+    SubstickY,
+    Undefined,
+};
+
+// Supported keywords and buttons from a TAS file
+constexpr std::array<std::pair<std::string_view, TasButton>, 20> text_to_tas_button = {
+    std::pair{"KEY_A", TasButton::BUTTON_A},
+    {"KEY_B", TasButton::BUTTON_B},
+    {"KEY_X", TasButton::BUTTON_X},
+    {"KEY_Y", TasButton::BUTTON_Y},
+    {"KEY_LSTICK", TasButton::STICK_L},
+    {"KEY_RSTICK", TasButton::STICK_R},
+    {"KEY_L", TasButton::TRIGGER_L},
+    {"KEY_R", TasButton::TRIGGER_R},
+    {"KEY_PLUS", TasButton::BUTTON_PLUS},
+    {"KEY_MINUS", TasButton::BUTTON_MINUS},
+    {"KEY_DLEFT", TasButton::BUTTON_LEFT},
+    {"KEY_DUP", TasButton::BUTTON_UP},
+    {"KEY_DRIGHT", TasButton::BUTTON_RIGHT},
+    {"KEY_DDOWN", TasButton::BUTTON_DOWN},
+    {"KEY_SL", TasButton::BUTTON_SL},
+    {"KEY_SR", TasButton::BUTTON_SR},
+    {"KEY_CAPTURE", TasButton::BUTTON_CAPTURE},
+    {"KEY_HOME", TasButton::BUTTON_HOME},
+    {"KEY_ZL", TasButton::TRIGGER_ZL},
+    {"KEY_ZR", TasButton::TRIGGER_ZR},
+};
+
+Tas::Tas(const std::string input_engine_) : InputCommon::InputEngine(input_engine_) {
+    for (size_t player_index = 0; player_index < PLAYER_NUMBER; player_index++) {
+        PadIdentifier identifier{
+            .guid = Common::UUID{},
+            .port = player_index,
+            .pad = 0,
+        };
+        PreSetController(identifier);
+    }
+    ClearInput();
+    if (!Settings::values.tas_enable) {
+        needs_reset = true;
+        return;
+    }
+    LoadTasFiles();
+}
+
+Tas::~Tas() {
+    Stop();
+};
+
+void Tas::LoadTasFiles() {
+    script_length = 0;
+    for (size_t i = 0; i < commands.size(); i++) {
+        LoadTasFile(i);
+        if (commands[i].size() > script_length) {
+            script_length = commands[i].size();
+        }
+    }
+}
+
+void Tas::LoadTasFile(size_t player_index) {
+    if (!commands[player_index].empty()) {
+        commands[player_index].clear();
+    }
+    std::string file =
+        Common::FS::ReadStringFromFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) /
+                                           fmt::format("script0-{}.txt", player_index + 1),
+                                       Common::FS::FileType::BinaryFile);
+    std::stringstream command_line(file);
+    std::string line;
+    int frame_no = 0;
+    while (std::getline(command_line, line, '\n')) {
+        if (line.empty()) {
+            continue;
+        }
+        std::smatch m;
+
+        std::stringstream linestream(line);
+        std::string segment;
+        std::vector<std::string> seglist;
+
+        while (std::getline(linestream, segment, ' ')) {
+            seglist.push_back(segment);
+        }
+
+        if (seglist.size() < 4) {
+            continue;
+        }
+
+        while (frame_no < std::stoi(seglist.at(0))) {
+            commands[player_index].push_back({});
+            frame_no++;
+        }
+
+        TASCommand command = {
+            .buttons = ReadCommandButtons(seglist.at(1)),
+            .l_axis = ReadCommandAxis(seglist.at(2)),
+            .r_axis = ReadCommandAxis(seglist.at(3)),
+        };
+        commands[player_index].push_back(command);
+        frame_no++;
+    }
+    LOG_INFO(Input, "TAS file loaded! {} frames", frame_no);
+}
+
+void Tas::WriteTasFile(std::u8string file_name) {
+    std::string output_text;
+    for (size_t frame = 0; frame < record_commands.size(); frame++) {
+        const TASCommand& line = record_commands[frame];
+        output_text += fmt::format("{} {} {} {} {}\n", frame, WriteCommandButtons(line.buttons),
+                                   WriteCommandAxis(line.l_axis), WriteCommandAxis(line.r_axis));
+    }
+    const auto bytes_written = Common::FS::WriteStringToFile(
+        Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / file_name,
+        Common::FS::FileType::TextFile, output_text);
+    if (bytes_written == output_text.size()) {
+        LOG_INFO(Input, "TAS file written to file!");
+    } else {
+        LOG_ERROR(Input, "Writing the TAS-file has failed! {} / {} bytes written", bytes_written,
+                  output_text.size());
+    }
+}
+
+void Tas::RecordInput(u32 buttons, TasAnalog left_axis, TasAnalog right_axis) {
+    last_input = {
+        .buttons = buttons,
+        .l_axis = FlipAxisY(left_axis),
+        .r_axis = FlipAxisY(right_axis),
+    };
+}
+
+TasAnalog Tas::FlipAxisY(TasAnalog old) {
+    return {
+        .x = old.x,
+        .y = -old.y,
+    };
+}
+
+std::tuple<TasState, size_t, size_t> Tas::GetStatus() const {
+    TasState state;
+    if (is_recording) {
+        return {TasState::Recording, 0, record_commands.size()};
+    }
+
+    if (is_running) {
+        state = TasState::Running;
+    } else {
+        state = TasState::Stopped;
+    }
+
+    return {state, current_command, script_length};
+}
+
+void Tas::UpdateThread() {
+    if (!Settings::values.tas_enable) {
+        if (is_running) {
+            Stop();
+        }
+        return;
+    }
+
+    if (is_recording) {
+        record_commands.push_back(last_input);
+    }
+    if (needs_reset) {
+        current_command = 0;
+        needs_reset = false;
+        LoadTasFiles();
+        LOG_DEBUG(Input, "tas_reset done");
+    }
+
+    if (!is_running) {
+        ClearInput();
+        return;
+    }
+    if (current_command < script_length) {
+        LOG_DEBUG(Input, "Playing TAS {}/{}", current_command, script_length);
+        size_t frame = current_command++;
+        for (size_t player_index = 0; player_index < commands.size(); player_index++) {
+            TASCommand command{};
+            if (frame < commands[player_index].size()) {
+                command = commands[player_index][frame];
+            }
+
+            PadIdentifier identifier{
+                .guid = Common::UUID{},
+                .port = player_index,
+                .pad = 0,
+            };
+            for (std::size_t i = 0; i < sizeof(command.buttons); ++i) {
+                const bool button_status = (command.buttons & (1U << i)) != 0;
+                const int button = static_cast<int>(i);
+                SetButton(identifier, button, button_status);
+            }
+            SetAxis(identifier, TasAxes::StickX, command.l_axis.x);
+            SetAxis(identifier, TasAxes::StickY, command.l_axis.y);
+            SetAxis(identifier, TasAxes::SubstickX, command.r_axis.x);
+            SetAxis(identifier, TasAxes::SubstickY, command.r_axis.y);
+        }
+    } else {
+        is_running = Settings::values.tas_loop.GetValue();
+        current_command = 0;
+        ClearInput();
+    }
+}
+
+void Tas::ClearInput() {
+    ResetButtonState();
+    ResetAnalogState();
+}
+
+TasAnalog Tas::ReadCommandAxis(const std::string& line) const {
+    std::stringstream linestream(line);
+    std::string segment;
+    std::vector<std::string> seglist;
+
+    while (std::getline(linestream, segment, ';')) {
+        seglist.push_back(segment);
+    }
+
+    const float x = std::stof(seglist.at(0)) / 32767.0f;
+    const float y = std::stof(seglist.at(1)) / 32767.0f;
+
+    return {x, y};
+}
+
+u32 Tas::ReadCommandButtons(const std::string& data) const {
+    std::stringstream button_text(data);
+    std::string line;
+    u32 buttons = 0;
+    while (std::getline(button_text, line, ';')) {
+        for (auto [text, tas_button] : text_to_tas_button) {
+            if (text == line) {
+                buttons |= static_cast<u32>(tas_button);
+                break;
+            }
+        }
+    }
+    return buttons;
+}
+
+std::string Tas::WriteCommandButtons(u32 buttons) const {
+    std::string returns = "";
+    for (auto [text_button, tas_button] : text_to_tas_button) {
+        if ((buttons & static_cast<u32>(tas_button)) != 0)
+            returns += fmt::format("{};", text_button.substr(4));
+    }
+    return returns.empty() ? "NONE" : returns.substr(2);
+}
+
+std::string Tas::WriteCommandAxis(TasAnalog analog) const {
+    return fmt::format("{};{}", analog.x * 32767, analog.y * 32767);
+}
+
+void Tas::StartStop() {
+    if (!Settings::values.tas_enable) {
+        return;
+    }
+    if (is_running) {
+        Stop();
+    } else {
+        is_running = true;
+    }
+}
+
+void Tas::Stop() {
+    is_running = false;
+}
+
+void Tas::Reset() {
+    if (!Settings::values.tas_enable) {
+        return;
+    }
+    needs_reset = true;
+}
+
+bool Tas::Record() {
+    if (!Settings::values.tas_enable) {
+        return true;
+    }
+    is_recording = !is_recording;
+    return is_recording;
+}
+
+void Tas::SaveRecording(bool overwrite_file) {
+    if (is_recording) {
+        return;
+    }
+    if (record_commands.empty()) {
+        return;
+    }
+    WriteTasFile(u8"record.txt");
+    if (overwrite_file) {
+        WriteTasFile(u8"script0-1.txt");
+    }
+    needs_reset = true;
+    record_commands.clear();
+}
+
+} // namespace InputCommon::TasInput
diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h
new file mode 100644
index 0000000000..9fadc118b7
--- /dev/null
+++ b/src/input_common/drivers/tas_input.h
@@ -0,0 +1,200 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+
+#include "common/common_types.h"
+#include "common/settings_input.h"
+#include "input_common/input_engine.h"
+#include "input_common/main.h"
+
+/*
+To play back TAS scripts on Yuzu, select the folder with scripts in the configuration menu below
+Tools -> Configure TAS. The file itself has normal text format and has to be called script0-1.txt
+for controller 1, script0-2.txt for controller 2 and so forth (with max. 8 players).
+
+A script file has the same format as TAS-nx uses, so final files will look like this:
+
+1 KEY_B 0;0 0;0
+6 KEY_ZL 0;0 0;0
+41 KEY_ZL;KEY_Y 0;0 0;0
+43 KEY_X;KEY_A 32767;0 0;0
+44 KEY_A 32767;0 0;0
+45 KEY_A 32767;0 0;0
+46 KEY_A 32767;0 0;0
+47 KEY_A 32767;0 0;0
+
+After placing the file at the correct location, it can be read into Yuzu with the (default) hotkey
+CTRL+F6 (refresh). In the bottom left corner, it will display the amount of frames the script file
+has. Playback can be started or stopped using CTRL+F5.
+
+However, for playback to actually work, the correct input device has to be selected: In the Controls
+menu, select TAS from the device list for the controller that the script should be played on.
+
+Recording a new script file is really simple: Just make sure that the proper device (not TAS) is
+connected on P1, and press CTRL+F7 to start recording. When done, just press the same keystroke
+again (CTRL+F7). The new script will be saved at the location previously selected, as the filename
+record.txt.
+
+For debugging purposes, the common controller debugger can be used (View -> Debugging -> Controller
+P1).
+*/
+
+namespace InputCommon::TasInput {
+
+constexpr size_t PLAYER_NUMBER = 10;
+
+enum class TasButton : u32 {
+    BUTTON_A = 1U << 0,
+    BUTTON_B = 1U << 1,
+    BUTTON_X = 1U << 2,
+    BUTTON_Y = 1U << 3,
+    STICK_L = 1U << 4,
+    STICK_R = 1U << 5,
+    TRIGGER_L = 1U << 6,
+    TRIGGER_R = 1U << 7,
+    TRIGGER_ZL = 1U << 8,
+    TRIGGER_ZR = 1U << 9,
+    BUTTON_PLUS = 1U << 10,
+    BUTTON_MINUS = 1U << 11,
+    BUTTON_LEFT = 1U << 12,
+    BUTTON_UP = 1U << 13,
+    BUTTON_RIGHT = 1U << 14,
+    BUTTON_DOWN = 1U << 15,
+    BUTTON_SL = 1U << 16,
+    BUTTON_SR = 1U << 17,
+    BUTTON_HOME = 1U << 18,
+    BUTTON_CAPTURE = 1U << 19,
+};
+
+struct TasAnalog {
+    float x{};
+    float y{};
+};
+
+enum class TasState {
+    Running,
+    Recording,
+    Stopped,
+};
+
+class Tas final : public InputCommon::InputEngine {
+public:
+    explicit Tas(const std::string input_engine_);
+    ~Tas();
+
+    /**
+     * Changes the input status that will be stored in each frame
+     * @param buttons: bitfield with the status of the buttons
+     * @param left_axis: value of the left axis
+     * @param right_axis: value of the right axis
+     */
+    void RecordInput(u32 buttons, TasAnalog left_axis, TasAnalog right_axis);
+
+    // Main loop that records or executes input
+    void UpdateThread();
+
+    //  Sets the flag to start or stop the TAS command excecution and swaps controllers profiles
+    void StartStop();
+
+    //  Stop the TAS and reverts any controller profile
+    void Stop();
+
+    // Sets the flag to reload the file and start from the begining in the next update
+    void Reset();
+
+    /**
+     * Sets the flag to enable or disable recording of inputs
+     * @return Returns true if the current recording status is enabled
+     */
+    bool Record();
+
+    /**
+     * Saves contents of record_commands on a file
+     * @param overwrite_file: Indicates if player 1 should be overwritten
+     */
+    void SaveRecording(bool overwrite_file);
+
+    /**
+     * Returns the current status values of TAS playback/recording
+     * @return Tuple of
+     * TasState indicating the current state out of Running ;
+     * Current playback progress ;
+     * Total length of script file currently loaded or being recorded
+     */
+    std::tuple<TasState, size_t, size_t> GetStatus() const;
+
+private:
+    struct TASCommand {
+        u32 buttons{};
+        TasAnalog l_axis{};
+        TasAnalog r_axis{};
+    };
+
+    /// Loads TAS files from all players
+    void LoadTasFiles();
+
+    /** Loads TAS file from the specified player
+     * @param player_index: player number where data is going to be stored
+     */
+    void LoadTasFile(size_t player_index);
+
+    /** Writes a TAS file from the recorded commands
+     * @param file_name: name of the file to be written
+     */
+    void WriteTasFile(std::u8string file_name);
+
+    /** Inverts the Y axis polarity
+     * @param old: value of the axis
+     * @return new value of the axis
+     */
+    TasAnalog FlipAxisY(TasAnalog old);
+
+    /**
+     * Parses a string containing the axis values. X and Y have a range from -32767 to 32767
+     * @param line: string containing axis values with the following format "x;y"
+     * @return Returns a TAS analog object with axis values with range from -1.0 to 1.0
+     */
+    TasAnalog ReadCommandAxis(const std::string& line) const;
+
+    /**
+     * Parses a string containing the button values. Each button is represented by it's text format
+     * specified in text_to_tas_button array
+     * @param line: string containing button name with the following format "a;b;c;d..."
+     * @return Returns a u32 with each bit representing the status of a button
+     */
+    u32 ReadCommandButtons(const std::string& line) const;
+
+    /**
+     * Reset state of all players
+     */
+    void ClearInput();
+
+    /**
+     * Converts an u32 containing the button status into the text equivalent
+     * @param buttons: bitfield with the status of the buttons
+     * @return Returns a string with the name of the buttons to be written to the file
+     */
+    std::string WriteCommandButtons(u32 buttons) const;
+
+    /**
+     * Converts an TAS analog object containing the axis status into the text equivalent
+     * @param data: value of the axis
+     * @return A string with the value of the axis to be written to the file
+     */
+    std::string WriteCommandAxis(TasAnalog data) const;
+
+    size_t script_length{0};
+    bool is_old_input_saved{false};
+    bool is_recording{false};
+    bool is_running{false};
+    bool needs_reset{false};
+    std::array<std::vector<TASCommand>, PLAYER_NUMBER> commands{};
+    std::vector<TASCommand> record_commands{};
+    size_t current_command{0};
+    TASCommand last_input{}; // only used for recording
+};
+} // namespace InputCommon::TasInput
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h
deleted file mode 100644
index e5de5e94fc..0000000000
--- a/src/input_common/gcadapter/gc_adapter.h
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2014 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-#include <algorithm>
-#include <functional>
-#include <mutex>
-#include <thread>
-#include <unordered_map>
-#include "common/common_types.h"
-#include "common/threadsafe_queue.h"
-#include "input_common/main.h"
-
-struct libusb_context;
-struct libusb_device;
-struct libusb_device_handle;
-
-namespace GCAdapter {
-
-enum class PadButton {
-    Undefined = 0x0000,
-    ButtonLeft = 0x0001,
-    ButtonRight = 0x0002,
-    ButtonDown = 0x0004,
-    ButtonUp = 0x0008,
-    TriggerZ = 0x0010,
-    TriggerR = 0x0020,
-    TriggerL = 0x0040,
-    ButtonA = 0x0100,
-    ButtonB = 0x0200,
-    ButtonX = 0x0400,
-    ButtonY = 0x0800,
-    ButtonStart = 0x1000,
-    // Below is for compatibility with "AxisButton" type
-    Stick = 0x2000,
-};
-
-enum class PadAxes : u8 {
-    StickX,
-    StickY,
-    SubstickX,
-    SubstickY,
-    TriggerLeft,
-    TriggerRight,
-    Undefined,
-};
-
-enum class ControllerTypes {
-    None,
-    Wired,
-    Wireless,
-};
-
-struct GCPadStatus {
-    std::size_t port{};
-
-    PadButton button{PadButton::Undefined}; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits
-
-    PadAxes axis{PadAxes::Undefined};
-    s16 axis_value{};
-    u8 axis_threshold{50};
-};
-
-struct GCController {
-    ControllerTypes type{};
-    bool enable_vibration{};
-    u8 rumble_amplitude{};
-    u16 buttons{};
-    PadButton last_button{};
-    std::array<s16, 6> axis_values{};
-    std::array<u8, 6> axis_origin{};
-    u8 reset_origin_counter{};
-};
-
-class Adapter {
-public:
-    Adapter();
-    ~Adapter();
-
-    /// Request a vibration for a controller
-    bool RumblePlay(std::size_t port, u8 amplitude);
-
-    /// Used for polling
-    void BeginConfiguration();
-    void EndConfiguration();
-
-    Common::SPSCQueue<GCPadStatus>& GetPadQueue();
-    const Common::SPSCQueue<GCPadStatus>& GetPadQueue() const;
-
-    GCController& GetPadState(std::size_t port);
-    const GCController& GetPadState(std::size_t port) const;
-
-    /// Returns true if there is a device connected to port
-    bool DeviceConnected(std::size_t port) const;
-
-    /// Used for automapping features
-    std::vector<Common::ParamPackage> GetInputDevices() const;
-    InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const;
-    InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const;
-
-private:
-    using AdapterPayload = std::array<u8, 37>;
-
-    void UpdatePadType(std::size_t port, ControllerTypes pad_type);
-    void UpdateControllers(const AdapterPayload& adapter_payload);
-    void UpdateYuzuSettings(std::size_t port);
-    void UpdateStateButtons(std::size_t port, u8 b1, u8 b2);
-    void UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_payload);
-    void UpdateVibrations();
-
-    void AdapterInputThread();
-
-    void AdapterScanThread();
-
-    bool IsPayloadCorrect(const AdapterPayload& adapter_payload, s32 payload_size);
-
-    // Updates vibration state of all controllers
-    void SendVibrations();
-
-    /// For use in initialization, querying devices to find the adapter
-    void Setup();
-
-    /// Resets status of all GC controller devices to a disconnected state
-    void ResetDevices();
-
-    /// Resets status of device connected to a disconnected state
-    void ResetDevice(std::size_t port);
-
-    /// Returns true if we successfully gain access to GC Adapter
-    bool CheckDeviceAccess();
-
-    /// Captures GC Adapter endpoint address
-    /// Returns true if the endpoint was set correctly
-    bool GetGCEndpoint(libusb_device* device);
-
-    /// For shutting down, clear all data, join all threads, release usb
-    void Reset();
-
-    // Join all threads
-    void JoinThreads();
-
-    // Release usb handles
-    void ClearLibusbHandle();
-
-    libusb_device_handle* usb_adapter_handle = nullptr;
-    std::array<GCController, 4> pads;
-    Common::SPSCQueue<GCPadStatus> pad_queue;
-
-    std::thread adapter_input_thread;
-    std::thread adapter_scan_thread;
-    bool adapter_input_thread_running;
-    bool adapter_scan_thread_running;
-    bool restart_scan_thread;
-
-    libusb_context* libusb_ctx;
-
-    u8 input_endpoint{0};
-    u8 output_endpoint{0};
-    u8 input_error_counter{0};
-    u8 output_error_counter{0};
-    int vibration_counter{0};
-
-    bool configuring{false};
-    bool rumble_enabled{true};
-    bool vibration_changed{true};
-};
-} // namespace GCAdapter
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp
deleted file mode 100644
index 1b6ded8d60..0000000000
--- a/src/input_common/gcadapter/gc_poller.cpp
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <atomic>
-#include <list>
-#include <mutex>
-#include <utility>
-#include "common/assert.h"
-#include "common/threadsafe_queue.h"
-#include "input_common/gcadapter/gc_adapter.h"
-#include "input_common/gcadapter/gc_poller.h"
-
-namespace InputCommon {
-
-class GCButton final : public Input::ButtonDevice {
-public:
-    explicit GCButton(u32 port_, s32 button_, const GCAdapter::Adapter* adapter)
-        : port(port_), button(button_), gcadapter(adapter) {}
-
-    ~GCButton() override;
-
-    bool GetStatus() const override {
-        if (gcadapter->DeviceConnected(port)) {
-            return (gcadapter->GetPadState(port).buttons & button) != 0;
-        }
-        return false;
-    }
-
-private:
-    const u32 port;
-    const s32 button;
-    const GCAdapter::Adapter* gcadapter;
-};
-
-class GCAxisButton final : public Input::ButtonDevice {
-public:
-    explicit GCAxisButton(u32 port_, u32 axis_, float threshold_, bool trigger_if_greater_,
-                          const GCAdapter::Adapter* adapter)
-        : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_),
-          gcadapter(adapter) {}
-
-    bool GetStatus() const override {
-        if (gcadapter->DeviceConnected(port)) {
-            const float current_axis_value = gcadapter->GetPadState(port).axis_values.at(axis);
-            const float axis_value = current_axis_value / 128.0f;
-            if (trigger_if_greater) {
-                // TODO: Might be worthwile to set a slider for the trigger threshold. It is
-                // currently always set to 0.5 in configure_input_player.cpp ZL/ZR HandleClick
-                return axis_value > threshold;
-            }
-            return axis_value < -threshold;
-        }
-        return false;
-    }
-
-private:
-    const u32 port;
-    const u32 axis;
-    float threshold;
-    bool trigger_if_greater;
-    const GCAdapter::Adapter* gcadapter;
-};
-
-GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
-    : adapter(std::move(adapter_)) {}
-
-GCButton::~GCButton() = default;
-
-std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::ParamPackage& params) {
-    const auto button_id = params.Get("button", 0);
-    const auto port = static_cast<u32>(params.Get("port", 0));
-
-    constexpr s32 PAD_STICK_ID = static_cast<s32>(GCAdapter::PadButton::Stick);
-
-    // button is not an axis/stick button
-    if (button_id != PAD_STICK_ID) {
-        return std::make_unique<GCButton>(port, button_id, adapter.get());
-    }
-
-    // For Axis buttons, used by the binary sticks.
-    if (button_id == PAD_STICK_ID) {
-        const int axis = params.Get("axis", 0);
-        const float threshold = params.Get("threshold", 0.25f);
-        const std::string direction_name = params.Get("direction", "");
-        bool trigger_if_greater;
-        if (direction_name == "+") {
-            trigger_if_greater = true;
-        } else if (direction_name == "-") {
-            trigger_if_greater = false;
-        } else {
-            trigger_if_greater = true;
-            LOG_ERROR(Input, "Unknown direction {}", direction_name);
-        }
-        return std::make_unique<GCAxisButton>(port, axis, threshold, trigger_if_greater,
-                                              adapter.get());
-    }
-
-    return nullptr;
-}
-
-Common::ParamPackage GCButtonFactory::GetNextInput() const {
-    Common::ParamPackage params;
-    GCAdapter::GCPadStatus pad;
-    auto& queue = adapter->GetPadQueue();
-    while (queue.Pop(pad)) {
-        // This while loop will break on the earliest detected button
-        params.Set("engine", "gcpad");
-        params.Set("port", static_cast<s32>(pad.port));
-        if (pad.button != GCAdapter::PadButton::Undefined) {
-            params.Set("button", static_cast<u16>(pad.button));
-        }
-
-        // For Axis button implementation
-        if (pad.axis != GCAdapter::PadAxes::Undefined) {
-            params.Set("axis", static_cast<u8>(pad.axis));
-            params.Set("button", static_cast<u16>(GCAdapter::PadButton::Stick));
-            params.Set("threshold", "0.25");
-            if (pad.axis_value > 0) {
-                params.Set("direction", "+");
-            } else {
-                params.Set("direction", "-");
-            }
-            break;
-        }
-    }
-    return params;
-}
-
-void GCButtonFactory::BeginConfiguration() {
-    polling = true;
-    adapter->BeginConfiguration();
-}
-
-void GCButtonFactory::EndConfiguration() {
-    polling = false;
-    adapter->EndConfiguration();
-}
-
-class GCAnalog final : public Input::AnalogDevice {
-public:
-    explicit GCAnalog(u32 port_, u32 axis_x_, u32 axis_y_, bool invert_x_, bool invert_y_,
-                      float deadzone_, float range_, const GCAdapter::Adapter* adapter)
-        : port(port_), axis_x(axis_x_), axis_y(axis_y_), invert_x(invert_x_), invert_y(invert_y_),
-          deadzone(deadzone_), range(range_), gcadapter(adapter) {}
-
-    float GetAxis(u32 axis) const {
-        if (gcadapter->DeviceConnected(port)) {
-            std::lock_guard lock{mutex};
-            const auto axis_value =
-                static_cast<float>(gcadapter->GetPadState(port).axis_values.at(axis));
-            return (axis_value) / (100.0f * range);
-        }
-        return 0.0f;
-    }
-
-    std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
-        float x = GetAxis(analog_axis_x);
-        float y = GetAxis(analog_axis_y);
-        if (invert_x) {
-            x = -x;
-        }
-        if (invert_y) {
-            y = -y;
-        }
-        // Make sure the coordinates are in the unit circle,
-        // otherwise normalize it.
-        float r = x * x + y * y;
-        if (r > 1.0f) {
-            r = std::sqrt(r);
-            x /= r;
-            y /= r;
-        }
-
-        return {x, y};
-    }
-
-    std::tuple<float, float> GetStatus() const override {
-        const auto [x, y] = GetAnalog(axis_x, axis_y);
-        const float r = std::sqrt((x * x) + (y * y));
-        if (r > deadzone) {
-            return {x / r * (r - deadzone) / (1 - deadzone),
-                    y / r * (r - deadzone) / (1 - deadzone)};
-        }
-        return {0.0f, 0.0f};
-    }
-
-    std::tuple<float, float> GetRawStatus() const override {
-        const float x = GetAxis(axis_x);
-        const float y = GetAxis(axis_y);
-        return {x, y};
-    }
-
-    Input::AnalogProperties GetAnalogProperties() const override {
-        return {deadzone, range, 0.5f};
-    }
-
-    bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
-        const auto [x, y] = GetStatus();
-        const float directional_deadzone = 0.5f;
-        switch (direction) {
-        case Input::AnalogDirection::RIGHT:
-            return x > directional_deadzone;
-        case Input::AnalogDirection::LEFT:
-            return x < -directional_deadzone;
-        case Input::AnalogDirection::UP:
-            return y > directional_deadzone;
-        case Input::AnalogDirection::DOWN:
-            return y < -directional_deadzone;
-        }
-        return false;
-    }
-
-private:
-    const u32 port;
-    const u32 axis_x;
-    const u32 axis_y;
-    const bool invert_x;
-    const bool invert_y;
-    const float deadzone;
-    const float range;
-    const GCAdapter::Adapter* gcadapter;
-    mutable std::mutex mutex;
-};
-
-/// An analog device factory that creates analog devices from GC Adapter
-GCAnalogFactory::GCAnalogFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
-    : adapter(std::move(adapter_)) {}
-
-/**
- * Creates analog device from joystick axes
- * @param params contains parameters for creating the device:
- *     - "port": the nth gcpad on the adapter
- *     - "axis_x": the index of the axis to be bind as x-axis
- *     - "axis_y": the index of the axis to be bind as y-axis
- */
-std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::ParamPackage& params) {
-    const auto port = static_cast<u32>(params.Get("port", 0));
-    const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
-    const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
-    const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
-    const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
-    const std::string invert_x_value = params.Get("invert_x", "+");
-    const std::string invert_y_value = params.Get("invert_y", "+");
-    const bool invert_x = invert_x_value == "-";
-    const bool invert_y = invert_y_value == "-";
-
-    return std::make_unique<GCAnalog>(port, axis_x, axis_y, invert_x, invert_y, deadzone, range,
-                                      adapter.get());
-}
-
-void GCAnalogFactory::BeginConfiguration() {
-    polling = true;
-    adapter->BeginConfiguration();
-}
-
-void GCAnalogFactory::EndConfiguration() {
-    polling = false;
-    adapter->EndConfiguration();
-}
-
-Common::ParamPackage GCAnalogFactory::GetNextInput() {
-    GCAdapter::GCPadStatus pad;
-    Common::ParamPackage params;
-    auto& queue = adapter->GetPadQueue();
-    while (queue.Pop(pad)) {
-        if (pad.button != GCAdapter::PadButton::Undefined) {
-            params.Set("engine", "gcpad");
-            params.Set("port", static_cast<s32>(pad.port));
-            params.Set("button", static_cast<u16>(pad.button));
-            return params;
-        }
-        if (pad.axis == GCAdapter::PadAxes::Undefined ||
-            std::abs(static_cast<float>(pad.axis_value) / 128.0f) < 0.1f) {
-            continue;
-        }
-        // An analog device needs two axes, so we need to store the axis for later and wait for
-        // a second input event. The axes also must be from the same joystick.
-        const u8 axis = static_cast<u8>(pad.axis);
-        if (axis == 0 || axis == 1) {
-            analog_x_axis = 0;
-            analog_y_axis = 1;
-            controller_number = static_cast<s32>(pad.port);
-            break;
-        }
-        if (axis == 2 || axis == 3) {
-            analog_x_axis = 2;
-            analog_y_axis = 3;
-            controller_number = static_cast<s32>(pad.port);
-            break;
-        }
-
-        if (analog_x_axis == -1) {
-            analog_x_axis = axis;
-            controller_number = static_cast<s32>(pad.port);
-        } else if (analog_y_axis == -1 && analog_x_axis != axis &&
-                   controller_number == static_cast<s32>(pad.port)) {
-            analog_y_axis = axis;
-            break;
-        }
-    }
-    if (analog_x_axis != -1 && analog_y_axis != -1) {
-        params.Set("engine", "gcpad");
-        params.Set("port", controller_number);
-        params.Set("axis_x", analog_x_axis);
-        params.Set("axis_y", analog_y_axis);
-        params.Set("invert_x", "+");
-        params.Set("invert_y", "+");
-        analog_x_axis = -1;
-        analog_y_axis = -1;
-        controller_number = -1;
-        return params;
-    }
-    return params;
-}
-
-class GCVibration final : public Input::VibrationDevice {
-public:
-    explicit GCVibration(u32 port_, GCAdapter::Adapter* adapter)
-        : port(port_), gcadapter(adapter) {}
-
-    u8 GetStatus() const override {
-        return gcadapter->RumblePlay(port, 0);
-    }
-
-    bool SetRumblePlay(f32 amp_low, [[maybe_unused]] f32 freq_low, f32 amp_high,
-                       [[maybe_unused]] f32 freq_high) const override {
-        const auto mean_amplitude = (amp_low + amp_high) * 0.5f;
-        const auto processed_amplitude =
-            static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8);
-
-        return gcadapter->RumblePlay(port, processed_amplitude);
-    }
-
-private:
-    const u32 port;
-    GCAdapter::Adapter* gcadapter;
-};
-
-/// An vibration device factory that creates vibration devices from GC Adapter
-GCVibrationFactory::GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
-    : adapter(std::move(adapter_)) {}
-
-/**
- * Creates a vibration device from a joystick
- * @param params contains parameters for creating the device:
- *     - "port": the nth gcpad on the adapter
- */
-std::unique_ptr<Input::VibrationDevice> GCVibrationFactory::Create(
-    const Common::ParamPackage& params) {
-    const auto port = static_cast<u32>(params.Get("port", 0));
-
-    return std::make_unique<GCVibration>(port, adapter.get());
-}
-
-} // namespace InputCommon
diff --git a/src/input_common/gcadapter/gc_poller.h b/src/input_common/gcadapter/gc_poller.h
deleted file mode 100644
index d1271e3ead..0000000000
--- a/src/input_common/gcadapter/gc_poller.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include "core/frontend/input.h"
-#include "input_common/gcadapter/gc_adapter.h"
-
-namespace InputCommon {
-
-/**
- * A button device factory representing a gcpad. It receives gcpad events and forward them
- * to all button devices it created.
- */
-class GCButtonFactory final : public Input::Factory<Input::ButtonDevice> {
-public:
-    explicit GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_);
-
-    /**
-     * Creates a button device from a button press
-     * @param params contains parameters for creating the device:
-     *     - "code": the code of the key to bind with the button
-     */
-    std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override;
-
-    Common::ParamPackage GetNextInput() const;
-
-    /// For device input configuration/polling
-    void BeginConfiguration();
-    void EndConfiguration();
-
-    bool IsPolling() const {
-        return polling;
-    }
-
-private:
-    std::shared_ptr<GCAdapter::Adapter> adapter;
-    bool polling = false;
-};
-
-/// An analog device factory that creates analog devices from GC Adapter
-class GCAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
-public:
-    explicit GCAnalogFactory(std::shared_ptr<GCAdapter::Adapter> adapter_);
-
-    std::unique_ptr<Input::AnalogDevice> Create(const Common::ParamPackage& params) override;
-    Common::ParamPackage GetNextInput();
-
-    /// For device input configuration/polling
-    void BeginConfiguration();
-    void EndConfiguration();
-
-    bool IsPolling() const {
-        return polling;
-    }
-
-private:
-    std::shared_ptr<GCAdapter::Adapter> adapter;
-    int analog_x_axis = -1;
-    int analog_y_axis = -1;
-    int controller_number = -1;
-    bool polling = false;
-};
-
-/// A vibration device factory creates vibration devices from GC Adapter
-class GCVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
-public:
-    explicit GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_);
-
-    std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override;
-
-private:
-    std::shared_ptr<GCAdapter::Adapter> adapter;
-};
-
-} // namespace InputCommon

From dc3ab9e11068998ffd419f65f00fb336585b8e8c Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 17:26:08 -0500
Subject: [PATCH 11/88] input_common: Rewrite tas input

---
 src/input_common/CMakeLists.txt     |   6 +-
 src/input_common/tas/tas_input.cpp  | 455 ----------------------------
 src/input_common/tas/tas_input.h    | 237 ---------------
 src/input_common/tas/tas_poller.cpp | 101 ------
 src/input_common/tas/tas_poller.h   |  43 ---
 5 files changed, 2 insertions(+), 840 deletions(-)
 delete mode 100644 src/input_common/tas/tas_input.cpp
 delete mode 100644 src/input_common/tas/tas_input.h
 delete mode 100644 src/input_common/tas/tas_poller.cpp
 delete mode 100644 src/input_common/tas/tas_poller.h

diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index c8871513ce..19270dc842 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -5,6 +5,8 @@ add_library(input_common STATIC
     drivers/keyboard.h
     drivers/mouse.cpp
     drivers/mouse.h
+    drivers/tas_input.cpp
+    drivers/tas_input.h
     drivers/touch_screen.cpp
     drivers/touch_screen.h
     helpers/stick_from_buttons.cpp
@@ -27,10 +29,6 @@ add_library(input_common STATIC
     motion_input.h
     sdl/sdl.cpp
     sdl/sdl.h
-    tas/tas_input.cpp
-    tas/tas_input.h
-    tas/tas_poller.cpp
-    tas/tas_poller.h
     udp/client.cpp
     udp/client.h
     udp/udp.cpp
diff --git a/src/input_common/tas/tas_input.cpp b/src/input_common/tas/tas_input.cpp
deleted file mode 100644
index 1598092b61..0000000000
--- a/src/input_common/tas/tas_input.cpp
+++ /dev/null
@@ -1,455 +0,0 @@
-// Copyright 2021 yuzu Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#include <cstring>
-#include <regex>
-
-#include "common/fs/file.h"
-#include "common/fs/fs_types.h"
-#include "common/fs/path_util.h"
-#include "common/logging/log.h"
-#include "common/settings.h"
-#include "input_common/tas/tas_input.h"
-
-namespace TasInput {
-
-// Supported keywords and buttons from a TAS file
-constexpr std::array<std::pair<std::string_view, TasButton>, 20> text_to_tas_button = {
-    std::pair{"KEY_A", TasButton::BUTTON_A},
-    {"KEY_B", TasButton::BUTTON_B},
-    {"KEY_X", TasButton::BUTTON_X},
-    {"KEY_Y", TasButton::BUTTON_Y},
-    {"KEY_LSTICK", TasButton::STICK_L},
-    {"KEY_RSTICK", TasButton::STICK_R},
-    {"KEY_L", TasButton::TRIGGER_L},
-    {"KEY_R", TasButton::TRIGGER_R},
-    {"KEY_PLUS", TasButton::BUTTON_PLUS},
-    {"KEY_MINUS", TasButton::BUTTON_MINUS},
-    {"KEY_DLEFT", TasButton::BUTTON_LEFT},
-    {"KEY_DUP", TasButton::BUTTON_UP},
-    {"KEY_DRIGHT", TasButton::BUTTON_RIGHT},
-    {"KEY_DDOWN", TasButton::BUTTON_DOWN},
-    {"KEY_SL", TasButton::BUTTON_SL},
-    {"KEY_SR", TasButton::BUTTON_SR},
-    {"KEY_CAPTURE", TasButton::BUTTON_CAPTURE},
-    {"KEY_HOME", TasButton::BUTTON_HOME},
-    {"KEY_ZL", TasButton::TRIGGER_ZL},
-    {"KEY_ZR", TasButton::TRIGGER_ZR},
-};
-
-Tas::Tas() {
-    if (!Settings::values.tas_enable) {
-        needs_reset = true;
-        return;
-    }
-    LoadTasFiles();
-}
-
-Tas::~Tas() {
-    Stop();
-};
-
-void Tas::LoadTasFiles() {
-    script_length = 0;
-    for (size_t i = 0; i < commands.size(); i++) {
-        LoadTasFile(i);
-        if (commands[i].size() > script_length) {
-            script_length = commands[i].size();
-        }
-    }
-}
-
-void Tas::LoadTasFile(size_t player_index) {
-    if (!commands[player_index].empty()) {
-        commands[player_index].clear();
-    }
-    std::string file =
-        Common::FS::ReadStringFromFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) /
-                                           fmt::format("script0-{}.txt", player_index + 1),
-                                       Common::FS::FileType::BinaryFile);
-    std::stringstream command_line(file);
-    std::string line;
-    int frame_no = 0;
-    while (std::getline(command_line, line, '\n')) {
-        if (line.empty()) {
-            continue;
-        }
-        LOG_DEBUG(Input, "Loading line: {}", line);
-        std::smatch m;
-
-        std::stringstream linestream(line);
-        std::string segment;
-        std::vector<std::string> seglist;
-
-        while (std::getline(linestream, segment, ' ')) {
-            seglist.push_back(segment);
-        }
-
-        if (seglist.size() < 4) {
-            continue;
-        }
-
-        while (frame_no < std::stoi(seglist.at(0))) {
-            commands[player_index].push_back({});
-            frame_no++;
-        }
-
-        TASCommand command = {
-            .buttons = ReadCommandButtons(seglist.at(1)),
-            .l_axis = ReadCommandAxis(seglist.at(2)),
-            .r_axis = ReadCommandAxis(seglist.at(3)),
-        };
-        commands[player_index].push_back(command);
-        frame_no++;
-    }
-    LOG_INFO(Input, "TAS file loaded! {} frames", frame_no);
-}
-
-void Tas::WriteTasFile(std::u8string file_name) {
-    std::string output_text;
-    for (size_t frame = 0; frame < record_commands.size(); frame++) {
-        if (!output_text.empty()) {
-            output_text += "\n";
-        }
-        const TASCommand& line = record_commands[frame];
-        output_text += std::to_string(frame) + " " + WriteCommandButtons(line.buttons) + " " +
-                       WriteCommandAxis(line.l_axis) + " " + WriteCommandAxis(line.r_axis);
-    }
-    const auto bytes_written = Common::FS::WriteStringToFile(
-        Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / file_name,
-        Common::FS::FileType::TextFile, output_text);
-    if (bytes_written == output_text.size()) {
-        LOG_INFO(Input, "TAS file written to file!");
-    } else {
-        LOG_ERROR(Input, "Writing the TAS-file has failed! {} / {} bytes written", bytes_written,
-                  output_text.size());
-    }
-}
-
-std::pair<float, float> Tas::FlipAxisY(std::pair<float, float> old) {
-    auto [x, y] = old;
-    return {x, -y};
-}
-
-void Tas::RecordInput(u32 buttons, const std::array<std::pair<float, float>, 2>& axes) {
-    last_input = {buttons, FlipAxisY(axes[0]), FlipAxisY(axes[1])};
-}
-
-std::tuple<TasState, size_t, size_t> Tas::GetStatus() const {
-    TasState state;
-    if (is_recording) {
-        return {TasState::Recording, 0, record_commands.size()};
-    }
-
-    if (is_running) {
-        state = TasState::Running;
-    } else {
-        state = TasState::Stopped;
-    }
-
-    return {state, current_command, script_length};
-}
-
-std::string Tas::DebugButtons(u32 buttons) const {
-    return fmt::format("{{ {} }}", TasInput::Tas::ButtonsToString(buttons));
-}
-
-std::string Tas::DebugJoystick(float x, float y) const {
-    return fmt::format("[ {} , {} ]", std::to_string(x), std::to_string(y));
-}
-
-std::string Tas::DebugInput(const TasData& data) const {
-    return fmt::format("{{ {} , {} , {} }}", DebugButtons(data.buttons),
-                       DebugJoystick(data.axis[0], data.axis[1]),
-                       DebugJoystick(data.axis[2], data.axis[3]));
-}
-
-std::string Tas::DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) const {
-    std::string returns = "[ ";
-    for (size_t i = 0; i < arr.size(); i++) {
-        returns += DebugInput(arr[i]);
-        if (i != arr.size() - 1) {
-            returns += " , ";
-        }
-    }
-    return returns + "]";
-}
-
-std::string Tas::ButtonsToString(u32 button) const {
-    std::string returns;
-    for (auto [text_button, tas_button] : text_to_tas_button) {
-        if ((button & static_cast<u32>(tas_button)) != 0)
-            returns += fmt::format(", {}", text_button.substr(4));
-    }
-    return returns.empty() ? "" : returns.substr(2);
-}
-
-void Tas::UpdateThread() {
-    if (!Settings::values.tas_enable) {
-        if (is_running) {
-            Stop();
-        }
-        return;
-    }
-
-    if (is_recording) {
-        record_commands.push_back(last_input);
-    }
-    if (needs_reset) {
-        current_command = 0;
-        needs_reset = false;
-        LoadTasFiles();
-        LOG_DEBUG(Input, "tas_reset done");
-    }
-
-    if (!is_running) {
-        tas_data.fill({});
-        return;
-    }
-    if (current_command < script_length) {
-        LOG_DEBUG(Input, "Playing TAS {}/{}", current_command, script_length);
-        size_t frame = current_command++;
-        for (size_t i = 0; i < commands.size(); i++) {
-            if (frame < commands[i].size()) {
-                TASCommand command = commands[i][frame];
-                tas_data[i].buttons = command.buttons;
-                auto [l_axis_x, l_axis_y] = command.l_axis;
-                tas_data[i].axis[0] = l_axis_x;
-                tas_data[i].axis[1] = l_axis_y;
-                auto [r_axis_x, r_axis_y] = command.r_axis;
-                tas_data[i].axis[2] = r_axis_x;
-                tas_data[i].axis[3] = r_axis_y;
-            } else {
-                tas_data[i] = {};
-            }
-        }
-    } else {
-        is_running = Settings::values.tas_loop.GetValue();
-        current_command = 0;
-        tas_data.fill({});
-        if (!is_running) {
-            SwapToStoredController();
-        }
-    }
-    LOG_DEBUG(Input, "TAS inputs: {}", DebugInputs(tas_data));
-}
-
-TasAnalog Tas::ReadCommandAxis(const std::string& line) const {
-    std::stringstream linestream(line);
-    std::string segment;
-    std::vector<std::string> seglist;
-
-    while (std::getline(linestream, segment, ';')) {
-        seglist.push_back(segment);
-    }
-
-    const float x = std::stof(seglist.at(0)) / 32767.0f;
-    const float y = std::stof(seglist.at(1)) / 32767.0f;
-
-    return {x, y};
-}
-
-u32 Tas::ReadCommandButtons(const std::string& data) const {
-    std::stringstream button_text(data);
-    std::string line;
-    u32 buttons = 0;
-    while (std::getline(button_text, line, ';')) {
-        for (auto [text, tas_button] : text_to_tas_button) {
-            if (text == line) {
-                buttons |= static_cast<u32>(tas_button);
-                break;
-            }
-        }
-    }
-    return buttons;
-}
-
-std::string Tas::WriteCommandAxis(TasAnalog data) const {
-    auto [x, y] = data;
-    std::string line;
-    line += std::to_string(static_cast<int>(x * 32767));
-    line += ";";
-    line += std::to_string(static_cast<int>(y * 32767));
-    return line;
-}
-
-std::string Tas::WriteCommandButtons(u32 data) const {
-    if (data == 0) {
-        return "NONE";
-    }
-
-    std::string line;
-    u32 index = 0;
-    while (data > 0) {
-        if ((data & 1) == 1) {
-            for (auto [text, tas_button] : text_to_tas_button) {
-                if (tas_button == static_cast<TasButton>(1 << index)) {
-                    if (line.size() > 0) {
-                        line += ";";
-                    }
-                    line += text;
-                    break;
-                }
-            }
-        }
-        index++;
-        data >>= 1;
-    }
-    return line;
-}
-
-void Tas::StartStop() {
-    if (!Settings::values.tas_enable) {
-        return;
-    }
-    if (is_running) {
-        Stop();
-    } else {
-        is_running = true;
-        SwapToTasController();
-    }
-}
-
-void Tas::Stop() {
-    is_running = false;
-    SwapToStoredController();
-}
-
-void Tas::SwapToTasController() {
-    if (!Settings::values.tas_swap_controllers) {
-        return;
-    }
-    auto& players = Settings::values.players.GetValue();
-    for (std::size_t index = 0; index < players.size(); index++) {
-        auto& player = players[index];
-        player_mappings[index] = player;
-
-        // Only swap active controllers
-        if (!player.connected) {
-            continue;
-        }
-
-        Common::ParamPackage tas_param;
-        tas_param.Set("pad", static_cast<u8>(index));
-        auto button_mapping = GetButtonMappingForDevice(tas_param);
-        auto analog_mapping = GetAnalogMappingForDevice(tas_param);
-        auto& buttons = player.buttons;
-        auto& analogs = player.analogs;
-
-        for (std::size_t i = 0; i < buttons.size(); ++i) {
-            buttons[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)].Serialize();
-        }
-        for (std::size_t i = 0; i < analogs.size(); ++i) {
-            analogs[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)].Serialize();
-        }
-    }
-    is_old_input_saved = true;
-    Settings::values.is_device_reload_pending.store(true);
-}
-
-void Tas::SwapToStoredController() {
-    if (!is_old_input_saved) {
-        return;
-    }
-    auto& players = Settings::values.players.GetValue();
-    for (std::size_t index = 0; index < players.size(); index++) {
-        players[index] = player_mappings[index];
-    }
-    is_old_input_saved = false;
-    Settings::values.is_device_reload_pending.store(true);
-}
-
-void Tas::Reset() {
-    if (!Settings::values.tas_enable) {
-        return;
-    }
-    needs_reset = true;
-}
-
-bool Tas::Record() {
-    if (!Settings::values.tas_enable) {
-        return true;
-    }
-    is_recording = !is_recording;
-    return is_recording;
-}
-
-void Tas::SaveRecording(bool overwrite_file) {
-    if (is_recording) {
-        return;
-    }
-    if (record_commands.empty()) {
-        return;
-    }
-    WriteTasFile(u8"record.txt");
-    if (overwrite_file) {
-        WriteTasFile(u8"script0-1.txt");
-    }
-    needs_reset = true;
-    record_commands.clear();
-}
-
-InputCommon::ButtonMapping Tas::GetButtonMappingForDevice(
-    const Common::ParamPackage& params) const {
-    // This list is missing ZL/ZR since those are not considered buttons.
-    // We will add those afterwards
-    // This list also excludes any button that can't be really mapped
-    static constexpr std::array<std::pair<Settings::NativeButton::Values, TasButton>, 20>
-        switch_to_tas_button = {
-            std::pair{Settings::NativeButton::A, TasButton::BUTTON_A},
-            {Settings::NativeButton::B, TasButton::BUTTON_B},
-            {Settings::NativeButton::X, TasButton::BUTTON_X},
-            {Settings::NativeButton::Y, TasButton::BUTTON_Y},
-            {Settings::NativeButton::LStick, TasButton::STICK_L},
-            {Settings::NativeButton::RStick, TasButton::STICK_R},
-            {Settings::NativeButton::L, TasButton::TRIGGER_L},
-            {Settings::NativeButton::R, TasButton::TRIGGER_R},
-            {Settings::NativeButton::Plus, TasButton::BUTTON_PLUS},
-            {Settings::NativeButton::Minus, TasButton::BUTTON_MINUS},
-            {Settings::NativeButton::DLeft, TasButton::BUTTON_LEFT},
-            {Settings::NativeButton::DUp, TasButton::BUTTON_UP},
-            {Settings::NativeButton::DRight, TasButton::BUTTON_RIGHT},
-            {Settings::NativeButton::DDown, TasButton::BUTTON_DOWN},
-            {Settings::NativeButton::SL, TasButton::BUTTON_SL},
-            {Settings::NativeButton::SR, TasButton::BUTTON_SR},
-            {Settings::NativeButton::Screenshot, TasButton::BUTTON_CAPTURE},
-            {Settings::NativeButton::Home, TasButton::BUTTON_HOME},
-            {Settings::NativeButton::ZL, TasButton::TRIGGER_ZL},
-            {Settings::NativeButton::ZR, TasButton::TRIGGER_ZR},
-        };
-
-    InputCommon::ButtonMapping mapping{};
-    for (const auto& [switch_button, tas_button] : switch_to_tas_button) {
-        Common::ParamPackage button_params({{"engine", "tas"}});
-        button_params.Set("pad", params.Get("pad", 0));
-        button_params.Set("button", static_cast<int>(tas_button));
-        mapping.insert_or_assign(switch_button, std::move(button_params));
-    }
-
-    return mapping;
-}
-
-InputCommon::AnalogMapping Tas::GetAnalogMappingForDevice(
-    const Common::ParamPackage& params) const {
-
-    InputCommon::AnalogMapping mapping = {};
-    Common::ParamPackage left_analog_params;
-    left_analog_params.Set("engine", "tas");
-    left_analog_params.Set("pad", params.Get("pad", 0));
-    left_analog_params.Set("axis_x", static_cast<int>(TasAxes::StickX));
-    left_analog_params.Set("axis_y", static_cast<int>(TasAxes::StickY));
-    mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params));
-    Common::ParamPackage right_analog_params;
-    right_analog_params.Set("engine", "tas");
-    right_analog_params.Set("pad", params.Get("pad", 0));
-    right_analog_params.Set("axis_x", static_cast<int>(TasAxes::SubstickX));
-    right_analog_params.Set("axis_y", static_cast<int>(TasAxes::SubstickY));
-    mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params));
-    return mapping;
-}
-
-const TasData& Tas::GetTasState(std::size_t pad) const {
-    return tas_data[pad];
-}
-} // namespace TasInput
diff --git a/src/input_common/tas/tas_input.h b/src/input_common/tas/tas_input.h
deleted file mode 100644
index 3e2db8f006..0000000000
--- a/src/input_common/tas/tas_input.h
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <array>
-
-#include "common/common_types.h"
-#include "common/settings_input.h"
-#include "core/frontend/input.h"
-#include "input_common/main.h"
-
-/*
-To play back TAS scripts on Yuzu, select the folder with scripts in the configuration menu below
-Tools -> Configure TAS. The file itself has normal text format and has to be called script0-1.txt
-for controller 1, script0-2.txt for controller 2 and so forth (with max. 8 players).
-
-A script file has the same format as TAS-nx uses, so final files will look like this:
-
-1 KEY_B 0;0 0;0
-6 KEY_ZL 0;0 0;0
-41 KEY_ZL;KEY_Y 0;0 0;0
-43 KEY_X;KEY_A 32767;0 0;0
-44 KEY_A 32767;0 0;0
-45 KEY_A 32767;0 0;0
-46 KEY_A 32767;0 0;0
-47 KEY_A 32767;0 0;0
-
-After placing the file at the correct location, it can be read into Yuzu with the (default) hotkey
-CTRL+F6 (refresh). In the bottom left corner, it will display the amount of frames the script file
-has. Playback can be started or stopped using CTRL+F5.
-
-However, for playback to actually work, the correct input device has to be selected: In the Controls
-menu, select TAS from the device list for the controller that the script should be played on.
-
-Recording a new script file is really simple: Just make sure that the proper device (not TAS) is
-connected on P1, and press CTRL+F7 to start recording. When done, just press the same keystroke
-again (CTRL+F7). The new script will be saved at the location previously selected, as the filename
-record.txt.
-
-For debugging purposes, the common controller debugger can be used (View -> Debugging -> Controller
-P1).
-*/
-
-namespace TasInput {
-
-constexpr size_t PLAYER_NUMBER = 8;
-
-using TasAnalog = std::pair<float, float>;
-
-enum class TasState {
-    Running,
-    Recording,
-    Stopped,
-};
-
-enum class TasButton : u32 {
-    BUTTON_A = 1U << 0,
-    BUTTON_B = 1U << 1,
-    BUTTON_X = 1U << 2,
-    BUTTON_Y = 1U << 3,
-    STICK_L = 1U << 4,
-    STICK_R = 1U << 5,
-    TRIGGER_L = 1U << 6,
-    TRIGGER_R = 1U << 7,
-    TRIGGER_ZL = 1U << 8,
-    TRIGGER_ZR = 1U << 9,
-    BUTTON_PLUS = 1U << 10,
-    BUTTON_MINUS = 1U << 11,
-    BUTTON_LEFT = 1U << 12,
-    BUTTON_UP = 1U << 13,
-    BUTTON_RIGHT = 1U << 14,
-    BUTTON_DOWN = 1U << 15,
-    BUTTON_SL = 1U << 16,
-    BUTTON_SR = 1U << 17,
-    BUTTON_HOME = 1U << 18,
-    BUTTON_CAPTURE = 1U << 19,
-};
-
-enum class TasAxes : u8 {
-    StickX,
-    StickY,
-    SubstickX,
-    SubstickY,
-    Undefined,
-};
-
-struct TasData {
-    u32 buttons{};
-    std::array<float, 4> axis{};
-};
-
-class Tas {
-public:
-    Tas();
-    ~Tas();
-
-    // Changes the input status that will be stored in each frame
-    void RecordInput(u32 buttons, const std::array<std::pair<float, float>, 2>& axes);
-
-    // Main loop that records or executes input
-    void UpdateThread();
-
-    //  Sets the flag to start or stop the TAS command excecution and swaps controllers profiles
-    void StartStop();
-
-    //  Stop the TAS and reverts any controller profile
-    void Stop();
-
-    // Sets the flag to reload the file and start from the begining in the next update
-    void Reset();
-
-    /**
-     * Sets the flag to enable or disable recording of inputs
-     * @return Returns true if the current recording status is enabled
-     */
-    bool Record();
-
-    // Saves contents of record_commands on a file if overwrite is enabled player 1 will be
-    // overwritten with the recorded commands
-    void SaveRecording(bool overwrite_file);
-
-    /**
-     * Returns the current status values of TAS playback/recording
-     * @return Tuple of
-     * TasState indicating the current state out of Running, Recording or Stopped ;
-     * Current playback progress or amount of frames (so far) for Recording ;
-     * Total length of script file currently loaded or amount of frames (so far) for Recording
-     */
-    std::tuple<TasState, size_t, size_t> GetStatus() const;
-
-    // Retuns an array of the default button mappings
-    InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const;
-
-    // Retuns an array of the default analog mappings
-    InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const;
-    [[nodiscard]] const TasData& GetTasState(std::size_t pad) const;
-
-private:
-    struct TASCommand {
-        u32 buttons{};
-        TasAnalog l_axis{};
-        TasAnalog r_axis{};
-    };
-
-    // Loads TAS files from all players
-    void LoadTasFiles();
-
-    // Loads TAS file from the specified player
-    void LoadTasFile(size_t player_index);
-
-    // Writes a TAS file from the recorded commands
-    void WriteTasFile(std::u8string file_name);
-
-    /**
-     * Parses a string containing the axis values with the following format "x;y"
-     * X and Y have a range from -32767 to 32767
-     * @return Returns a TAS analog object with axis values with range from -1.0 to 1.0
-     */
-    TasAnalog ReadCommandAxis(const std::string& line) const;
-
-    /**
-     * Parses a string containing the button values with the following format "a;b;c;d..."
-     * Each button is represented by it's text format specified in text_to_tas_button array
-     * @return Returns a u32 with each bit representing the status of a button
-     */
-    u32 ReadCommandButtons(const std::string& line) const;
-
-    /**
-     * Converts an u32 containing the button status into the text equivalent
-     * @return Returns a string with the name of the buttons to be written to the file
-     */
-    std::string WriteCommandButtons(u32 data) const;
-
-    /**
-     * Converts an TAS analog object containing the axis status into the text equivalent
-     * @return Returns a string with the value of the axis to be written to the file
-     */
-    std::string WriteCommandAxis(TasAnalog data) const;
-
-    // Inverts the Y axis polarity
-    std::pair<float, float> FlipAxisY(std::pair<float, float> old);
-
-    /**
-     * Converts an u32 containing the button status into the text equivalent
-     * @return Returns a string with the name of the buttons to be printed on console
-     */
-    std::string DebugButtons(u32 buttons) const;
-
-    /**
-     * Converts an TAS analog object containing the axis status into the text equivalent
-     * @return Returns a string with the value of the axis to be printed on console
-     */
-    std::string DebugJoystick(float x, float y) const;
-
-    /**
-     * Converts the given TAS status into the text equivalent
-     * @return Returns a string with the value of the TAS status to be printed on console
-     */
-    std::string DebugInput(const TasData& data) const;
-
-    /**
-     * Converts the given TAS status of multiple players into the text equivalent
-     * @return Returns a string with the value of the status of all TAS players to be printed on
-     * console
-     */
-    std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) const;
-
-    /**
-     * Converts an u32 containing the button status into the text equivalent
-     * @return Returns a string with the name of the buttons
-     */
-    std::string ButtonsToString(u32 button) const;
-
-    // Stores current controller configuration and sets a TAS controller for every active controller
-    // to the current config
-    void SwapToTasController();
-
-    // Sets the stored controller configuration to the current config
-    void SwapToStoredController();
-
-    size_t script_length{0};
-    std::array<TasData, PLAYER_NUMBER> tas_data;
-    bool is_old_input_saved{false};
-    bool is_recording{false};
-    bool is_running{false};
-    bool needs_reset{false};
-    std::array<std::vector<TASCommand>, PLAYER_NUMBER> commands{};
-    std::vector<TASCommand> record_commands{};
-    size_t current_command{0};
-    TASCommand last_input{}; // only used for recording
-
-    // Old settings for swapping controllers
-    std::array<Settings::PlayerInput, 10> player_mappings;
-};
-} // namespace TasInput
diff --git a/src/input_common/tas/tas_poller.cpp b/src/input_common/tas/tas_poller.cpp
deleted file mode 100644
index 15810d6b0d..0000000000
--- a/src/input_common/tas/tas_poller.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2021 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <mutex>
-#include <utility>
-
-#include "common/settings.h"
-#include "common/threadsafe_queue.h"
-#include "input_common/tas/tas_input.h"
-#include "input_common/tas/tas_poller.h"
-
-namespace InputCommon {
-
-class TasButton final : public Input::ButtonDevice {
-public:
-    explicit TasButton(u32 button_, u32 pad_, const TasInput::Tas* tas_input_)
-        : button(button_), pad(pad_), tas_input(tas_input_) {}
-
-    bool GetStatus() const override {
-        return (tas_input->GetTasState(pad).buttons & button) != 0;
-    }
-
-private:
-    const u32 button;
-    const u32 pad;
-    const TasInput::Tas* tas_input;
-};
-
-TasButtonFactory::TasButtonFactory(std::shared_ptr<TasInput::Tas> tas_input_)
-    : tas_input(std::move(tas_input_)) {}
-
-std::unique_ptr<Input::ButtonDevice> TasButtonFactory::Create(const Common::ParamPackage& params) {
-    const auto button_id = params.Get("button", 0);
-    const auto pad = params.Get("pad", 0);
-
-    return std::make_unique<TasButton>(button_id, pad, tas_input.get());
-}
-
-class TasAnalog final : public Input::AnalogDevice {
-public:
-    explicit TasAnalog(u32 pad_, u32 axis_x_, u32 axis_y_, const TasInput::Tas* tas_input_)
-        : pad(pad_), axis_x(axis_x_), axis_y(axis_y_), tas_input(tas_input_) {}
-
-    float GetAxis(u32 axis) const {
-        std::lock_guard lock{mutex};
-        return tas_input->GetTasState(pad).axis.at(axis);
-    }
-
-    std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
-        float x = GetAxis(analog_axis_x);
-        float y = GetAxis(analog_axis_y);
-
-        // Make sure the coordinates are in the unit circle,
-        // otherwise normalize it.
-        float r = x * x + y * y;
-        if (r > 1.0f) {
-            r = std::sqrt(r);
-            x /= r;
-            y /= r;
-        }
-
-        return {x, y};
-    }
-
-    std::tuple<float, float> GetStatus() const override {
-        return GetAnalog(axis_x, axis_y);
-    }
-
-    Input::AnalogProperties GetAnalogProperties() const override {
-        return {0.0f, 1.0f, 0.5f};
-    }
-
-private:
-    const u32 pad;
-    const u32 axis_x;
-    const u32 axis_y;
-    const TasInput::Tas* tas_input;
-    mutable std::mutex mutex;
-};
-
-/// An analog device factory that creates analog devices from GC Adapter
-TasAnalogFactory::TasAnalogFactory(std::shared_ptr<TasInput::Tas> tas_input_)
-    : tas_input(std::move(tas_input_)) {}
-
-/**
- * Creates analog device from joystick axes
- * @param params contains parameters for creating the device:
- *     - "port": the nth gcpad on the adapter
- *     - "axis_x": the index of the axis to be bind as x-axis
- *     - "axis_y": the index of the axis to be bind as y-axis
- */
-std::unique_ptr<Input::AnalogDevice> TasAnalogFactory::Create(const Common::ParamPackage& params) {
-    const auto pad = static_cast<u32>(params.Get("pad", 0));
-    const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
-    const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
-
-    return std::make_unique<TasAnalog>(pad, axis_x, axis_y, tas_input.get());
-}
-
-} // namespace InputCommon
diff --git a/src/input_common/tas/tas_poller.h b/src/input_common/tas/tas_poller.h
deleted file mode 100644
index 09e426cef5..0000000000
--- a/src/input_common/tas/tas_poller.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2021 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include "core/frontend/input.h"
-#include "input_common/tas/tas_input.h"
-
-namespace InputCommon {
-
-/**
- * A button device factory representing a tas bot. It receives tas events and forward them
- * to all button devices it created.
- */
-class TasButtonFactory final : public Input::Factory<Input::ButtonDevice> {
-public:
-    explicit TasButtonFactory(std::shared_ptr<TasInput::Tas> tas_input_);
-
-    /**
-     * Creates a button device from a button press
-     * @param params contains parameters for creating the device:
-     *     - "code": the code of the key to bind with the button
-     */
-    std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override;
-
-private:
-    std::shared_ptr<TasInput::Tas> tas_input;
-};
-
-/// An analog device factory that creates analog devices from tas
-class TasAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
-public:
-    explicit TasAnalogFactory(std::shared_ptr<TasInput::Tas> tas_input_);
-
-    std::unique_ptr<Input::AnalogDevice> Create(const Common::ParamPackage& params) override;
-
-private:
-    std::shared_ptr<TasInput::Tas> tas_input;
-};
-
-} // namespace InputCommon

From 10241886ddbead1a24a5924debf83a4fad0ade0d Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 17:33:19 -0500
Subject: [PATCH 12/88] input_common: Rewrite udp client

---
 src/input_common/CMakeLists.txt               |   6 +-
 .../client.cpp => drivers/udp_client.cpp}     | 240 +++---------------
 .../{udp/client.h => drivers/udp_client.h}    |  80 +-----
 src/input_common/udp/udp.cpp                  | 110 --------
 src/input_common/udp/udp.h                    |  57 -----
 5 files changed, 53 insertions(+), 440 deletions(-)
 rename src/input_common/{udp/client.cpp => drivers/udp_client.cpp} (60%)
 rename src/input_common/{udp/client.h => drivers/udp_client.h} (56%)
 delete mode 100644 src/input_common/udp/udp.cpp
 delete mode 100644 src/input_common/udp/udp.h

diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 19270dc842..9c0c82138b 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -9,6 +9,8 @@ add_library(input_common STATIC
     drivers/tas_input.h
     drivers/touch_screen.cpp
     drivers/touch_screen.h
+    drivers/udp_client.cpp
+    drivers/udp_client.h
     helpers/stick_from_buttons.cpp
     helpers/stick_from_buttons.h
     helpers/touch_from_buttons.cpp
@@ -29,10 +31,6 @@ add_library(input_common STATIC
     motion_input.h
     sdl/sdl.cpp
     sdl/sdl.h
-    udp/client.cpp
-    udp/client.h
-    udp/udp.cpp
-    udp/udp.h
 )
 
 if (MSVC)
diff --git a/src/input_common/udp/client.cpp b/src/input_common/drivers/udp_client.cpp
similarity index 60%
rename from src/input_common/udp/client.cpp
rename to src/input_common/drivers/udp_client.cpp
index bcc29c4e07..6fcc3a01b7 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/drivers/udp_client.cpp
@@ -2,15 +2,13 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include <chrono>
-#include <cstring>
-#include <functional>
 #include <random>
-#include <thread>
 #include <boost/asio.hpp>
+
 #include "common/logging/log.h"
+#include "common/param_package.h"
 #include "common/settings.h"
-#include "input_common/udp/client.h"
+#include "input_common/drivers/udp_client.h"
 #include "input_common/helpers/udp_protocol.h"
 
 using boost::asio::ip::udp;
@@ -86,7 +84,6 @@ private:
             case Type::PadData: {
                 Response::PadData pad_data;
                 std::memcpy(&pad_data, &receive_buffer[sizeof(Header)], sizeof(Response::PadData));
-                SanitizeMotion(pad_data);
                 callback.pad_data(std::move(pad_data));
                 break;
             }
@@ -115,28 +112,6 @@ private:
         StartSend(timer.expiry());
     }
 
-    void SanitizeMotion(Response::PadData& data) {
-        // Zero out any non number value
-        if (!std::isnormal(data.gyro.pitch)) {
-            data.gyro.pitch = 0;
-        }
-        if (!std::isnormal(data.gyro.roll)) {
-            data.gyro.roll = 0;
-        }
-        if (!std::isnormal(data.gyro.yaw)) {
-            data.gyro.yaw = 0;
-        }
-        if (!std::isnormal(data.accel.x)) {
-            data.accel.x = 0;
-        }
-        if (!std::isnormal(data.accel.y)) {
-            data.accel.y = 0;
-        }
-        if (!std::isnormal(data.accel.z)) {
-            data.accel.z = 0;
-        }
-    }
-
     SocketCallback callback;
     boost::asio::io_service io_service;
     boost::asio::basic_waitable_timer<clock> timer;
@@ -160,48 +135,23 @@ static void SocketLoop(Socket* socket) {
     socket->Loop();
 }
 
-Client::Client() {
+UDPClient::UDPClient(const std::string& input_engine_) : InputEngine(input_engine_) {
     LOG_INFO(Input, "Udp Initialization started");
-    finger_id.fill(MAX_TOUCH_FINGERS);
     ReloadSockets();
 }
 
-Client::~Client() {
+UDPClient::~UDPClient() {
     Reset();
 }
 
-Client::ClientConnection::ClientConnection() = default;
+UDPClient::ClientConnection::ClientConnection() = default;
 
-Client::ClientConnection::~ClientConnection() = default;
+UDPClient::ClientConnection::~ClientConnection() = default;
 
-std::vector<Common::ParamPackage> Client::GetInputDevices() const {
-    std::vector<Common::ParamPackage> devices;
-    for (std::size_t pad = 0; pad < pads.size(); pad++) {
-        if (!DeviceConnected(pad)) {
-            continue;
-        }
-        std::string name = fmt::format("UDP Controller {}", pad);
-        devices.emplace_back(Common::ParamPackage{
-            {"class", "cemuhookudp"},
-            {"display", std::move(name)},
-            {"port", std::to_string(pad)},
-        });
-    }
-    return devices;
-}
-
-bool Client::DeviceConnected(std::size_t pad) const {
-    // Use last timestamp to detect if the socket has stopped sending data
-    const auto now = std::chrono::steady_clock::now();
-    const auto time_difference = static_cast<u64>(
-        std::chrono::duration_cast<std::chrono::milliseconds>(now - pads[pad].last_update).count());
-    return time_difference < 1000 && pads[pad].connected;
-}
-
-void Client::ReloadSockets() {
+void UDPClient::ReloadSockets() {
     Reset();
 
-    std::stringstream servers_ss(static_cast<std::string>(Settings::values.udp_input_servers));
+    std::stringstream servers_ss(Settings::values.udp_input_servers.GetValue());
     std::string server_token;
     std::size_t client = 0;
     while (std::getline(servers_ss, server_token, ',')) {
@@ -229,7 +179,7 @@ void Client::ReloadSockets() {
     }
 }
 
-std::size_t Client::GetClientNumber(std::string_view host, u16 port) const {
+std::size_t UDPClient::GetClientNumber(std::string_view host, u16 port) const {
     for (std::size_t client = 0; client < clients.size(); client++) {
         if (clients[client].active == -1) {
             continue;
@@ -241,15 +191,15 @@ std::size_t Client::GetClientNumber(std::string_view host, u16 port) const {
     return MAX_UDP_CLIENTS;
 }
 
-void Client::OnVersion([[maybe_unused]] Response::Version data) {
+void UDPClient::OnVersion([[maybe_unused]] Response::Version data) {
     LOG_TRACE(Input, "Version packet received: {}", data.version);
 }
 
-void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) {
+void UDPClient::OnPortInfo([[maybe_unused]] Response::PortInfo data) {
     LOG_TRACE(Input, "PortInfo packet received: {}", data.model);
 }
 
-void Client::OnPadData(Response::PadData data, std::size_t client) {
+void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
     const std::size_t pad_index = (client * PADS_PER_CLIENT) + data.info.id;
 
     if (pad_index >= pads.size()) {
@@ -277,32 +227,25 @@ void Client::OnPadData(Response::PadData data, std::size_t client) {
             .count());
     pads[pad_index].last_update = now;
 
-    const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw};
-    pads[pad_index].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y});
     // Gyroscope values are not it the correct scale from better joy.
     // Dividing by 312 allows us to make one full turn = 1 turn
     // This must be a configurable valued called sensitivity
-    pads[pad_index].motion.SetGyroscope(raw_gyroscope / 312.0f);
-    pads[pad_index].motion.UpdateRotation(time_difference);
-    pads[pad_index].motion.UpdateOrientation(time_difference);
+    const float gyro_scale = 1.0f / 312.0f;
 
-    {
-        std::lock_guard guard(pads[pad_index].status.update_mutex);
-        pads[pad_index].status.motion_status = pads[pad_index].motion.GetMotion();
-
-        for (std::size_t id = 0; id < data.touch.size(); ++id) {
-            UpdateTouchInput(data.touch[id], client, id);
-        }
-
-        if (configuring) {
-            const Common::Vec3f gyroscope = pads[pad_index].motion.GetGyroscope();
-            const Common::Vec3f accelerometer = pads[pad_index].motion.GetAcceleration();
-            UpdateYuzuSettings(client, data.info.id, accelerometer, gyroscope);
-        }
-    }
+    const BasicMotion motion{
+        .gyro_x = data.gyro.pitch * gyro_scale,
+        .gyro_y = data.gyro.roll * gyro_scale,
+        .gyro_z = -data.gyro.yaw * gyro_scale,
+        .accel_x = data.accel.x,
+        .accel_y = -data.accel.z,
+        .accel_z = data.accel.y,
+        .delta_timestamp = time_difference,
+    };
+    const PadIdentifier identifier = GetPadIdentifier(pad_index);
+    SetMotion(identifier, 0, motion);
 }
 
-void Client::StartCommunication(std::size_t client, const std::string& host, u16 port) {
+void UDPClient::StartCommunication(std::size_t client, const std::string& host, u16 port) {
     SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
                             [this](Response::PortInfo info) { OnPortInfo(info); },
                             [this, client](Response::PadData data) { OnPadData(data, client); }};
@@ -312,16 +255,22 @@ void Client::StartCommunication(std::size_t client, const std::string& host, u16
     clients[client].active = 0;
     clients[client].socket = std::make_unique<Socket>(host, port, callback);
     clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()};
-
-    // Set motion parameters
-    // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
-    // Real HW values are unknown, 0.0001 is an approximate to Standard
-    for (std::size_t pad = 0; pad < PADS_PER_CLIENT; pad++) {
-        pads[client * PADS_PER_CLIENT + pad].motion.SetGyroThreshold(0.0001f);
+    for (std::size_t index = 0; index < PADS_PER_CLIENT; ++index) {
+        const PadIdentifier identifier = GetPadIdentifier(client * PADS_PER_CLIENT + index);
+        PreSetController(identifier);
     }
 }
 
-void Client::Reset() {
+const PadIdentifier UDPClient::GetPadIdentifier(std::size_t pad_index) const {
+    const std::size_t client = pad_index / PADS_PER_CLIENT;
+    return {
+        .guid = Common::UUID{clients[client].host},
+        .port = static_cast<std::size_t>(clients[client].port),
+        .pad = pad_index,
+    };
+}
+
+void UDPClient::Reset() {
     for (auto& client : clients) {
         if (client.thread.joinable()) {
             client.active = -1;
@@ -331,117 +280,6 @@ void Client::Reset() {
     }
 }
 
-void Client::UpdateYuzuSettings(std::size_t client, std::size_t pad_index,
-                                const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro) {
-    if (gyro.Length() > 0.2f) {
-        LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {})", client,
-                  gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2]);
-    }
-    UDPPadStatus pad{
-        .host = clients[client].host,
-        .port = clients[client].port,
-        .pad_index = pad_index,
-    };
-    for (std::size_t i = 0; i < 3; ++i) {
-        if (gyro[i] > 5.0f || gyro[i] < -5.0f) {
-            pad.motion = static_cast<PadMotion>(i);
-            pad.motion_value = gyro[i];
-            pad_queue.Push(pad);
-        }
-        if (acc[i] > 1.75f || acc[i] < -1.75f) {
-            pad.motion = static_cast<PadMotion>(i + 3);
-            pad.motion_value = acc[i];
-            pad_queue.Push(pad);
-        }
-    }
-}
-
-std::optional<std::size_t> Client::GetUnusedFingerID() const {
-    std::size_t first_free_id = 0;
-    while (first_free_id < MAX_TOUCH_FINGERS) {
-        if (!std::get<2>(touch_status[first_free_id])) {
-            return first_free_id;
-        } else {
-            first_free_id++;
-        }
-    }
-    return std::nullopt;
-}
-
-void Client::UpdateTouchInput(Response::TouchPad& touch_pad, std::size_t client, std::size_t id) {
-    // TODO: Use custom calibration per device
-    const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue());
-    const u16 min_x = static_cast<u16>(touch_param.Get("min_x", 100));
-    const u16 min_y = static_cast<u16>(touch_param.Get("min_y", 50));
-    const u16 max_x = static_cast<u16>(touch_param.Get("max_x", 1800));
-    const u16 max_y = static_cast<u16>(touch_param.Get("max_y", 850));
-    const std::size_t touch_id = client * 2 + id;
-    if (touch_pad.is_active) {
-        if (finger_id[touch_id] == MAX_TOUCH_FINGERS) {
-            const auto first_free_id = GetUnusedFingerID();
-            if (!first_free_id) {
-                // Invalid finger id skip to next input
-                return;
-            }
-            finger_id[touch_id] = *first_free_id;
-        }
-        auto& [x, y, pressed] = touch_status[finger_id[touch_id]];
-        x = static_cast<float>(std::clamp(static_cast<u16>(touch_pad.x), min_x, max_x) - min_x) /
-            static_cast<float>(max_x - min_x);
-        y = static_cast<float>(std::clamp(static_cast<u16>(touch_pad.y), min_y, max_y) - min_y) /
-            static_cast<float>(max_y - min_y);
-        pressed = true;
-        return;
-    }
-
-    if (finger_id[touch_id] != MAX_TOUCH_FINGERS) {
-        touch_status[finger_id[touch_id]] = {};
-        finger_id[touch_id] = MAX_TOUCH_FINGERS;
-    }
-}
-
-void Client::BeginConfiguration() {
-    pad_queue.Clear();
-    configuring = true;
-}
-
-void Client::EndConfiguration() {
-    pad_queue.Clear();
-    configuring = false;
-}
-
-DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) {
-    const std::size_t client_number = GetClientNumber(host, port);
-    if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) {
-        return pads[0].status;
-    }
-    return pads[(client_number * PADS_PER_CLIENT) + pad].status;
-}
-
-const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const {
-    const std::size_t client_number = GetClientNumber(host, port);
-    if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) {
-        return pads[0].status;
-    }
-    return pads[(client_number * PADS_PER_CLIENT) + pad].status;
-}
-
-Input::TouchStatus& Client::GetTouchState() {
-    return touch_status;
-}
-
-const Input::TouchStatus& Client::GetTouchState() const {
-    return touch_status;
-}
-
-Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() {
-    return pad_queue;
-}
-
-const Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() const {
-    return pad_queue;
-}
-
 void TestCommunication(const std::string& host, u16 port,
                        const std::function<void()>& success_callback,
                        const std::function<void()>& failure_callback) {
diff --git a/src/input_common/udp/client.h b/src/input_common/drivers/udp_client.h
similarity index 56%
rename from src/input_common/udp/client.h
rename to src/input_common/drivers/udp_client.h
index 380f9bb76d..58b2e921d1 100644
--- a/src/input_common/udp/client.h
+++ b/src/input_common/drivers/udp_client.h
@@ -1,23 +1,14 @@
-// Copyright 2018 Citra Emulator Project
+// Copyright 2021 yuzu Emulator Project
 // Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// Refer to the license.txt file included
 
 #pragma once
 
-#include <functional>
-#include <memory>
-#include <mutex>
 #include <optional>
-#include <string>
-#include <thread>
-#include <tuple>
+
 #include "common/common_types.h"
-#include "common/param_package.h"
 #include "common/thread.h"
-#include "common/threadsafe_queue.h"
-#include "common/vector_math.h"
-#include "core/frontend/input.h"
-#include "input_common/motion_input.h"
+#include "input_common/input_engine.h"
 
 namespace InputCommon::CemuhookUDP {
 
@@ -30,16 +21,6 @@ struct TouchPad;
 struct Version;
 } // namespace Response
 
-enum class PadMotion {
-    GyroX,
-    GyroY,
-    GyroZ,
-    AccX,
-    AccY,
-    AccZ,
-    Undefined,
-};
-
 enum class PadTouch {
     Click,
     Undefined,
@@ -49,14 +30,10 @@ struct UDPPadStatus {
     std::string host{"127.0.0.1"};
     u16 port{26760};
     std::size_t pad_index{};
-    PadMotion motion{PadMotion::Undefined};
-    f32 motion_value{0.0f};
 };
 
 struct DeviceStatus {
     std::mutex update_mutex;
-    Input::MotionStatus motion_status;
-    std::tuple<float, float, bool> touch_status;
 
     // calibration data for scaling the device's touch area to 3ds
     struct CalibrationData {
@@ -68,32 +45,17 @@ struct DeviceStatus {
     std::optional<CalibrationData> touch_calibration;
 };
 
-class Client {
+/**
+ * A button device factory representing a keyboard. It receives keyboard events and forward them
+ * to all button devices it created.
+ */
+class UDPClient final : public InputCommon::InputEngine {
 public:
-    // Initialize the UDP client capture and read sequence
-    Client();
+    explicit UDPClient(const std::string& input_engine_);
+    ~UDPClient();
 
-    // Close and release the client
-    ~Client();
-
-    // Used for polling
-    void BeginConfiguration();
-    void EndConfiguration();
-
-    std::vector<Common::ParamPackage> GetInputDevices() const;
-
-    bool DeviceConnected(std::size_t pad) const;
     void ReloadSockets();
 
-    Common::SPSCQueue<UDPPadStatus>& GetPadQueue();
-    const Common::SPSCQueue<UDPPadStatus>& GetPadQueue() const;
-
-    DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad);
-    const DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad) const;
-
-    Input::TouchStatus& GetTouchState();
-    const Input::TouchStatus& GetTouchState() const;
-
 private:
     struct PadData {
         std::size_t pad_index{};
@@ -101,9 +63,6 @@ private:
         DeviceStatus status;
         u64 packet_sequence{};
 
-        // Realtime values
-        // motion is initalized with PID values for drift correction on joycons
-        InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f};
         std::chrono::time_point<std::chrono::steady_clock> last_update;
     };
 
@@ -127,28 +86,13 @@ private:
     void OnPortInfo(Response::PortInfo);
     void OnPadData(Response::PadData, std::size_t client);
     void StartCommunication(std::size_t client, const std::string& host, u16 port);
-    void UpdateYuzuSettings(std::size_t client, std::size_t pad_index,
-                            const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro);
-
-    // Returns an unused finger id, if there is no fingers available std::nullopt will be
-    // returned
-    std::optional<std::size_t> GetUnusedFingerID() const;
-
-    // Merges and updates all touch inputs into the touch_status array
-    void UpdateTouchInput(Response::TouchPad& touch_pad, std::size_t client, std::size_t id);
-
-    bool configuring = false;
+    const PadIdentifier GetPadIdentifier(std::size_t pad_index) const;
 
     // Allocate clients for 8 udp servers
     static constexpr std::size_t MAX_UDP_CLIENTS = 8;
     static constexpr std::size_t PADS_PER_CLIENT = 4;
-    // Each client can have up 2 touch inputs
-    static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2;
     std::array<PadData, MAX_UDP_CLIENTS * PADS_PER_CLIENT> pads{};
     std::array<ClientConnection, MAX_UDP_CLIENTS> clients{};
-    Common::SPSCQueue<UDPPadStatus> pad_queue{};
-    Input::TouchStatus touch_status{};
-    std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{};
 };
 
 /// An async job allowing configuration of the touchpad calibration.
diff --git a/src/input_common/udp/udp.cpp b/src/input_common/udp/udp.cpp
deleted file mode 100644
index 9829da6f00..0000000000
--- a/src/input_common/udp/udp.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <mutex>
-#include <utility>
-#include "common/assert.h"
-#include "common/threadsafe_queue.h"
-#include "input_common/udp/client.h"
-#include "input_common/udp/udp.h"
-
-namespace InputCommon {
-
-class UDPMotion final : public Input::MotionDevice {
-public:
-    explicit UDPMotion(std::string ip_, u16 port_, u16 pad_, CemuhookUDP::Client* client_)
-        : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {}
-
-    Input::MotionStatus GetStatus() const override {
-        return client->GetPadState(ip, port, pad).motion_status;
-    }
-
-private:
-    const std::string ip;
-    const u16 port;
-    const u16 pad;
-    CemuhookUDP::Client* client;
-    mutable std::mutex mutex;
-};
-
-/// A motion device factory that creates motion devices from a UDP client
-UDPMotionFactory::UDPMotionFactory(std::shared_ptr<CemuhookUDP::Client> client_)
-    : client(std::move(client_)) {}
-
-/**
- * Creates motion device
- * @param params contains parameters for creating the device:
- *     - "port": the UDP port number
- */
-std::unique_ptr<Input::MotionDevice> UDPMotionFactory::Create(const Common::ParamPackage& params) {
-    auto ip = params.Get("ip", "127.0.0.1");
-    const auto port = static_cast<u16>(params.Get("port", 26760));
-    const auto pad = static_cast<u16>(params.Get("pad_index", 0));
-
-    return std::make_unique<UDPMotion>(std::move(ip), port, pad, client.get());
-}
-
-void UDPMotionFactory::BeginConfiguration() {
-    polling = true;
-    client->BeginConfiguration();
-}
-
-void UDPMotionFactory::EndConfiguration() {
-    polling = false;
-    client->EndConfiguration();
-}
-
-Common::ParamPackage UDPMotionFactory::GetNextInput() {
-    Common::ParamPackage params;
-    CemuhookUDP::UDPPadStatus pad;
-    auto& queue = client->GetPadQueue();
-    while (queue.Pop(pad)) {
-        if (pad.motion == CemuhookUDP::PadMotion::Undefined || std::abs(pad.motion_value) < 1) {
-            continue;
-        }
-        params.Set("engine", "cemuhookudp");
-        params.Set("ip", pad.host);
-        params.Set("port", static_cast<u16>(pad.port));
-        params.Set("pad_index", static_cast<u16>(pad.pad_index));
-        params.Set("motion", static_cast<u16>(pad.motion));
-        return params;
-    }
-    return params;
-}
-
-class UDPTouch final : public Input::TouchDevice {
-public:
-    explicit UDPTouch(std::string ip_, u16 port_, u16 pad_, CemuhookUDP::Client* client_)
-        : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {}
-
-    Input::TouchStatus GetStatus() const override {
-        return client->GetTouchState();
-    }
-
-private:
-    const std::string ip;
-    [[maybe_unused]] const u16 port;
-    [[maybe_unused]] const u16 pad;
-    CemuhookUDP::Client* client;
-    mutable std::mutex mutex;
-};
-
-/// A motion device factory that creates motion devices from a UDP client
-UDPTouchFactory::UDPTouchFactory(std::shared_ptr<CemuhookUDP::Client> client_)
-    : client(std::move(client_)) {}
-
-/**
- * Creates motion device
- * @param params contains parameters for creating the device:
- *     - "port": the UDP port number
- */
-std::unique_ptr<Input::TouchDevice> UDPTouchFactory::Create(const Common::ParamPackage& params) {
-    auto ip = params.Get("ip", "127.0.0.1");
-    const auto port = static_cast<u16>(params.Get("port", 26760));
-    const auto pad = static_cast<u16>(params.Get("pad_index", 0));
-
-    return std::make_unique<UDPTouch>(std::move(ip), port, pad, client.get());
-}
-
-} // namespace InputCommon
diff --git a/src/input_common/udp/udp.h b/src/input_common/udp/udp.h
deleted file mode 100644
index ea3fd41751..0000000000
--- a/src/input_common/udp/udp.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include "core/frontend/input.h"
-#include "input_common/udp/client.h"
-
-namespace InputCommon {
-
-/// A motion device factory that creates motion devices from udp clients
-class UDPMotionFactory final : public Input::Factory<Input::MotionDevice> {
-public:
-    explicit UDPMotionFactory(std::shared_ptr<CemuhookUDP::Client> client_);
-
-    std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
-
-    Common::ParamPackage GetNextInput();
-
-    /// For device input configuration/polling
-    void BeginConfiguration();
-    void EndConfiguration();
-
-    bool IsPolling() const {
-        return polling;
-    }
-
-private:
-    std::shared_ptr<CemuhookUDP::Client> client;
-    bool polling = false;
-};
-
-/// A touch device factory that creates touch devices from udp clients
-class UDPTouchFactory final : public Input::Factory<Input::TouchDevice> {
-public:
-    explicit UDPTouchFactory(std::shared_ptr<CemuhookUDP::Client> client_);
-
-    std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override;
-
-    Common::ParamPackage GetNextInput();
-
-    /// For device input configuration/polling
-    void BeginConfiguration();
-    void EndConfiguration();
-
-    bool IsPolling() const {
-        return polling;
-    }
-
-private:
-    std::shared_ptr<CemuhookUDP::Client> client;
-    bool polling = false;
-};
-
-} // namespace InputCommon

From 59b995a9e53f09b9831b03608cfe5ce27c3e3485 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 17:36:23 -0500
Subject: [PATCH 13/88] input_common: Rewrite SDL

---
 src/input_common/CMakeLists.txt               |    8 +-
 src/input_common/drivers/sdl_driver.cpp       |  915 +++++++++
 .../{sdl/sdl_impl.h => drivers/sdl_driver.h}  |   56 +-
 src/input_common/sdl/sdl.cpp                  |   19 -
 src/input_common/sdl/sdl.h                    |   51 -
 src/input_common/sdl/sdl_impl.cpp             | 1658 -----------------
 6 files changed, 950 insertions(+), 1757 deletions(-)
 create mode 100644 src/input_common/drivers/sdl_driver.cpp
 rename src/input_common/{sdl/sdl_impl.h => drivers/sdl_driver.h} (67%)
 delete mode 100644 src/input_common/sdl/sdl.cpp
 delete mode 100644 src/input_common/sdl/sdl.h
 delete mode 100644 src/input_common/sdl/sdl_impl.cpp

diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 9c0c82138b..8cdcd315b3 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -5,6 +5,8 @@ add_library(input_common STATIC
     drivers/keyboard.h
     drivers/mouse.cpp
     drivers/mouse.h
+    drivers/sdl_driver.cpp
+    drivers/sdl_driver.h
     drivers/tas_input.cpp
     drivers/tas_input.h
     drivers/touch_screen.cpp
@@ -29,8 +31,6 @@ add_library(input_common STATIC
     motion_from_button.h
     motion_input.cpp
     motion_input.h
-    sdl/sdl.cpp
-    sdl/sdl.h
 )
 
 if (MSVC)
@@ -57,8 +57,8 @@ endif()
 
 if (ENABLE_SDL2)
     target_sources(input_common PRIVATE
-        sdl/sdl_impl.cpp
-        sdl/sdl_impl.h
+        drivers/sdl_driver.cpp
+        drivers/sdl_driver.h
     )
     target_link_libraries(input_common PRIVATE SDL2)
     target_compile_definitions(input_common PRIVATE HAVE_SDL2)
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
new file mode 100644
index 0000000000..efb4a21068
--- /dev/null
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -0,0 +1,915 @@
+// Copyright 2018 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/logging/log.h"
+#include "common/math_util.h"
+#include "common/param_package.h"
+#include "common/settings.h"
+#include "common/thread.h"
+#include "common/vector_math.h"
+#include "input_common/drivers/sdl_driver.h"
+
+namespace InputCommon {
+
+namespace {
+std::string GetGUID(SDL_Joystick* joystick) {
+    const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
+    char guid_str[33];
+    SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
+    return guid_str;
+}
+} // Anonymous namespace
+
+static int SDLEventWatcher(void* user_data, SDL_Event* event) {
+    auto* const sdl_state = static_cast<SDLDriver*>(user_data);
+
+    sdl_state->HandleGameControllerEvent(*event);
+
+    return 0;
+}
+
+class SDLJoystick {
+public:
+    SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick,
+                SDL_GameController* game_controller)
+        : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose},
+          sdl_controller{game_controller, &SDL_GameControllerClose} {
+        EnableMotion();
+    }
+
+    void EnableMotion() {
+        if (sdl_controller) {
+            SDL_GameController* controller = sdl_controller.get();
+            if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) && !has_accel) {
+                SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
+                has_accel = true;
+            }
+            if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) && !has_gyro) {
+                SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
+                has_gyro = true;
+            }
+        }
+    }
+
+    bool HasGyro() const {
+        return has_gyro;
+    }
+
+    bool HasAccel() const {
+        return has_accel;
+    }
+
+    bool UpdateMotion(SDL_ControllerSensorEvent event) {
+        constexpr float gravity_constant = 9.80665f;
+        std::lock_guard lock{mutex};
+        const u64 time_difference = event.timestamp - last_motion_update;
+        last_motion_update = event.timestamp;
+        switch (event.sensor) {
+        case SDL_SENSOR_ACCEL: {
+            motion.accel_x = -event.data[0] / gravity_constant;
+            motion.accel_y = event.data[2] / gravity_constant;
+            motion.accel_z = -event.data[1] / gravity_constant;
+            break;
+        }
+        case SDL_SENSOR_GYRO: {
+            motion.gyro_x = event.data[0] / (Common::PI * 2);
+            motion.gyro_y = -event.data[2] / (Common::PI * 2);
+            motion.gyro_z = event.data[1] / (Common::PI * 2);
+            break;
+        }
+        }
+
+        // Ignore duplicated timestamps
+        if (time_difference == 0) {
+            return false;
+        }
+        motion.delta_timestamp = time_difference * 1000;
+        return true;
+    }
+
+    BasicMotion GetMotion() {
+        return motion;
+    }
+
+    bool RumblePlay(const Input::VibrationStatus vibration) {
+        constexpr u32 rumble_max_duration_ms = 1000;
+
+        if (sdl_controller) {
+            return SDL_GameControllerRumble(
+                       sdl_controller.get(), static_cast<u16>(vibration.low_amplitude),
+                       static_cast<u16>(vibration.high_amplitude), rumble_max_duration_ms) != -1;
+        } else if (sdl_joystick) {
+            return SDL_JoystickRumble(sdl_joystick.get(), static_cast<u16>(vibration.low_amplitude),
+                                      static_cast<u16>(vibration.high_amplitude),
+                                      rumble_max_duration_ms) != -1;
+        }
+
+        return false;
+    }
+    /**
+     * The Pad identifier of the joystick
+     */
+    const PadIdentifier GetPadIdentifier() const {
+        return {
+            .guid = Common::UUID{guid},
+            .port = static_cast<std::size_t>(port),
+            .pad = 0,
+        };
+    }
+
+    /**
+     * The guid of the joystick
+     */
+    const std::string& GetGUID() const {
+        return guid;
+    }
+
+    /**
+     * The number of joystick from the same type that were connected before this joystick
+     */
+    int GetPort() const {
+        return port;
+    }
+
+    SDL_Joystick* GetSDLJoystick() const {
+        return sdl_joystick.get();
+    }
+
+    SDL_GameController* GetSDLGameController() const {
+        return sdl_controller.get();
+    }
+
+    void SetSDLJoystick(SDL_Joystick* joystick, SDL_GameController* controller) {
+        sdl_joystick.reset(joystick);
+        sdl_controller.reset(controller);
+    }
+
+    bool IsJoyconLeft() const {
+        const std::string controller_name = GetControllerName();
+        if (std::strstr(controller_name.c_str(), "Joy-Con Left") != nullptr) {
+            return true;
+        }
+        if (std::strstr(controller_name.c_str(), "Joy-Con (L)") != nullptr) {
+            return true;
+        }
+        return false;
+    }
+
+    bool IsJoyconRight() const {
+        const std::string controller_name = GetControllerName();
+        if (std::strstr(controller_name.c_str(), "Joy-Con Right") != nullptr) {
+            return true;
+        }
+        if (std::strstr(controller_name.c_str(), "Joy-Con (R)") != nullptr) {
+            return true;
+        }
+        return false;
+    }
+
+    BatteryLevel GetBatteryLevel() {
+        const auto level = SDL_JoystickCurrentPowerLevel(sdl_joystick.get());
+        switch (level) {
+        case SDL_JOYSTICK_POWER_EMPTY:
+            return BatteryLevel::Empty;
+        case SDL_JOYSTICK_POWER_LOW:
+            return BatteryLevel::Critical;
+        case SDL_JOYSTICK_POWER_MEDIUM:
+            return BatteryLevel::Low;
+        case SDL_JOYSTICK_POWER_FULL:
+            return BatteryLevel::Medium;
+        case SDL_JOYSTICK_POWER_MAX:
+            return BatteryLevel::Full;
+        case SDL_JOYSTICK_POWER_UNKNOWN:
+        case SDL_JOYSTICK_POWER_WIRED:
+        default:
+            return BatteryLevel::Charging;
+        }
+    }
+
+    std::string GetControllerName() const {
+        if (sdl_controller) {
+            switch (SDL_GameControllerGetType(sdl_controller.get())) {
+            case SDL_CONTROLLER_TYPE_XBOX360:
+                return "XBox 360 Controller";
+            case SDL_CONTROLLER_TYPE_XBOXONE:
+                return "XBox One Controller";
+            default:
+                break;
+            }
+            const auto name = SDL_GameControllerName(sdl_controller.get());
+            if (name) {
+                return name;
+            }
+        }
+
+        if (sdl_joystick) {
+            const auto name = SDL_JoystickName(sdl_joystick.get());
+            if (name) {
+                return name;
+            }
+        }
+
+        return "Unknown";
+    }
+
+    bool IsYAxis(u8 index) {
+        if (!sdl_controller) {
+            return false;
+        }
+
+        const auto& binding_left_y =
+            SDL_GameControllerGetBindForAxis(sdl_controller.get(), SDL_CONTROLLER_AXIS_LEFTY);
+        const auto& binding_right_y =
+            SDL_GameControllerGetBindForAxis(sdl_controller.get(), SDL_CONTROLLER_AXIS_RIGHTY);
+        if (index == binding_left_y.value.axis) {
+            return true;
+        }
+        if (index == binding_right_y.value.axis) {
+            return true;
+        }
+        return false;
+    }
+
+private:
+    std::string guid;
+    int port;
+    std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
+    std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
+    mutable std::mutex mutex;
+
+    u64 last_motion_update{};
+    bool has_gyro{false};
+    bool has_accel{false};
+    BasicMotion motion;
+};
+
+std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string& guid, int port) {
+    std::lock_guard lock{joystick_map_mutex};
+    const auto it = joystick_map.find(guid);
+
+    if (it != joystick_map.end()) {
+        while (it->second.size() <= static_cast<std::size_t>(port)) {
+            auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()),
+                                                          nullptr, nullptr);
+            it->second.emplace_back(std::move(joystick));
+        }
+
+        return it->second[static_cast<std::size_t>(port)];
+    }
+
+    auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr);
+
+    return joystick_map[guid].emplace_back(std::move(joystick));
+}
+
+std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) {
+    auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id);
+    const std::string guid = GetGUID(sdl_joystick);
+
+    std::lock_guard lock{joystick_map_mutex};
+    const auto map_it = joystick_map.find(guid);
+
+    if (map_it == joystick_map.end()) {
+        return nullptr;
+    }
+
+    const auto vec_it = std::find_if(map_it->second.begin(), map_it->second.end(),
+                                     [&sdl_joystick](const auto& joystick) {
+                                         return joystick->GetSDLJoystick() == sdl_joystick;
+                                     });
+
+    if (vec_it == map_it->second.end()) {
+        return nullptr;
+    }
+
+    return *vec_it;
+}
+
+void SDLDriver::InitJoystick(int joystick_index) {
+    SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index);
+    SDL_GameController* sdl_gamecontroller = nullptr;
+
+    if (SDL_IsGameController(joystick_index)) {
+        sdl_gamecontroller = SDL_GameControllerOpen(joystick_index);
+    }
+
+    if (!sdl_joystick) {
+        LOG_ERROR(Input, "Failed to open joystick {}", joystick_index);
+        return;
+    }
+
+    const std::string guid = GetGUID(sdl_joystick);
+
+    std::lock_guard lock{joystick_map_mutex};
+    if (joystick_map.find(guid) == joystick_map.end()) {
+        auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller);
+        PreSetController(joystick->GetPadIdentifier());
+        joystick_map[guid].emplace_back(std::move(joystick));
+        return;
+    }
+
+    auto& joystick_guid_list = joystick_map[guid];
+    const auto joystick_it =
+        std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
+                     [](const auto& joystick) { return !joystick->GetSDLJoystick(); });
+
+    if (joystick_it != joystick_guid_list.end()) {
+        (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller);
+        return;
+    }
+
+    const int port = static_cast<int>(joystick_guid_list.size());
+    auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller);
+    PreSetController(joystick->GetPadIdentifier());
+    joystick_guid_list.emplace_back(std::move(joystick));
+}
+
+void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) {
+    const std::string guid = GetGUID(sdl_joystick);
+
+    std::lock_guard lock{joystick_map_mutex};
+    // This call to guid is safe since the joystick is guaranteed to be in the map
+    const auto& joystick_guid_list = joystick_map[guid];
+    const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
+                                          [&sdl_joystick](const auto& joystick) {
+                                              return joystick->GetSDLJoystick() == sdl_joystick;
+                                          });
+
+    if (joystick_it != joystick_guid_list.end()) {
+        (*joystick_it)->SetSDLJoystick(nullptr, nullptr);
+    }
+}
+
+void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {
+    switch (event.type) {
+    case SDL_JOYBUTTONUP: {
+        if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) {
+            const PadIdentifier identifier = joystick->GetPadIdentifier();
+            SetButton(identifier, event.jbutton.button, false);
+        }
+        break;
+    }
+    case SDL_JOYBUTTONDOWN: {
+        if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) {
+            const PadIdentifier identifier = joystick->GetPadIdentifier();
+            SetButton(identifier, event.jbutton.button, true);
+        }
+        break;
+    }
+    case SDL_JOYHATMOTION: {
+        if (const auto joystick = GetSDLJoystickBySDLID(event.jhat.which)) {
+            const PadIdentifier identifier = joystick->GetPadIdentifier();
+            SetHatButton(identifier, event.jhat.hat, event.jhat.value);
+        }
+        break;
+    }
+    case SDL_JOYAXISMOTION: {
+        if (const auto joystick = GetSDLJoystickBySDLID(event.jaxis.which)) {
+            const PadIdentifier identifier = joystick->GetPadIdentifier();
+            // Vertical axis is inverted on nintendo compared to SDL
+            if (joystick->IsYAxis(event.jaxis.axis)) {
+                SetAxis(identifier, event.jaxis.axis, -event.jaxis.value / 32767.0f);
+                break;
+            }
+            SetAxis(identifier, event.jaxis.axis, event.jaxis.value / 32767.0f);
+        }
+        break;
+    }
+    case SDL_CONTROLLERSENSORUPDATE: {
+        if (auto joystick = GetSDLJoystickBySDLID(event.csensor.which)) {
+            if (joystick->UpdateMotion(event.csensor)) {
+                const PadIdentifier identifier = joystick->GetPadIdentifier();
+                SetMotion(identifier, 0, joystick->GetMotion());
+            };
+        }
+        break;
+    }
+    case SDL_JOYDEVICEREMOVED:
+        LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which);
+        CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which));
+        break;
+    case SDL_JOYDEVICEADDED:
+        LOG_DEBUG(Input, "Controller connected with device index {}", event.jdevice.which);
+        InitJoystick(event.jdevice.which);
+        break;
+    }
+}
+
+void SDLDriver::CloseJoysticks() {
+    std::lock_guard lock{joystick_map_mutex};
+    joystick_map.clear();
+}
+
+SDLDriver::SDLDriver(const std::string& input_engine_) : InputEngine(input_engine_) {
+    Common::SetCurrentThreadName("yuzu:input:SDL");
+
+    if (!Settings::values.enable_raw_input) {
+        // Disable raw input. When enabled this setting causes SDL to die when a web applet opens
+        SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0");
+    }
+
+    // Prevent SDL from adding undesired axis
+    SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
+
+    // Enable HIDAPI rumble. This prevents SDL from disabling motion on PS4 and PS5 controllers
+    SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
+    SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
+    SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
+
+    // Use hidapi driver for joycons. This will allow joycons to be detected as a GameController and
+    // not a generic one
+    SDL_SetHint("SDL_JOYSTICK_HIDAPI_JOY_CONS", "1");
+
+    // Turn off Pro controller home led
+    SDL_SetHint("SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED", "0");
+
+    // If the frontend is going to manage the event loop, then we don't start one here
+    start_thread = SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) == 0;
+    if (start_thread && SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) {
+        LOG_CRITICAL(Input, "SDL_Init failed with: {}", SDL_GetError());
+        return;
+    }
+
+    SDL_AddEventWatch(&SDLEventWatcher, this);
+
+    initialized = true;
+    if (start_thread) {
+        poll_thread = std::thread([this] {
+            using namespace std::chrono_literals;
+            while (initialized) {
+                SDL_PumpEvents();
+                std::this_thread::sleep_for(1ms);
+            }
+        });
+    }
+    // Because the events for joystick connection happens before we have our event watcher added, we
+    // can just open all the joysticks right here
+    for (int i = 0; i < SDL_NumJoysticks(); ++i) {
+        InitJoystick(i);
+    }
+}
+
+SDLDriver::~SDLDriver() {
+    CloseJoysticks();
+    SDL_DelEventWatch(&SDLEventWatcher, this);
+
+    initialized = false;
+    if (start_thread) {
+        poll_thread.join();
+        SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
+    }
+}
+
+std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
+    std::vector<Common::ParamPackage> devices;
+    std::unordered_map<int, std::shared_ptr<SDLJoystick>> joycon_pairs;
+    for (const auto& [key, value] : joystick_map) {
+        for (const auto& joystick : value) {
+            if (!joystick->GetSDLJoystick()) {
+                continue;
+            }
+            const std::string name =
+                fmt::format("{} {}", joystick->GetControllerName(), joystick->GetPort());
+            devices.emplace_back(Common::ParamPackage{
+                {"engine", "sdl"},
+                {"display", std::move(name)},
+                {"guid", joystick->GetGUID()},
+                {"port", std::to_string(joystick->GetPort())},
+            });
+            if (joystick->IsJoyconLeft()) {
+                joycon_pairs.insert_or_assign(joystick->GetPort(), joystick);
+            }
+        }
+    }
+
+    // Add dual controllers
+    for (const auto& [key, value] : joystick_map) {
+        for (const auto& joystick : value) {
+            if (joystick->IsJoyconRight()) {
+                if (!joycon_pairs.contains(joystick->GetPort())) {
+                    continue;
+                }
+                const auto joystick2 = joycon_pairs.at(joystick->GetPort());
+
+                const std::string name =
+                    fmt::format("{} {}", "Nintendo Dual Joy-Con", joystick->GetPort());
+                devices.emplace_back(Common::ParamPackage{
+                    {"engine", "sdl"},
+                    {"display", std::move(name)},
+                    {"guid", joystick->GetGUID()},
+                    {"guid2", joystick2->GetGUID()},
+                    {"port", std::to_string(joystick->GetPort())},
+                });
+            }
+        }
+    }
+    return devices;
+}
+bool SDLDriver::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) {
+    const auto joystick =
+        GetSDLJoystickByGUID(identifier.guid.Format(), static_cast<int>(identifier.port));
+    const auto process_amplitude = [](f32 amplitude) {
+        return (amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF;
+    };
+    const Input::VibrationStatus new_vibration{
+        .low_amplitude = process_amplitude(vibration.low_amplitude),
+        .low_frequency = vibration.low_frequency,
+        .high_amplitude = process_amplitude(vibration.high_amplitude),
+        .high_frequency = vibration.high_frequency,
+    };
+
+    return joystick->RumblePlay(new_vibration);
+}
+Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,
+                                                                 s32 axis, float value) const {
+    Common::ParamPackage params({{"engine", "sdl"}});
+    params.Set("port", port);
+    params.Set("guid", std::move(guid));
+    params.Set("axis", axis);
+    params.Set("threshold", "0.5");
+    params.Set("invert", value < 0 ? "-" : "+");
+    return params;
+}
+
+Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, std::string guid,
+                                                                 s32 button) const {
+    Common::ParamPackage params({{"engine", "sdl"}});
+    params.Set("port", port);
+    params.Set("guid", std::move(guid));
+    params.Set("button", button);
+    return params;
+}
+
+Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, std::string guid, s32 hat,
+                                                              u8 value) const {
+    Common::ParamPackage params({{"engine", "sdl"}});
+
+    params.Set("port", port);
+    params.Set("guid", std::move(guid));
+    params.Set("hat", hat);
+    params.Set("direction", GetHatButtonName(value));
+    return params;
+}
+
+Common::ParamPackage SDLDriver::BuildMotionParam(int port, std::string guid) const {
+    Common::ParamPackage params({{"engine", "sdl"}, {"motion", "0"}});
+    params.Set("port", port);
+    params.Set("guid", std::move(guid));
+    return params;
+}
+
+Common::ParamPackage SDLDriver::BuildParamPackageForBinding(
+    int port, const std::string& guid, const SDL_GameControllerButtonBind& binding) const {
+    switch (binding.bindType) {
+    case SDL_CONTROLLER_BINDTYPE_NONE:
+        break;
+    case SDL_CONTROLLER_BINDTYPE_AXIS:
+        return BuildAnalogParamPackageForButton(port, guid, binding.value.axis);
+    case SDL_CONTROLLER_BINDTYPE_BUTTON:
+        return BuildButtonParamPackageForButton(port, guid, binding.value.button);
+    case SDL_CONTROLLER_BINDTYPE_HAT:
+        return BuildHatParamPackageForButton(port, guid, binding.value.hat.hat,
+                                             static_cast<u8>(binding.value.hat.hat_mask));
+    }
+    return {};
+}
+
+Common::ParamPackage SDLDriver::BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x,
+                                                           int axis_y, float offset_x,
+                                                           float offset_y) const {
+    Common::ParamPackage params;
+    params.Set("engine", "sdl");
+    params.Set("port", static_cast<int>(identifier.port));
+    params.Set("guid", identifier.guid.Format());
+    params.Set("axis_x", axis_x);
+    params.Set("axis_y", axis_y);
+    params.Set("offset_x", offset_x);
+    params.Set("offset_y", offset_y);
+    params.Set("invert_x", "+");
+    params.Set("invert_y", "+");
+    return params;
+}
+
+ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& params) {
+    if (!params.Has("guid") || !params.Has("port")) {
+        return {};
+    }
+    const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
+
+    auto* controller = joystick->GetSDLGameController();
+    if (controller == nullptr) {
+        return {};
+    }
+
+    // This list is missing ZL/ZR since those are not considered buttons in SDL GameController.
+    // We will add those afterwards
+    // This list also excludes Screenshot since theres not really a mapping for that
+    ButtonBindings switch_to_sdl_button;
+
+    if (SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) {
+        switch_to_sdl_button = GetNintendoButtonBinding(joystick);
+    } else {
+        switch_to_sdl_button = GetDefaultButtonBinding();
+    }
+
+    // Add the missing bindings for ZL/ZR
+    static constexpr ZButtonBindings switch_to_sdl_axis{{
+        {Settings::NativeButton::ZL, SDL_CONTROLLER_AXIS_TRIGGERLEFT},
+        {Settings::NativeButton::ZR, SDL_CONTROLLER_AXIS_TRIGGERRIGHT},
+    }};
+
+    // Parameters contain two joysticks return dual
+    if (params.Has("guid2")) {
+        const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0));
+
+        if (joystick2->GetSDLGameController() != nullptr) {
+            return GetDualControllerMapping(joystick, joystick2, switch_to_sdl_button,
+                                            switch_to_sdl_axis);
+        }
+    }
+
+    return GetSingleControllerMapping(joystick, switch_to_sdl_button, switch_to_sdl_axis);
+}
+
+ButtonBindings SDLDriver::GetDefaultButtonBinding() const {
+    return {
+        std::pair{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B},
+        {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A},
+        {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y},
+        {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X},
+        {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK},
+        {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
+        {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
+        {Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
+        {Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START},
+        {Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK},
+        {Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT},
+        {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP},
+        {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
+        {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN},
+        {Settings::NativeButton::SL, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
+        {Settings::NativeButton::SR, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
+        {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE},
+    };
+}
+
+ButtonBindings SDLDriver::GetNintendoButtonBinding(
+    const std::shared_ptr<SDLJoystick>& joystick) const {
+    // Default SL/SR mapping for pro controllers
+    auto sl_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
+    auto sr_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
+
+    if (joystick->IsJoyconLeft()) {
+        sl_button = SDL_CONTROLLER_BUTTON_PADDLE2;
+        sr_button = SDL_CONTROLLER_BUTTON_PADDLE4;
+    }
+    if (joystick->IsJoyconRight()) {
+        sl_button = SDL_CONTROLLER_BUTTON_PADDLE3;
+        sr_button = SDL_CONTROLLER_BUTTON_PADDLE1;
+    }
+
+    return {
+        std::pair{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_A},
+        {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_B},
+        {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_X},
+        {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_Y},
+        {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK},
+        {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
+        {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
+        {Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
+        {Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START},
+        {Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK},
+        {Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT},
+        {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP},
+        {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
+        {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN},
+        {Settings::NativeButton::SL, sl_button},
+        {Settings::NativeButton::SR, sr_button},
+        {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE},
+    };
+}
+
+ButtonMapping SDLDriver::GetSingleControllerMapping(
+    const std::shared_ptr<SDLJoystick>& joystick, const ButtonBindings& switch_to_sdl_button,
+    const ZButtonBindings& switch_to_sdl_axis) const {
+    ButtonMapping mapping;
+    mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size());
+    auto* controller = joystick->GetSDLGameController();
+
+    for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) {
+        const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button);
+        mapping.insert_or_assign(
+            switch_button,
+            BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
+    }
+    for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) {
+        const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis);
+        mapping.insert_or_assign(
+            switch_button,
+            BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
+    }
+
+    return mapping;
+}
+
+ButtonMapping SDLDriver::GetDualControllerMapping(const std::shared_ptr<SDLJoystick>& joystick,
+                                                  const std::shared_ptr<SDLJoystick>& joystick2,
+                                                  const ButtonBindings& switch_to_sdl_button,
+                                                  const ZButtonBindings& switch_to_sdl_axis) const {
+    ButtonMapping mapping;
+    mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size());
+    auto* controller = joystick->GetSDLGameController();
+    auto* controller2 = joystick2->GetSDLGameController();
+
+    for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) {
+        if (IsButtonOnLeftSide(switch_button)) {
+            const auto& binding = SDL_GameControllerGetBindForButton(controller2, sdl_button);
+            mapping.insert_or_assign(
+                switch_button,
+                BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding));
+            continue;
+        }
+        const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button);
+        mapping.insert_or_assign(
+            switch_button,
+            BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
+    }
+    for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) {
+        if (IsButtonOnLeftSide(switch_button)) {
+            const auto& binding = SDL_GameControllerGetBindForAxis(controller2, sdl_axis);
+            mapping.insert_or_assign(
+                switch_button,
+                BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding));
+            continue;
+        }
+        const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis);
+        mapping.insert_or_assign(
+            switch_button,
+            BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
+    }
+
+    return mapping;
+}
+
+bool SDLDriver::IsButtonOnLeftSide(Settings::NativeButton::Values button) const {
+    switch (button) {
+    case Settings::NativeButton::DDown:
+    case Settings::NativeButton::DLeft:
+    case Settings::NativeButton::DRight:
+    case Settings::NativeButton::DUp:
+    case Settings::NativeButton::L:
+    case Settings::NativeButton::LStick:
+    case Settings::NativeButton::Minus:
+    case Settings::NativeButton::Screenshot:
+    case Settings::NativeButton::ZL:
+        return true;
+    default:
+        return false;
+    }
+}
+
+AnalogMapping SDLDriver::GetAnalogMappingForDevice(const Common::ParamPackage& params) {
+    if (!params.Has("guid") || !params.Has("port")) {
+        return {};
+    }
+    const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
+    const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0));
+    auto* controller = joystick->GetSDLGameController();
+    if (controller == nullptr) {
+        return {};
+    }
+
+    AnalogMapping mapping = {};
+    const auto& binding_left_x =
+        SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX);
+    const auto& binding_left_y =
+        SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY);
+    if (params.Has("guid2")) {
+        const auto identifier = joystick2->GetPadIdentifier();
+        PreSetController(identifier);
+        PreSetAxis(identifier, binding_left_x.value.axis);
+        PreSetAxis(identifier, binding_left_y.value.axis);
+        const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis);
+        const auto left_offset_y = -GetAxis(identifier, binding_left_y.value.axis);
+        mapping.insert_or_assign(Settings::NativeAnalog::LStick,
+                                 BuildParamPackageForAnalog(identifier, binding_left_x.value.axis,
+                                                            binding_left_y.value.axis,
+                                                            left_offset_x, left_offset_y));
+    } else {
+        const auto identifier = joystick->GetPadIdentifier();
+        PreSetController(identifier);
+        PreSetAxis(identifier, binding_left_x.value.axis);
+        PreSetAxis(identifier, binding_left_y.value.axis);
+        const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis);
+        const auto left_offset_y = -GetAxis(identifier, binding_left_y.value.axis);
+        mapping.insert_or_assign(Settings::NativeAnalog::LStick,
+                                 BuildParamPackageForAnalog(identifier, binding_left_x.value.axis,
+                                                            binding_left_y.value.axis,
+                                                            left_offset_x, left_offset_y));
+    }
+    const auto& binding_right_x =
+        SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX);
+    const auto& binding_right_y =
+        SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY);
+    const auto identifier = joystick->GetPadIdentifier();
+    PreSetController(identifier);
+    PreSetAxis(identifier, binding_right_x.value.axis);
+    PreSetAxis(identifier, binding_right_y.value.axis);
+    const auto right_offset_x = -GetAxis(identifier, binding_right_x.value.axis);
+    const auto right_offset_y = -GetAxis(identifier, binding_right_y.value.axis);
+    mapping.insert_or_assign(Settings::NativeAnalog::RStick,
+                             BuildParamPackageForAnalog(identifier, binding_right_x.value.axis,
+                                                        binding_right_y.value.axis, right_offset_x,
+                                                        right_offset_y));
+    return mapping;
+}
+
+MotionMapping SDLDriver::GetMotionMappingForDevice(const Common::ParamPackage& params) {
+    if (!params.Has("guid") || !params.Has("port")) {
+        return {};
+    }
+    const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
+    const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0));
+    auto* controller = joystick->GetSDLGameController();
+    if (controller == nullptr) {
+        return {};
+    }
+
+    MotionMapping mapping = {};
+    joystick->EnableMotion();
+
+    if (joystick->HasGyro() || joystick->HasAccel()) {
+        mapping.insert_or_assign(Settings::NativeMotion::MotionRight,
+                                 BuildMotionParam(joystick->GetPort(), joystick->GetGUID()));
+    }
+    if (params.Has("guid2")) {
+        joystick2->EnableMotion();
+        if (joystick2->HasGyro() || joystick2->HasAccel()) {
+            mapping.insert_or_assign(Settings::NativeMotion::MotionLeft,
+                                     BuildMotionParam(joystick2->GetPort(), joystick2->GetGUID()));
+        }
+    } else {
+        if (joystick->HasGyro() || joystick->HasAccel()) {
+            mapping.insert_or_assign(Settings::NativeMotion::MotionLeft,
+                                     BuildMotionParam(joystick->GetPort(), joystick->GetGUID()));
+        }
+    }
+
+    return mapping;
+}
+
+std::string SDLDriver::GetUIName(const Common::ParamPackage& params) const {
+    if (params.Has("button")) {
+        // TODO(German77): Find how to substitue the values for real button names
+        return fmt::format("Button {}", params.Get("button", 0));
+    }
+    if (params.Has("hat")) {
+        return fmt::format("Hat {}", params.Get("direction", ""));
+    }
+    if (params.Has("axis")) {
+        return fmt::format("Axis {}", params.Get("axis", ""));
+    }
+    if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) {
+        return fmt::format("Axis {},{},{}", params.Get("axis_x", ""), params.Get("axis_y", ""),
+                           params.Get("axis_z", ""));
+    }
+    if (params.Has("motion")) {
+        return "SDL motion";
+    }
+
+    return "Bad SDL";
+}
+
+std::string SDLDriver::GetHatButtonName(u8 direction_value) const {
+    switch (direction_value) {
+    case SDL_HAT_UP:
+        return "up";
+    case SDL_HAT_DOWN:
+        return "down";
+    case SDL_HAT_LEFT:
+        return "left";
+    case SDL_HAT_RIGHT:
+        return "right";
+    default:
+        return {};
+    }
+}
+
+u8 SDLDriver::GetHatButtonId(const std::string direction_name) const {
+    Uint8 direction;
+    if (direction_name == "up") {
+        direction = SDL_HAT_UP;
+    } else if (direction_name == "down") {
+        direction = SDL_HAT_DOWN;
+    } else if (direction_name == "left") {
+        direction = SDL_HAT_LEFT;
+    } else if (direction_name == "right") {
+        direction = SDL_HAT_RIGHT;
+    } else {
+        direction = 0;
+    }
+    return direction;
+}
+
+} // namespace InputCommon
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/drivers/sdl_driver.h
similarity index 67%
rename from src/input_common/sdl/sdl_impl.h
rename to src/input_common/drivers/sdl_driver.h
index 7a9ad63465..d8d3501842 100644
--- a/src/input_common/sdl/sdl_impl.h
+++ b/src/input_common/drivers/sdl_driver.h
@@ -5,7 +5,6 @@
 #pragma once
 
 #include <atomic>
-#include <memory>
 #include <mutex>
 #include <thread>
 #include <unordered_map>
@@ -13,8 +12,7 @@
 #include <SDL.h>
 
 #include "common/common_types.h"
-#include "common/threadsafe_queue.h"
-#include "input_common/sdl/sdl.h"
+#include "input_common/input_engine.h"
 
 union SDL_Event;
 using SDL_GameController = struct _SDL_GameController;
@@ -26,21 +24,17 @@ using ButtonBindings =
 using ZButtonBindings =
     std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerAxis>, 2>;
 
-namespace InputCommon::SDL {
+namespace InputCommon {
 
-class SDLAnalogFactory;
-class SDLButtonFactory;
-class SDLMotionFactory;
-class SDLVibrationFactory;
 class SDLJoystick;
 
-class SDLState : public State {
+class SDLDriver : public InputCommon::InputEngine {
 public:
     /// Initializes and registers SDL device factories
-    SDLState();
+    SDLDriver(const std::string& input_engine_);
 
     /// Unregisters SDL device factories and shut them down.
-    ~SDLState() override;
+    ~SDLDriver() override;
 
     /// Handle SDL_Events for joysticks from SDL_PollEvent
     void HandleGameControllerEvent(const SDL_Event& event);
@@ -54,18 +48,18 @@ public:
      */
     std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port);
 
-    /// Get all DevicePoller that use the SDL backend for a specific device type
-    Pollers GetPollers(Polling::DeviceType type) override;
-
-    /// Used by the Pollers during config
-    std::atomic<bool> polling = false;
-    Common::SPSCQueue<SDL_Event> event_queue;
-
-    std::vector<Common::ParamPackage> GetInputDevices() override;
+    std::vector<Common::ParamPackage> GetInputDevices() const override;
 
     ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override;
     AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
     MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override;
+    std::string GetUIName(const Common::ParamPackage& params) const override;
+
+    std::string GetHatButtonName(u8 direction_value) const override;
+    u8 GetHatButtonId(const std::string direction_name) const override;
+
+    bool SetRumble(const PadIdentifier& identifier,
+                   const Input::VibrationStatus vibration) override;
 
 private:
     void InitJoystick(int joystick_index);
@@ -74,6 +68,23 @@ private:
     /// Needs to be called before SDL_QuitSubSystem.
     void CloseJoysticks();
 
+    Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis,
+                                                          float value = 0.1f) const;
+    Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid,
+                                                          s32 button) const;
+
+    Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s32 hat,
+                                                       u8 value) const;
+
+    Common::ParamPackage BuildMotionParam(int port, std::string guid) const;
+
+    Common::ParamPackage BuildParamPackageForBinding(
+        int port, const std::string& guid, const SDL_GameControllerButtonBind& binding) const;
+
+    Common::ParamPackage BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x,
+                                                    int axis_y, float offset_x,
+                                                    float offset_y) const;
+
     /// Returns the default button bindings list for generic controllers
     ButtonBindings GetDefaultButtonBinding() const;
 
@@ -101,14 +112,9 @@ private:
     std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
     std::mutex joystick_map_mutex;
 
-    std::shared_ptr<SDLButtonFactory> button_factory;
-    std::shared_ptr<SDLAnalogFactory> analog_factory;
-    std::shared_ptr<SDLVibrationFactory> vibration_factory;
-    std::shared_ptr<SDLMotionFactory> motion_factory;
-
     bool start_thread = false;
     std::atomic<bool> initialized = false;
 
     std::thread poll_thread;
 };
-} // namespace InputCommon::SDL
+} // namespace InputCommon
diff --git a/src/input_common/sdl/sdl.cpp b/src/input_common/sdl/sdl.cpp
deleted file mode 100644
index 644db3448f..0000000000
--- a/src/input_common/sdl/sdl.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "input_common/sdl/sdl.h"
-#ifdef HAVE_SDL2
-#include "input_common/sdl/sdl_impl.h"
-#endif
-
-namespace InputCommon::SDL {
-
-std::unique_ptr<State> Init() {
-#ifdef HAVE_SDL2
-    return std::make_unique<SDLState>();
-#else
-    return std::make_unique<NullState>();
-#endif
-}
-} // namespace InputCommon::SDL
diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h
deleted file mode 100644
index b5d41bba42..0000000000
--- a/src/input_common/sdl/sdl.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2018 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include <vector>
-#include "common/param_package.h"
-#include "input_common/main.h"
-
-namespace InputCommon::Polling {
-class DevicePoller;
-enum class DeviceType;
-} // namespace InputCommon::Polling
-
-namespace InputCommon::SDL {
-
-class State {
-public:
-    using Pollers = std::vector<std::unique_ptr<Polling::DevicePoller>>;
-
-    /// Unregisters SDL device factories and shut them down.
-    virtual ~State() = default;
-
-    virtual Pollers GetPollers(Polling::DeviceType) {
-        return {};
-    }
-
-    virtual std::vector<Common::ParamPackage> GetInputDevices() {
-        return {};
-    }
-
-    virtual ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage&) {
-        return {};
-    }
-    virtual AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&) {
-        return {};
-    }
-    virtual MotionMapping GetMotionMappingForDevice(const Common::ParamPackage&) {
-        return {};
-    }
-};
-
-class NullState : public State {
-public:
-};
-
-std::unique_ptr<State> Init();
-
-} // namespace InputCommon::SDL
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
deleted file mode 100644
index ecb00d4286..0000000000
--- a/src/input_common/sdl/sdl_impl.cpp
+++ /dev/null
@@ -1,1658 +0,0 @@
-// Copyright 2018 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <array>
-#include <atomic>
-#include <chrono>
-#include <cmath>
-#include <functional>
-#include <mutex>
-#include <optional>
-#include <sstream>
-#include <string>
-#include <thread>
-#include <tuple>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include "common/logging/log.h"
-#include "common/math_util.h"
-#include "common/param_package.h"
-#include "common/settings.h"
-#include "common/threadsafe_queue.h"
-#include "core/frontend/input.h"
-#include "input_common/motion_input.h"
-#include "input_common/sdl/sdl_impl.h"
-
-namespace InputCommon::SDL {
-
-namespace {
-std::string GetGUID(SDL_Joystick* joystick) {
-    const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
-    char guid_str[33];
-    SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
-    return guid_str;
-}
-
-/// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice
-Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event);
-} // Anonymous namespace
-
-static int SDLEventWatcher(void* user_data, SDL_Event* event) {
-    auto* const sdl_state = static_cast<SDLState*>(user_data);
-
-    // Don't handle the event if we are configuring
-    if (sdl_state->polling) {
-        sdl_state->event_queue.Push(*event);
-    } else {
-        sdl_state->HandleGameControllerEvent(*event);
-    }
-
-    return 0;
-}
-
-class SDLJoystick {
-public:
-    SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick,
-                SDL_GameController* game_controller)
-        : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose},
-          sdl_controller{game_controller, &SDL_GameControllerClose} {
-        EnableMotion();
-    }
-
-    void EnableMotion() {
-        if (sdl_controller) {
-            SDL_GameController* controller = sdl_controller.get();
-            if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) && !has_accel) {
-                SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
-                has_accel = true;
-            }
-            if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) && !has_gyro) {
-                SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
-                has_gyro = true;
-            }
-        }
-    }
-
-    void SetButton(int button, bool value) {
-        std::lock_guard lock{mutex};
-        state.buttons.insert_or_assign(button, value);
-    }
-
-    void PreSetButton(int button) {
-        if (!state.buttons.contains(button)) {
-            SetButton(button, false);
-        }
-    }
-
-    void SetMotion(SDL_ControllerSensorEvent event) {
-        constexpr float gravity_constant = 9.80665f;
-        std::lock_guard lock{mutex};
-        u64 time_difference = event.timestamp - last_motion_update;
-        last_motion_update = event.timestamp;
-        switch (event.sensor) {
-        case SDL_SENSOR_ACCEL: {
-            const Common::Vec3f acceleration = {-event.data[0], event.data[2], -event.data[1]};
-            motion.SetAcceleration(acceleration / gravity_constant);
-            break;
-        }
-        case SDL_SENSOR_GYRO: {
-            const Common::Vec3f gyroscope = {event.data[0], -event.data[2], event.data[1]};
-            motion.SetGyroscope(gyroscope / (Common::PI * 2));
-            break;
-        }
-        }
-
-        // Ignore duplicated timestamps
-        if (time_difference == 0) {
-            return;
-        }
-
-        motion.SetGyroThreshold(0.0001f);
-        motion.UpdateRotation(time_difference * 1000);
-        motion.UpdateOrientation(time_difference * 1000);
-    }
-
-    bool GetButton(int button) const {
-        std::lock_guard lock{mutex};
-        return state.buttons.at(button);
-    }
-
-    bool ToggleButton(int button) {
-        std::lock_guard lock{mutex};
-
-        if (!state.toggle_buttons.contains(button) || !state.lock_buttons.contains(button)) {
-            state.toggle_buttons.insert_or_assign(button, false);
-            state.lock_buttons.insert_or_assign(button, false);
-        }
-
-        const bool button_state = state.toggle_buttons.at(button);
-        const bool button_lock = state.lock_buttons.at(button);
-
-        if (button_lock) {
-            return button_state;
-        }
-
-        state.lock_buttons.insert_or_assign(button, true);
-
-        if (button_state) {
-            state.toggle_buttons.insert_or_assign(button, false);
-        } else {
-            state.toggle_buttons.insert_or_assign(button, true);
-        }
-
-        return !button_state;
-    }
-
-    bool UnlockButton(int button) {
-        std::lock_guard lock{mutex};
-        if (!state.toggle_buttons.contains(button)) {
-            return false;
-        }
-        state.lock_buttons.insert_or_assign(button, false);
-        return state.toggle_buttons.at(button);
-    }
-
-    void SetAxis(int axis, Sint16 value) {
-        std::lock_guard lock{mutex};
-        state.axes.insert_or_assign(axis, value);
-    }
-
-    void PreSetAxis(int axis) {
-        if (!state.axes.contains(axis)) {
-            SetAxis(axis, 0);
-        }
-    }
-
-    float GetAxis(int axis, float range, float offset) const {
-        std::lock_guard lock{mutex};
-        const float value = static_cast<float>(state.axes.at(axis)) / 32767.0f;
-        const float offset_scale = (value + offset) > 0.0f ? 1.0f + offset : 1.0f - offset;
-        return (value + offset) / range / offset_scale;
-    }
-
-    bool RumblePlay(u16 amp_low, u16 amp_high) {
-        constexpr u32 rumble_max_duration_ms = 1000;
-
-        if (sdl_controller) {
-            return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high,
-                                            rumble_max_duration_ms) != -1;
-        } else if (sdl_joystick) {
-            return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high,
-                                      rumble_max_duration_ms) != -1;
-        }
-
-        return false;
-    }
-
-    std::tuple<float, float> GetAnalog(int axis_x, int axis_y, float range, float offset_x,
-                                       float offset_y) const {
-        float x = GetAxis(axis_x, range, offset_x);
-        float y = GetAxis(axis_y, range, offset_y);
-        y = -y; // 3DS uses an y-axis inverse from SDL
-
-        // Make sure the coordinates are in the unit circle,
-        // otherwise normalize it.
-        float r = x * x + y * y;
-        if (r > 1.0f) {
-            r = std::sqrt(r);
-            x /= r;
-            y /= r;
-        }
-
-        return std::make_tuple(x, y);
-    }
-
-    bool HasGyro() const {
-        return has_gyro;
-    }
-
-    bool HasAccel() const {
-        return has_accel;
-    }
-
-    const MotionInput& GetMotion() const {
-        return motion;
-    }
-
-    void SetHat(int hat, Uint8 direction) {
-        std::lock_guard lock{mutex};
-        state.hats.insert_or_assign(hat, direction);
-    }
-
-    bool GetHatDirection(int hat, Uint8 direction) const {
-        std::lock_guard lock{mutex};
-        return (state.hats.at(hat) & direction) != 0;
-    }
-    /**
-     * The guid of the joystick
-     */
-    const std::string& GetGUID() const {
-        return guid;
-    }
-
-    /**
-     * The number of joystick from the same type that were connected before this joystick
-     */
-    int GetPort() const {
-        return port;
-    }
-
-    SDL_Joystick* GetSDLJoystick() const {
-        return sdl_joystick.get();
-    }
-
-    SDL_GameController* GetSDLGameController() const {
-        return sdl_controller.get();
-    }
-
-    void SetSDLJoystick(SDL_Joystick* joystick, SDL_GameController* controller) {
-        sdl_joystick.reset(joystick);
-        sdl_controller.reset(controller);
-    }
-
-    bool IsJoyconLeft() const {
-        const std::string controller_name = GetControllerName();
-        if (std::strstr(controller_name.c_str(), "Joy-Con Left") != nullptr) {
-            return true;
-        }
-        if (std::strstr(controller_name.c_str(), "Joy-Con (L)") != nullptr) {
-            return true;
-        }
-        return false;
-    }
-
-    bool IsJoyconRight() const {
-        const std::string controller_name = GetControllerName();
-        if (std::strstr(controller_name.c_str(), "Joy-Con Right") != nullptr) {
-            return true;
-        }
-        if (std::strstr(controller_name.c_str(), "Joy-Con (R)") != nullptr) {
-            return true;
-        }
-        return false;
-    }
-
-    std::string GetControllerName() const {
-        if (sdl_controller) {
-            switch (SDL_GameControllerGetType(sdl_controller.get())) {
-            case SDL_CONTROLLER_TYPE_XBOX360:
-                return "XBox 360 Controller";
-            case SDL_CONTROLLER_TYPE_XBOXONE:
-                return "XBox One Controller";
-            default:
-                break;
-            }
-            const auto name = SDL_GameControllerName(sdl_controller.get());
-            if (name) {
-                return name;
-            }
-        }
-
-        if (sdl_joystick) {
-            const auto name = SDL_JoystickName(sdl_joystick.get());
-            if (name) {
-                return name;
-            }
-        }
-
-        return "Unknown";
-    }
-
-private:
-    struct State {
-        std::unordered_map<int, bool> buttons;
-        std::unordered_map<int, bool> toggle_buttons{};
-        std::unordered_map<int, bool> lock_buttons{};
-        std::unordered_map<int, Sint16> axes;
-        std::unordered_map<int, Uint8> hats;
-    } state;
-    std::string guid;
-    int port;
-    std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
-    std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
-    mutable std::mutex mutex;
-
-    // Motion is initialized with the PID values
-    MotionInput motion{0.3f, 0.005f, 0.0f};
-    u64 last_motion_update{};
-    bool has_gyro{false};
-    bool has_accel{false};
-};
-
-std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) {
-    std::lock_guard lock{joystick_map_mutex};
-    const auto it = joystick_map.find(guid);
-
-    if (it != joystick_map.end()) {
-        while (it->second.size() <= static_cast<std::size_t>(port)) {
-            auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()),
-                                                          nullptr, nullptr);
-            it->second.emplace_back(std::move(joystick));
-        }
-
-        return it->second[static_cast<std::size_t>(port)];
-    }
-
-    auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr);
-
-    return joystick_map[guid].emplace_back(std::move(joystick));
-}
-
-std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) {
-    auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id);
-    const std::string guid = GetGUID(sdl_joystick);
-
-    std::lock_guard lock{joystick_map_mutex};
-    const auto map_it = joystick_map.find(guid);
-
-    if (map_it == joystick_map.end()) {
-        return nullptr;
-    }
-
-    const auto vec_it = std::find_if(map_it->second.begin(), map_it->second.end(),
-                                     [&sdl_joystick](const auto& joystick) {
-                                         return joystick->GetSDLJoystick() == sdl_joystick;
-                                     });
-
-    if (vec_it == map_it->second.end()) {
-        return nullptr;
-    }
-
-    return *vec_it;
-}
-
-void SDLState::InitJoystick(int joystick_index) {
-    SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index);
-    SDL_GameController* sdl_gamecontroller = nullptr;
-
-    if (SDL_IsGameController(joystick_index)) {
-        sdl_gamecontroller = SDL_GameControllerOpen(joystick_index);
-    }
-
-    if (!sdl_joystick) {
-        LOG_ERROR(Input, "Failed to open joystick {}", joystick_index);
-        return;
-    }
-
-    const std::string guid = GetGUID(sdl_joystick);
-
-    std::lock_guard lock{joystick_map_mutex};
-    if (joystick_map.find(guid) == joystick_map.end()) {
-        auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller);
-        joystick_map[guid].emplace_back(std::move(joystick));
-        return;
-    }
-
-    auto& joystick_guid_list = joystick_map[guid];
-    const auto joystick_it =
-        std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
-                     [](const auto& joystick) { return !joystick->GetSDLJoystick(); });
-
-    if (joystick_it != joystick_guid_list.end()) {
-        (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller);
-        return;
-    }
-
-    const int port = static_cast<int>(joystick_guid_list.size());
-    auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller);
-    joystick_guid_list.emplace_back(std::move(joystick));
-}
-
-void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) {
-    const std::string guid = GetGUID(sdl_joystick);
-
-    std::lock_guard lock{joystick_map_mutex};
-    // This call to guid is safe since the joystick is guaranteed to be in the map
-    const auto& joystick_guid_list = joystick_map[guid];
-    const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
-                                          [&sdl_joystick](const auto& joystick) {
-                                              return joystick->GetSDLJoystick() == sdl_joystick;
-                                          });
-
-    if (joystick_it != joystick_guid_list.end()) {
-        (*joystick_it)->SetSDLJoystick(nullptr, nullptr);
-    }
-}
-
-void SDLState::HandleGameControllerEvent(const SDL_Event& event) {
-    switch (event.type) {
-    case SDL_JOYBUTTONUP: {
-        if (auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) {
-            joystick->SetButton(event.jbutton.button, false);
-        }
-        break;
-    }
-    case SDL_JOYBUTTONDOWN: {
-        if (auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) {
-            joystick->SetButton(event.jbutton.button, true);
-        }
-        break;
-    }
-    case SDL_JOYHATMOTION: {
-        if (auto joystick = GetSDLJoystickBySDLID(event.jhat.which)) {
-            joystick->SetHat(event.jhat.hat, event.jhat.value);
-        }
-        break;
-    }
-    case SDL_JOYAXISMOTION: {
-        if (auto joystick = GetSDLJoystickBySDLID(event.jaxis.which)) {
-            joystick->SetAxis(event.jaxis.axis, event.jaxis.value);
-        }
-        break;
-    }
-    case SDL_CONTROLLERSENSORUPDATE: {
-        if (auto joystick = GetSDLJoystickBySDLID(event.csensor.which)) {
-            joystick->SetMotion(event.csensor);
-        }
-        break;
-    }
-    case SDL_JOYDEVICEREMOVED:
-        LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which);
-        CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which));
-        break;
-    case SDL_JOYDEVICEADDED:
-        LOG_DEBUG(Input, "Controller connected with device index {}", event.jdevice.which);
-        InitJoystick(event.jdevice.which);
-        break;
-    }
-}
-
-void SDLState::CloseJoysticks() {
-    std::lock_guard lock{joystick_map_mutex};
-    joystick_map.clear();
-}
-
-class SDLButton final : public Input::ButtonDevice {
-public:
-    explicit SDLButton(std::shared_ptr<SDLJoystick> joystick_, int button_, bool toggle_)
-        : joystick(std::move(joystick_)), button(button_), toggle(toggle_) {}
-
-    bool GetStatus() const override {
-        const bool button_state = joystick->GetButton(button);
-        if (!toggle) {
-            return button_state;
-        }
-
-        if (button_state) {
-            return joystick->ToggleButton(button);
-        }
-        return joystick->UnlockButton(button);
-    }
-
-private:
-    std::shared_ptr<SDLJoystick> joystick;
-    int button;
-    bool toggle;
-};
-
-class SDLDirectionButton final : public Input::ButtonDevice {
-public:
-    explicit SDLDirectionButton(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
-        : joystick(std::move(joystick_)), hat(hat_), direction(direction_) {}
-
-    bool GetStatus() const override {
-        return joystick->GetHatDirection(hat, direction);
-    }
-
-private:
-    std::shared_ptr<SDLJoystick> joystick;
-    int hat;
-    Uint8 direction;
-};
-
-class SDLAxisButton final : public Input::ButtonDevice {
-public:
-    explicit SDLAxisButton(std::shared_ptr<SDLJoystick> joystick_, int axis_, float threshold_,
-                           bool trigger_if_greater_)
-        : joystick(std::move(joystick_)), axis(axis_), threshold(threshold_),
-          trigger_if_greater(trigger_if_greater_) {}
-
-    bool GetStatus() const override {
-        const float axis_value = joystick->GetAxis(axis, 1.0f, 0.0f);
-        if (trigger_if_greater) {
-            return axis_value > threshold;
-        }
-        return axis_value < threshold;
-    }
-
-private:
-    std::shared_ptr<SDLJoystick> joystick;
-    int axis;
-    float threshold;
-    bool trigger_if_greater;
-};
-
-class SDLAnalog final : public Input::AnalogDevice {
-public:
-    explicit SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_,
-                       bool invert_x_, bool invert_y_, float deadzone_, float range_,
-                       float offset_x_, float offset_y_)
-        : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), invert_x(invert_x_),
-          invert_y(invert_y_), deadzone(deadzone_), range(range_), offset_x(offset_x_),
-          offset_y(offset_y_) {}
-
-    std::tuple<float, float> GetStatus() const override {
-        auto [x, y] = joystick->GetAnalog(axis_x, axis_y, range, offset_x, offset_y);
-        const float r = std::sqrt((x * x) + (y * y));
-        if (invert_x) {
-            x = -x;
-        }
-        if (invert_y) {
-            y = -y;
-        }
-
-        if (r > deadzone) {
-            return std::make_tuple(x / r * (r - deadzone) / (1 - deadzone),
-                                   y / r * (r - deadzone) / (1 - deadzone));
-        }
-        return {};
-    }
-
-    std::tuple<float, float> GetRawStatus() const override {
-        const float x = joystick->GetAxis(axis_x, range, offset_x);
-        const float y = joystick->GetAxis(axis_y, range, offset_y);
-        return {x, -y};
-    }
-
-    Input::AnalogProperties GetAnalogProperties() const override {
-        return {deadzone, range, 0.5f};
-    }
-
-    bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
-        const auto [x, y] = GetStatus();
-        const float directional_deadzone = 0.5f;
-        switch (direction) {
-        case Input::AnalogDirection::RIGHT:
-            return x > directional_deadzone;
-        case Input::AnalogDirection::LEFT:
-            return x < -directional_deadzone;
-        case Input::AnalogDirection::UP:
-            return y > directional_deadzone;
-        case Input::AnalogDirection::DOWN:
-            return y < -directional_deadzone;
-        }
-        return false;
-    }
-
-private:
-    std::shared_ptr<SDLJoystick> joystick;
-    const int axis_x;
-    const int axis_y;
-    const bool invert_x;
-    const bool invert_y;
-    const float deadzone;
-    const float range;
-    const float offset_x;
-    const float offset_y;
-};
-
-class SDLVibration final : public Input::VibrationDevice {
-public:
-    explicit SDLVibration(std::shared_ptr<SDLJoystick> joystick_)
-        : joystick(std::move(joystick_)) {}
-
-    u8 GetStatus() const override {
-        joystick->RumblePlay(1, 1);
-        return joystick->RumblePlay(0, 0);
-    }
-
-    bool SetRumblePlay(f32 amp_low, [[maybe_unused]] f32 freq_low, f32 amp_high,
-                       [[maybe_unused]] f32 freq_high) const override {
-        const auto process_amplitude = [](f32 amplitude) {
-            return static_cast<u16>((amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF);
-        };
-
-        const auto processed_amp_low = process_amplitude(amp_low);
-        const auto processed_amp_high = process_amplitude(amp_high);
-
-        return joystick->RumblePlay(processed_amp_low, processed_amp_high);
-    }
-
-private:
-    std::shared_ptr<SDLJoystick> joystick;
-};
-
-class SDLMotion final : public Input::MotionDevice {
-public:
-    explicit SDLMotion(std::shared_ptr<SDLJoystick> joystick_) : joystick(std::move(joystick_)) {}
-
-    Input::MotionStatus GetStatus() const override {
-        return joystick->GetMotion().GetMotion();
-    }
-
-private:
-    std::shared_ptr<SDLJoystick> joystick;
-};
-
-class SDLDirectionMotion final : public Input::MotionDevice {
-public:
-    explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
-        : joystick(std::move(joystick_)), hat(hat_), direction(direction_) {}
-
-    Input::MotionStatus GetStatus() const override {
-        if (joystick->GetHatDirection(hat, direction)) {
-            return joystick->GetMotion().GetRandomMotion(2, 6);
-        }
-        return joystick->GetMotion().GetRandomMotion(0, 0);
-    }
-
-private:
-    std::shared_ptr<SDLJoystick> joystick;
-    int hat;
-    Uint8 direction;
-};
-
-class SDLAxisMotion final : public Input::MotionDevice {
-public:
-    explicit SDLAxisMotion(std::shared_ptr<SDLJoystick> joystick_, int axis_, float threshold_,
-                           bool trigger_if_greater_)
-        : joystick(std::move(joystick_)), axis(axis_), threshold(threshold_),
-          trigger_if_greater(trigger_if_greater_) {}
-
-    Input::MotionStatus GetStatus() const override {
-        const float axis_value = joystick->GetAxis(axis, 1.0f, 0.0f);
-        bool trigger = axis_value < threshold;
-        if (trigger_if_greater) {
-            trigger = axis_value > threshold;
-        }
-
-        if (trigger) {
-            return joystick->GetMotion().GetRandomMotion(2, 6);
-        }
-        return joystick->GetMotion().GetRandomMotion(0, 0);
-    }
-
-private:
-    std::shared_ptr<SDLJoystick> joystick;
-    int axis;
-    float threshold;
-    bool trigger_if_greater;
-};
-
-class SDLButtonMotion final : public Input::MotionDevice {
-public:
-    explicit SDLButtonMotion(std::shared_ptr<SDLJoystick> joystick_, int button_)
-        : joystick(std::move(joystick_)), button(button_) {}
-
-    Input::MotionStatus GetStatus() const override {
-        if (joystick->GetButton(button)) {
-            return joystick->GetMotion().GetRandomMotion(2, 6);
-        }
-        return joystick->GetMotion().GetRandomMotion(0, 0);
-    }
-
-private:
-    std::shared_ptr<SDLJoystick> joystick;
-    int button;
-};
-
-/// A button device factory that creates button devices from SDL joystick
-class SDLButtonFactory final : public Input::Factory<Input::ButtonDevice> {
-public:
-    explicit SDLButtonFactory(SDLState& state_) : state(state_) {}
-
-    /**
-     * Creates a button device from a joystick button
-     * @param params contains parameters for creating the device:
-     *     - "guid": the guid of the joystick to bind
-     *     - "port": the nth joystick of the same type to bind
-     *     - "button"(optional): the index of the button to bind
-     *     - "hat"(optional): the index of the hat to bind as direction buttons
-     *     - "axis"(optional): the index of the axis to bind
-     *     - "direction"(only used for hat): the direction name of the hat to bind. Can be "up",
-     *         "down", "left" or "right"
-     *     - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is
-     *         triggered if the axis value crosses
-     *     - "direction"(only used for axis): "+" means the button is triggered when the axis
-     * value is greater than the threshold; "-" means the button is triggered when the axis
-     * value is smaller than the threshold
-     */
-    std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override {
-        const std::string guid = params.Get("guid", "0");
-        const int port = params.Get("port", 0);
-        const auto toggle = params.Get("toggle", false);
-
-        auto joystick = state.GetSDLJoystickByGUID(guid, port);
-
-        if (params.Has("hat")) {
-            const int hat = params.Get("hat", 0);
-            const std::string direction_name = params.Get("direction", "");
-            Uint8 direction;
-            if (direction_name == "up") {
-                direction = SDL_HAT_UP;
-            } else if (direction_name == "down") {
-                direction = SDL_HAT_DOWN;
-            } else if (direction_name == "left") {
-                direction = SDL_HAT_LEFT;
-            } else if (direction_name == "right") {
-                direction = SDL_HAT_RIGHT;
-            } else {
-                direction = 0;
-            }
-            // This is necessary so accessing GetHat with hat won't crash
-            joystick->SetHat(hat, SDL_HAT_CENTERED);
-            return std::make_unique<SDLDirectionButton>(joystick, hat, direction);
-        }
-
-        if (params.Has("axis")) {
-            const int axis = params.Get("axis", 0);
-            // Convert range from (0.0, 1.0) to (-1.0, 1.0)
-            const float threshold = (params.Get("threshold", 0.5f) - 0.5f) * 2.0f;
-            const std::string direction_name = params.Get("direction", "");
-            bool trigger_if_greater;
-            if (direction_name == "+") {
-                trigger_if_greater = true;
-            } else if (direction_name == "-") {
-                trigger_if_greater = false;
-            } else {
-                trigger_if_greater = true;
-                LOG_ERROR(Input, "Unknown direction {}", direction_name);
-            }
-            // This is necessary so accessing GetAxis with axis won't crash
-            joystick->PreSetAxis(axis);
-            return std::make_unique<SDLAxisButton>(joystick, axis, threshold, trigger_if_greater);
-        }
-
-        const int button = params.Get("button", 0);
-        // This is necessary so accessing GetButton with button won't crash
-        joystick->PreSetButton(button);
-        return std::make_unique<SDLButton>(joystick, button, toggle);
-    }
-
-private:
-    SDLState& state;
-};
-
-/// An analog device factory that creates analog devices from SDL joystick
-class SDLAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
-public:
-    explicit SDLAnalogFactory(SDLState& state_) : state(state_) {}
-    /**
-     * Creates an analog device from joystick axes
-     * @param params contains parameters for creating the device:
-     *     - "guid": the guid of the joystick to bind
-     *     - "port": the nth joystick of the same type
-     *     - "axis_x": the index of the axis to be bind as x-axis
-     *     - "axis_y": the index of the axis to be bind as y-axis
-     */
-    std::unique_ptr<Input::AnalogDevice> Create(const Common::ParamPackage& params) override {
-        const std::string guid = params.Get("guid", "0");
-        const int port = params.Get("port", 0);
-        const int axis_x = params.Get("axis_x", 0);
-        const int axis_y = params.Get("axis_y", 1);
-        const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
-        const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
-        const std::string invert_x_value = params.Get("invert_x", "+");
-        const std::string invert_y_value = params.Get("invert_y", "+");
-        const bool invert_x = invert_x_value == "-";
-        const bool invert_y = invert_y_value == "-";
-        const float offset_x = std::clamp(params.Get("offset_x", 0.0f), -0.99f, 0.99f);
-        const float offset_y = std::clamp(params.Get("offset_y", 0.0f), -0.99f, 0.99f);
-        auto joystick = state.GetSDLJoystickByGUID(guid, port);
-
-        // This is necessary so accessing GetAxis with axis_x and axis_y won't crash
-        joystick->PreSetAxis(axis_x);
-        joystick->PreSetAxis(axis_y);
-        return std::make_unique<SDLAnalog>(joystick, axis_x, axis_y, invert_x, invert_y, deadzone,
-                                           range, offset_x, offset_y);
-    }
-
-private:
-    SDLState& state;
-};
-
-/// An vibration device factory that creates vibration devices from SDL joystick
-class SDLVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
-public:
-    explicit SDLVibrationFactory(SDLState& state_) : state(state_) {}
-    /**
-     * Creates a vibration device from a joystick
-     * @param params contains parameters for creating the device:
-     *     - "guid": the guid of the joystick to bind
-     *     - "port": the nth joystick of the same type
-     */
-    std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override {
-        const std::string guid = params.Get("guid", "0");
-        const int port = params.Get("port", 0);
-        return std::make_unique<SDLVibration>(state.GetSDLJoystickByGUID(guid, port));
-    }
-
-private:
-    SDLState& state;
-};
-
-/// A motion device factory that creates motion devices from SDL joystick
-class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> {
-public:
-    explicit SDLMotionFactory(SDLState& state_) : state(state_) {}
-    /**
-     * Creates motion device from joystick axes
-     * @param params contains parameters for creating the device:
-     *     - "guid": the guid of the joystick to bind
-     *     - "port": the nth joystick of the same type
-     */
-    std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override {
-        const std::string guid = params.Get("guid", "0");
-        const int port = params.Get("port", 0);
-
-        auto joystick = state.GetSDLJoystickByGUID(guid, port);
-
-        if (params.Has("motion")) {
-            return std::make_unique<SDLMotion>(joystick);
-        }
-
-        if (params.Has("hat")) {
-            const int hat = params.Get("hat", 0);
-            const std::string direction_name = params.Get("direction", "");
-            Uint8 direction;
-            if (direction_name == "up") {
-                direction = SDL_HAT_UP;
-            } else if (direction_name == "down") {
-                direction = SDL_HAT_DOWN;
-            } else if (direction_name == "left") {
-                direction = SDL_HAT_LEFT;
-            } else if (direction_name == "right") {
-                direction = SDL_HAT_RIGHT;
-            } else {
-                direction = 0;
-            }
-            // This is necessary so accessing GetHat with hat won't crash
-            joystick->SetHat(hat, SDL_HAT_CENTERED);
-            return std::make_unique<SDLDirectionMotion>(joystick, hat, direction);
-        }
-
-        if (params.Has("axis")) {
-            const int axis = params.Get("axis", 0);
-            const float threshold = params.Get("threshold", 0.5f);
-            const std::string direction_name = params.Get("direction", "");
-            bool trigger_if_greater;
-            if (direction_name == "+") {
-                trigger_if_greater = true;
-            } else if (direction_name == "-") {
-                trigger_if_greater = false;
-            } else {
-                trigger_if_greater = true;
-                LOG_ERROR(Input, "Unknown direction {}", direction_name);
-            }
-            // This is necessary so accessing GetAxis with axis won't crash
-            joystick->PreSetAxis(axis);
-            return std::make_unique<SDLAxisMotion>(joystick, axis, threshold, trigger_if_greater);
-        }
-
-        const int button = params.Get("button", 0);
-        // This is necessary so accessing GetButton with button won't crash
-        joystick->PreSetButton(button);
-        return std::make_unique<SDLButtonMotion>(joystick, button);
-    }
-
-private:
-    SDLState& state;
-};
-
-SDLState::SDLState() {
-    using namespace Input;
-    button_factory = std::make_shared<SDLButtonFactory>(*this);
-    analog_factory = std::make_shared<SDLAnalogFactory>(*this);
-    vibration_factory = std::make_shared<SDLVibrationFactory>(*this);
-    motion_factory = std::make_shared<SDLMotionFactory>(*this);
-    RegisterFactory<ButtonDevice>("sdl", button_factory);
-    RegisterFactory<AnalogDevice>("sdl", analog_factory);
-    RegisterFactory<VibrationDevice>("sdl", vibration_factory);
-    RegisterFactory<MotionDevice>("sdl", motion_factory);
-
-    if (!Settings::values.enable_raw_input) {
-        // Disable raw input. When enabled this setting causes SDL to die when a web applet opens
-        SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0");
-    }
-
-    // Enable HIDAPI rumble. This prevents SDL from disabling motion on PS4 and PS5 controllers
-    SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
-    SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
-
-    // Tell SDL2 to use the hidapi driver. This will allow joycons to be detected as a
-    // GameController and not a generic one
-    SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1");
-
-    // Turn off Pro controller home led
-    SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED, "0");
-
-    // If the frontend is going to manage the event loop, then we don't start one here
-    start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0;
-    if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) {
-        LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError());
-        return;
-    }
-    has_gamecontroller = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0;
-    if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) {
-        LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError());
-    }
-
-    SDL_AddEventWatch(&SDLEventWatcher, this);
-
-    initialized = true;
-    if (start_thread) {
-        poll_thread = std::thread([this] {
-            using namespace std::chrono_literals;
-            while (initialized) {
-                SDL_PumpEvents();
-                std::this_thread::sleep_for(1ms);
-            }
-        });
-    }
-    // Because the events for joystick connection happens before we have our event watcher added, we
-    // can just open all the joysticks right here
-    for (int i = 0; i < SDL_NumJoysticks(); ++i) {
-        InitJoystick(i);
-    }
-}
-
-SDLState::~SDLState() {
-    using namespace Input;
-    UnregisterFactory<ButtonDevice>("sdl");
-    UnregisterFactory<AnalogDevice>("sdl");
-    UnregisterFactory<VibrationDevice>("sdl");
-    UnregisterFactory<MotionDevice>("sdl");
-
-    CloseJoysticks();
-    SDL_DelEventWatch(&SDLEventWatcher, this);
-
-    initialized = false;
-    if (start_thread) {
-        poll_thread.join();
-        SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
-    }
-}
-
-std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
-    std::scoped_lock lock(joystick_map_mutex);
-    std::vector<Common::ParamPackage> devices;
-    std::unordered_map<int, std::shared_ptr<SDLJoystick>> joycon_pairs;
-    for (const auto& [key, value] : joystick_map) {
-        for (const auto& joystick : value) {
-            if (!joystick->GetSDLJoystick()) {
-                continue;
-            }
-            std::string name =
-                fmt::format("{} {}", joystick->GetControllerName(), joystick->GetPort());
-            devices.emplace_back(Common::ParamPackage{
-                {"class", "sdl"},
-                {"display", std::move(name)},
-                {"guid", joystick->GetGUID()},
-                {"port", std::to_string(joystick->GetPort())},
-            });
-            if (joystick->IsJoyconLeft()) {
-                joycon_pairs.insert_or_assign(joystick->GetPort(), joystick);
-            }
-        }
-    }
-
-    // Add dual controllers
-    for (const auto& [key, value] : joystick_map) {
-        for (const auto& joystick : value) {
-            if (joystick->IsJoyconRight()) {
-                if (!joycon_pairs.contains(joystick->GetPort())) {
-                    continue;
-                }
-                const auto joystick2 = joycon_pairs.at(joystick->GetPort());
-
-                std::string name =
-                    fmt::format("{} {}", "Nintendo Dual Joy-Con", joystick->GetPort());
-                devices.emplace_back(Common::ParamPackage{
-                    {"class", "sdl"},
-                    {"display", std::move(name)},
-                    {"guid", joystick->GetGUID()},
-                    {"guid2", joystick2->GetGUID()},
-                    {"port", std::to_string(joystick->GetPort())},
-                });
-            }
-        }
-    }
-    return devices;
-}
-
-namespace {
-Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis,
-                                                      float value = 0.1f) {
-    Common::ParamPackage params({{"engine", "sdl"}});
-    params.Set("port", port);
-    params.Set("guid", std::move(guid));
-    params.Set("axis", axis);
-    params.Set("threshold", "0.5");
-    if (value > 0) {
-        params.Set("direction", "+");
-    } else {
-        params.Set("direction", "-");
-    }
-    return params;
-}
-
-Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, s32 button) {
-    Common::ParamPackage params({{"engine", "sdl"}});
-    params.Set("port", port);
-    params.Set("guid", std::move(guid));
-    params.Set("button", button);
-    params.Set("toggle", false);
-    return params;
-}
-
-Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s32 hat, s32 value) {
-    Common::ParamPackage params({{"engine", "sdl"}});
-
-    params.Set("port", port);
-    params.Set("guid", std::move(guid));
-    params.Set("hat", hat);
-    switch (value) {
-    case SDL_HAT_UP:
-        params.Set("direction", "up");
-        break;
-    case SDL_HAT_DOWN:
-        params.Set("direction", "down");
-        break;
-    case SDL_HAT_LEFT:
-        params.Set("direction", "left");
-        break;
-    case SDL_HAT_RIGHT:
-        params.Set("direction", "right");
-        break;
-    default:
-        return {};
-    }
-    return params;
-}
-
-Common::ParamPackage BuildMotionParam(int port, std::string guid) {
-    Common::ParamPackage params({{"engine", "sdl"}, {"motion", "0"}});
-    params.Set("port", port);
-    params.Set("guid", std::move(guid));
-    return params;
-}
-
-Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) {
-    switch (event.type) {
-    case SDL_JOYAXISMOTION: {
-        if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which)) {
-            return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
-                                                    static_cast<s32>(event.jaxis.axis),
-                                                    event.jaxis.value);
-        }
-        break;
-    }
-    case SDL_JOYBUTTONUP: {
-        if (const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which)) {
-            return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
-                                                    static_cast<s32>(event.jbutton.button));
-        }
-        break;
-    }
-    case SDL_JOYHATMOTION: {
-        if (const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which)) {
-            return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
-                                                 static_cast<s32>(event.jhat.hat),
-                                                 static_cast<s32>(event.jhat.value));
-        }
-        break;
-    }
-    }
-    return {};
-}
-
-Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Event& event) {
-    switch (event.type) {
-    case SDL_JOYAXISMOTION: {
-        if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which)) {
-            return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
-                                                    static_cast<s32>(event.jaxis.axis),
-                                                    event.jaxis.value);
-        }
-        break;
-    }
-    case SDL_JOYBUTTONUP: {
-        if (const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which)) {
-            return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
-                                                    static_cast<s32>(event.jbutton.button));
-        }
-        break;
-    }
-    case SDL_JOYHATMOTION: {
-        if (const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which)) {
-            return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
-                                                 static_cast<s32>(event.jhat.hat),
-                                                 static_cast<s32>(event.jhat.value));
-        }
-        break;
-    }
-    case SDL_CONTROLLERSENSORUPDATE: {
-        bool is_motion_shaking = false;
-        constexpr float gyro_threshold = 5.0f;
-        constexpr float accel_threshold = 11.0f;
-        if (event.csensor.sensor == SDL_SENSOR_ACCEL) {
-            const Common::Vec3f acceleration = {-event.csensor.data[0], event.csensor.data[2],
-                                                -event.csensor.data[1]};
-            if (acceleration.Length() > accel_threshold) {
-                is_motion_shaking = true;
-            }
-        }
-
-        if (event.csensor.sensor == SDL_SENSOR_GYRO) {
-            const Common::Vec3f gyroscope = {event.csensor.data[0], -event.csensor.data[2],
-                                             event.csensor.data[1]};
-            if (gyroscope.Length() > gyro_threshold) {
-                is_motion_shaking = true;
-            }
-        }
-
-        if (!is_motion_shaking) {
-            break;
-        }
-
-        if (const auto joystick = state.GetSDLJoystickBySDLID(event.csensor.which)) {
-            return BuildMotionParam(joystick->GetPort(), joystick->GetGUID());
-        }
-        break;
-    }
-    }
-    return {};
-}
-
-Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid,
-                                                 const SDL_GameControllerButtonBind& binding) {
-    switch (binding.bindType) {
-    case SDL_CONTROLLER_BINDTYPE_NONE:
-        break;
-    case SDL_CONTROLLER_BINDTYPE_AXIS:
-        return BuildAnalogParamPackageForButton(port, guid, binding.value.axis);
-    case SDL_CONTROLLER_BINDTYPE_BUTTON:
-        return BuildButtonParamPackageForButton(port, guid, binding.value.button);
-    case SDL_CONTROLLER_BINDTYPE_HAT:
-        return BuildHatParamPackageForButton(port, guid, binding.value.hat.hat,
-                                             binding.value.hat.hat_mask);
-    }
-    return {};
-}
-
-Common::ParamPackage BuildParamPackageForAnalog(int port, const std::string& guid, int axis_x,
-                                                int axis_y, float offset_x, float offset_y) {
-    Common::ParamPackage params;
-    params.Set("engine", "sdl");
-    params.Set("port", port);
-    params.Set("guid", guid);
-    params.Set("axis_x", axis_x);
-    params.Set("axis_y", axis_y);
-    params.Set("offset_x", offset_x);
-    params.Set("offset_y", offset_y);
-    params.Set("invert_x", "+");
-    params.Set("invert_y", "+");
-    return params;
-}
-} // Anonymous namespace
-
-ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& params) {
-    if (!params.Has("guid") || !params.Has("port")) {
-        return {};
-    }
-    const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
-
-    auto* controller = joystick->GetSDLGameController();
-    if (controller == nullptr) {
-        return {};
-    }
-
-    // This list is missing ZL/ZR since those are not considered buttons in SDL GameController.
-    // We will add those afterwards
-    // This list also excludes Screenshot since theres not really a mapping for that
-    ButtonBindings switch_to_sdl_button;
-
-    if (SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) {
-        switch_to_sdl_button = GetNintendoButtonBinding(joystick);
-    } else {
-        switch_to_sdl_button = GetDefaultButtonBinding();
-    }
-
-    // Add the missing bindings for ZL/ZR
-    static constexpr ZButtonBindings switch_to_sdl_axis{{
-        {Settings::NativeButton::ZL, SDL_CONTROLLER_AXIS_TRIGGERLEFT},
-        {Settings::NativeButton::ZR, SDL_CONTROLLER_AXIS_TRIGGERRIGHT},
-    }};
-
-    // Parameters contain two joysticks return dual
-    if (params.Has("guid2")) {
-        const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0));
-
-        if (joystick2->GetSDLGameController() != nullptr) {
-            return GetDualControllerMapping(joystick, joystick2, switch_to_sdl_button,
-                                            switch_to_sdl_axis);
-        }
-    }
-
-    return GetSingleControllerMapping(joystick, switch_to_sdl_button, switch_to_sdl_axis);
-}
-
-ButtonBindings SDLState::GetDefaultButtonBinding() const {
-    return {
-        std::pair{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B},
-        {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A},
-        {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y},
-        {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X},
-        {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK},
-        {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
-        {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
-        {Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
-        {Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START},
-        {Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK},
-        {Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT},
-        {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP},
-        {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
-        {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN},
-        {Settings::NativeButton::SL, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
-        {Settings::NativeButton::SR, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
-        {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE},
-    };
-}
-
-ButtonBindings SDLState::GetNintendoButtonBinding(
-    const std::shared_ptr<SDLJoystick>& joystick) const {
-    // Default SL/SR mapping for pro controllers
-    auto sl_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
-    auto sr_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
-
-    if (joystick->IsJoyconLeft()) {
-        sl_button = SDL_CONTROLLER_BUTTON_PADDLE2;
-        sr_button = SDL_CONTROLLER_BUTTON_PADDLE4;
-    }
-    if (joystick->IsJoyconRight()) {
-        sl_button = SDL_CONTROLLER_BUTTON_PADDLE3;
-        sr_button = SDL_CONTROLLER_BUTTON_PADDLE1;
-    }
-
-    return {
-        std::pair{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_A},
-        {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_B},
-        {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_X},
-        {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_Y},
-        {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK},
-        {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
-        {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
-        {Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
-        {Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START},
-        {Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK},
-        {Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT},
-        {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP},
-        {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
-        {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN},
-        {Settings::NativeButton::SL, sl_button},
-        {Settings::NativeButton::SR, sr_button},
-        {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE},
-    };
-}
-
-ButtonMapping SDLState::GetSingleControllerMapping(
-    const std::shared_ptr<SDLJoystick>& joystick, const ButtonBindings& switch_to_sdl_button,
-    const ZButtonBindings& switch_to_sdl_axis) const {
-    ButtonMapping mapping;
-    mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size());
-    auto* controller = joystick->GetSDLGameController();
-
-    for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) {
-        const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button);
-        mapping.insert_or_assign(
-            switch_button,
-            BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
-    }
-    for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) {
-        const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis);
-        mapping.insert_or_assign(
-            switch_button,
-            BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
-    }
-
-    return mapping;
-}
-
-ButtonMapping SDLState::GetDualControllerMapping(const std::shared_ptr<SDLJoystick>& joystick,
-                                                 const std::shared_ptr<SDLJoystick>& joystick2,
-                                                 const ButtonBindings& switch_to_sdl_button,
-                                                 const ZButtonBindings& switch_to_sdl_axis) const {
-    ButtonMapping mapping;
-    mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size());
-    auto* controller = joystick->GetSDLGameController();
-    auto* controller2 = joystick2->GetSDLGameController();
-
-    for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) {
-        if (IsButtonOnLeftSide(switch_button)) {
-            const auto& binding = SDL_GameControllerGetBindForButton(controller2, sdl_button);
-            mapping.insert_or_assign(
-                switch_button,
-                BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding));
-            continue;
-        }
-        const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button);
-        mapping.insert_or_assign(
-            switch_button,
-            BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
-    }
-    for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) {
-        if (IsButtonOnLeftSide(switch_button)) {
-            const auto& binding = SDL_GameControllerGetBindForAxis(controller2, sdl_axis);
-            mapping.insert_or_assign(
-                switch_button,
-                BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding));
-            continue;
-        }
-        const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis);
-        mapping.insert_or_assign(
-            switch_button,
-            BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
-    }
-
-    return mapping;
-}
-
-bool SDLState::IsButtonOnLeftSide(Settings::NativeButton::Values button) const {
-    switch (button) {
-    case Settings::NativeButton::DDown:
-    case Settings::NativeButton::DLeft:
-    case Settings::NativeButton::DRight:
-    case Settings::NativeButton::DUp:
-    case Settings::NativeButton::L:
-    case Settings::NativeButton::LStick:
-    case Settings::NativeButton::Minus:
-    case Settings::NativeButton::Screenshot:
-    case Settings::NativeButton::ZL:
-        return true;
-    default:
-        return false;
-    }
-}
-
-AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& params) {
-    if (!params.Has("guid") || !params.Has("port")) {
-        return {};
-    }
-    const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
-    const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0));
-    auto* controller = joystick->GetSDLGameController();
-    if (controller == nullptr) {
-        return {};
-    }
-
-    AnalogMapping mapping = {};
-    const auto& binding_left_x =
-        SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX);
-    const auto& binding_left_y =
-        SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY);
-    if (params.Has("guid2")) {
-        joystick2->PreSetAxis(binding_left_x.value.axis);
-        joystick2->PreSetAxis(binding_left_y.value.axis);
-        const auto left_offset_x = -joystick2->GetAxis(binding_left_x.value.axis, 1.0f, 0);
-        const auto left_offset_y = -joystick2->GetAxis(binding_left_y.value.axis, 1.0f, 0);
-        mapping.insert_or_assign(
-            Settings::NativeAnalog::LStick,
-            BuildParamPackageForAnalog(joystick2->GetPort(), joystick2->GetGUID(),
-                                       binding_left_x.value.axis, binding_left_y.value.axis,
-                                       left_offset_x, left_offset_y));
-    } else {
-        joystick->PreSetAxis(binding_left_x.value.axis);
-        joystick->PreSetAxis(binding_left_y.value.axis);
-        const auto left_offset_x = -joystick->GetAxis(binding_left_x.value.axis, 1.0f, 0);
-        const auto left_offset_y = -joystick->GetAxis(binding_left_y.value.axis, 1.0f, 0);
-        mapping.insert_or_assign(
-            Settings::NativeAnalog::LStick,
-            BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(),
-                                       binding_left_x.value.axis, binding_left_y.value.axis,
-                                       left_offset_x, left_offset_y));
-    }
-    const auto& binding_right_x =
-        SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX);
-    const auto& binding_right_y =
-        SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY);
-    joystick->PreSetAxis(binding_right_x.value.axis);
-    joystick->PreSetAxis(binding_right_y.value.axis);
-    const auto right_offset_x = -joystick->GetAxis(binding_right_x.value.axis, 1.0f, 0);
-    const auto right_offset_y = -joystick->GetAxis(binding_right_y.value.axis, 1.0f, 0);
-    mapping.insert_or_assign(Settings::NativeAnalog::RStick,
-                             BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(),
-                                                        binding_right_x.value.axis,
-                                                        binding_right_y.value.axis, right_offset_x,
-                                                        right_offset_y));
-    return mapping;
-}
-
-MotionMapping SDLState::GetMotionMappingForDevice(const Common::ParamPackage& params) {
-    if (!params.Has("guid") || !params.Has("port")) {
-        return {};
-    }
-    const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
-    const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0));
-    auto* controller = joystick->GetSDLGameController();
-    if (controller == nullptr) {
-        return {};
-    }
-
-    MotionMapping mapping = {};
-    joystick->EnableMotion();
-
-    if (joystick->HasGyro() || joystick->HasAccel()) {
-        mapping.insert_or_assign(Settings::NativeMotion::MotionRight,
-                                 BuildMotionParam(joystick->GetPort(), joystick->GetGUID()));
-    }
-    if (params.Has("guid2")) {
-        joystick2->EnableMotion();
-        if (joystick2->HasGyro() || joystick2->HasAccel()) {
-            mapping.insert_or_assign(Settings::NativeMotion::MotionLeft,
-                                     BuildMotionParam(joystick2->GetPort(), joystick2->GetGUID()));
-        }
-    } else {
-        if (joystick->HasGyro() || joystick->HasAccel()) {
-            mapping.insert_or_assign(Settings::NativeMotion::MotionLeft,
-                                     BuildMotionParam(joystick->GetPort(), joystick->GetGUID()));
-        }
-    }
-
-    return mapping;
-}
-namespace Polling {
-class SDLPoller : public InputCommon::Polling::DevicePoller {
-public:
-    explicit SDLPoller(SDLState& state_) : state(state_) {}
-
-    void Start([[maybe_unused]] const std::string& device_id) override {
-        state.event_queue.Clear();
-        state.polling = true;
-    }
-
-    void Stop() override {
-        state.polling = false;
-    }
-
-protected:
-    SDLState& state;
-};
-
-class SDLButtonPoller final : public SDLPoller {
-public:
-    explicit SDLButtonPoller(SDLState& state_) : SDLPoller(state_) {}
-
-    Common::ParamPackage GetNextInput() override {
-        SDL_Event event;
-        while (state.event_queue.Pop(event)) {
-            const auto package = FromEvent(event);
-            if (package) {
-                return *package;
-            }
-        }
-        return {};
-    }
-    [[nodiscard]] std::optional<Common::ParamPackage> FromEvent(SDL_Event& event) {
-        switch (event.type) {
-        case SDL_JOYAXISMOTION:
-            if (!axis_memory.count(event.jaxis.which) ||
-                !axis_memory[event.jaxis.which].count(event.jaxis.axis)) {
-                axis_memory[event.jaxis.which][event.jaxis.axis] = event.jaxis.value;
-                axis_event_count[event.jaxis.which][event.jaxis.axis] = 1;
-                break;
-            } else {
-                axis_event_count[event.jaxis.which][event.jaxis.axis]++;
-                // The joystick and axis exist in our map if we take this branch, so no checks
-                // needed
-                if (std::abs(
-                        (event.jaxis.value - axis_memory[event.jaxis.which][event.jaxis.axis]) /
-                        32767.0) < 0.5) {
-                    break;
-                } else {
-                    if (axis_event_count[event.jaxis.which][event.jaxis.axis] == 2 &&
-                        IsAxisAtPole(event.jaxis.value) &&
-                        IsAxisAtPole(axis_memory[event.jaxis.which][event.jaxis.axis])) {
-                        // If we have exactly two events and both are near a pole, this is
-                        // likely a digital input masquerading as an analog axis; Instead of
-                        // trying to look at the direction the axis travelled, assume the first
-                        // event was press and the second was release; This should handle most
-                        // digital axes while deferring to the direction of travel for analog
-                        // axes
-                        event.jaxis.value = static_cast<Sint16>(
-                            std::copysign(32767, axis_memory[event.jaxis.which][event.jaxis.axis]));
-                    } else {
-                        // There are more than two events, so this is likely a true analog axis,
-                        // check the direction it travelled
-                        event.jaxis.value = static_cast<Sint16>(std::copysign(
-                            32767,
-                            event.jaxis.value - axis_memory[event.jaxis.which][event.jaxis.axis]));
-                    }
-                    axis_memory.clear();
-                    axis_event_count.clear();
-                }
-            }
-            [[fallthrough]];
-        case SDL_JOYBUTTONUP:
-        case SDL_JOYHATMOTION:
-            return {SDLEventToButtonParamPackage(state, event)};
-        }
-        return std::nullopt;
-    }
-
-private:
-    // Determine whether an axis value is close to an extreme or center
-    // Some controllers have a digital D-Pad as a pair of analog sticks, with 3 possible values per
-    // axis, which is why the center must be considered a pole
-    bool IsAxisAtPole(int16_t value) const {
-        return std::abs(value) >= 32767 || std::abs(value) < 327;
-    }
-    std::unordered_map<SDL_JoystickID, std::unordered_map<uint8_t, int16_t>> axis_memory;
-    std::unordered_map<SDL_JoystickID, std::unordered_map<uint8_t, uint32_t>> axis_event_count;
-};
-
-class SDLMotionPoller final : public SDLPoller {
-public:
-    explicit SDLMotionPoller(SDLState& state_) : SDLPoller(state_) {}
-
-    Common::ParamPackage GetNextInput() override {
-        SDL_Event event;
-        while (state.event_queue.Pop(event)) {
-            const auto package = FromEvent(event);
-            if (package) {
-                return *package;
-            }
-        }
-        return {};
-    }
-    [[nodiscard]] std::optional<Common::ParamPackage> FromEvent(const SDL_Event& event) const {
-        switch (event.type) {
-        case SDL_JOYAXISMOTION:
-            if (std::abs(event.jaxis.value / 32767.0) < 0.5) {
-                break;
-            }
-            [[fallthrough]];
-        case SDL_JOYBUTTONUP:
-        case SDL_JOYHATMOTION:
-        case SDL_CONTROLLERSENSORUPDATE:
-            return {SDLEventToMotionParamPackage(state, event)};
-        }
-        return std::nullopt;
-    }
-};
-
-/**
- * Attempts to match the press to a controller joy axis (left/right stick) and if a match
- * isn't found, checks if the event matches anything from SDLButtonPoller and uses that
- * instead
- */
-class SDLAnalogPreferredPoller final : public SDLPoller {
-public:
-    explicit SDLAnalogPreferredPoller(SDLState& state_)
-        : SDLPoller(state_), button_poller(state_) {}
-
-    void Start(const std::string& device_id) override {
-        SDLPoller::Start(device_id);
-        // Reset stored axes
-        first_axis = -1;
-    }
-
-    Common::ParamPackage GetNextInput() override {
-        SDL_Event event;
-        while (state.event_queue.Pop(event)) {
-            if (event.type != SDL_JOYAXISMOTION) {
-                // Check for a button press
-                auto button_press = button_poller.FromEvent(event);
-                if (button_press) {
-                    return *button_press;
-                }
-                continue;
-            }
-            const auto axis = event.jaxis.axis;
-
-            // Filter out axis events that are below a threshold
-            if (std::abs(event.jaxis.value / 32767.0) < 0.5) {
-                continue;
-            }
-
-            // Filter out axis events that are the same
-            if (first_axis == axis) {
-                continue;
-            }
-
-            // In order to return a complete analog param, we need inputs for both axes.
-            // If the first axis isn't set we set the value then wait till next event
-            if (first_axis == -1) {
-                first_axis = axis;
-                continue;
-            }
-
-            if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which)) {
-                // Set offset to zero since the joystick is not on center
-                auto params = BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(),
-                                                         first_axis, axis, 0, 0);
-                first_axis = -1;
-                return params;
-            }
-        }
-        return {};
-    }
-
-private:
-    int first_axis = -1;
-    SDLButtonPoller button_poller;
-};
-} // namespace Polling
-
-SDLState::Pollers SDLState::GetPollers(InputCommon::Polling::DeviceType type) {
-    Pollers pollers;
-
-    switch (type) {
-    case InputCommon::Polling::DeviceType::AnalogPreferred:
-        pollers.emplace_back(std::make_unique<Polling::SDLAnalogPreferredPoller>(*this));
-        break;
-    case InputCommon::Polling::DeviceType::Button:
-        pollers.emplace_back(std::make_unique<Polling::SDLButtonPoller>(*this));
-        break;
-    case InputCommon::Polling::DeviceType::Motion:
-        pollers.emplace_back(std::make_unique<Polling::SDLMotionPoller>(*this));
-        break;
-    }
-
-    return pollers;
-}
-
-} // namespace InputCommon::SDL

From 6d108f0dcb5b388c3586f90426fc2c832a8bffc0 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 17:39:58 -0500
Subject: [PATCH 14/88] input_common: Remove obsolete files

---
 src/input_common/CMakeLists.txt         |   4 -
 src/input_common/motion_from_button.cpp |  34 ---
 src/input_common/motion_from_button.h   |  25 --
 src/input_common/motion_input.cpp       | 307 ------------------------
 src/input_common/motion_input.h         |  74 ------
 5 files changed, 444 deletions(-)
 delete mode 100644 src/input_common/motion_from_button.cpp
 delete mode 100644 src/input_common/motion_from_button.h
 delete mode 100644 src/input_common/motion_input.cpp
 delete mode 100644 src/input_common/motion_input.h

diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 8cdcd315b3..d4fa69a775 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -27,10 +27,6 @@ add_library(input_common STATIC
     input_poller.h
     main.cpp
     main.h
-    motion_from_button.cpp
-    motion_from_button.h
-    motion_input.cpp
-    motion_input.h
 )
 
 if (MSVC)
diff --git a/src/input_common/motion_from_button.cpp b/src/input_common/motion_from_button.cpp
deleted file mode 100644
index 29045a673f..0000000000
--- a/src/input_common/motion_from_button.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "input_common/motion_from_button.h"
-#include "input_common/motion_input.h"
-
-namespace InputCommon {
-
-class MotionKey final : public Input::MotionDevice {
-public:
-    using Button = std::unique_ptr<Input::ButtonDevice>;
-
-    explicit MotionKey(Button key_) : key(std::move(key_)) {}
-
-    Input::MotionStatus GetStatus() const override {
-
-        if (key->GetStatus()) {
-            return motion.GetRandomMotion(2, 6);
-        }
-        return motion.GetRandomMotion(0, 0);
-    }
-
-private:
-    Button key;
-    InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f};
-};
-
-std::unique_ptr<Input::MotionDevice> MotionFromButton::Create(const Common::ParamPackage& params) {
-    auto key = Input::CreateDevice<Input::ButtonDevice>(params.Serialize());
-    return std::make_unique<MotionKey>(std::move(key));
-}
-
-} // namespace InputCommon
diff --git a/src/input_common/motion_from_button.h b/src/input_common/motion_from_button.h
deleted file mode 100644
index a959046fb5..0000000000
--- a/src/input_common/motion_from_button.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/frontend/input.h"
-
-namespace InputCommon {
-
-/**
- * An motion device factory that takes a keyboard button and uses it as a random
- * motion device.
- */
-class MotionFromButton final : public Input::Factory<Input::MotionDevice> {
-public:
-    /**
-     * Creates an motion device from button devices
-     * @param params contains parameters for creating the device:
-     *     - "key": a serialized ParamPackage for creating a button device
-     */
-    std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
-};
-
-} // namespace InputCommon
diff --git a/src/input_common/motion_input.cpp b/src/input_common/motion_input.cpp
deleted file mode 100644
index 1c9d561c0b..0000000000
--- a/src/input_common/motion_input.cpp
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included
-
-#include <random>
-#include "common/math_util.h"
-#include "input_common/motion_input.h"
-
-namespace InputCommon {
-
-MotionInput::MotionInput(f32 new_kp, f32 new_ki, f32 new_kd) : kp(new_kp), ki(new_ki), kd(new_kd) {}
-
-void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
-    accel = acceleration;
-}
-
-void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
-    gyro = gyroscope - gyro_drift;
-
-    // Auto adjust drift to minimize drift
-    if (!IsMoving(0.1f)) {
-        gyro_drift = (gyro_drift * 0.9999f) + (gyroscope * 0.0001f);
-    }
-
-    if (gyro.Length2() < gyro_threshold) {
-        gyro = {};
-    } else {
-        only_accelerometer = false;
-    }
-}
-
-void MotionInput::SetQuaternion(const Common::Quaternion<f32>& quaternion) {
-    quat = quaternion;
-}
-
-void MotionInput::SetGyroDrift(const Common::Vec3f& drift) {
-    gyro_drift = drift;
-}
-
-void MotionInput::SetGyroThreshold(f32 threshold) {
-    gyro_threshold = threshold;
-}
-
-void MotionInput::EnableReset(bool reset) {
-    reset_enabled = reset;
-}
-
-void MotionInput::ResetRotations() {
-    rotations = {};
-}
-
-bool MotionInput::IsMoving(f32 sensitivity) const {
-    return gyro.Length() >= sensitivity || accel.Length() <= 0.9f || accel.Length() >= 1.1f;
-}
-
-bool MotionInput::IsCalibrated(f32 sensitivity) const {
-    return real_error.Length() < sensitivity;
-}
-
-void MotionInput::UpdateRotation(u64 elapsed_time) {
-    const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f;
-    if (sample_period > 0.1f) {
-        return;
-    }
-    rotations += gyro * sample_period;
-}
-
-void MotionInput::UpdateOrientation(u64 elapsed_time) {
-    if (!IsCalibrated(0.1f)) {
-        ResetOrientation();
-    }
-    // Short name local variable for readability
-    f32 q1 = quat.w;
-    f32 q2 = quat.xyz[0];
-    f32 q3 = quat.xyz[1];
-    f32 q4 = quat.xyz[2];
-    const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f;
-
-    // Ignore invalid elapsed time
-    if (sample_period > 0.1f) {
-        return;
-    }
-
-    const auto normal_accel = accel.Normalized();
-    auto rad_gyro = gyro * Common::PI * 2;
-    const f32 swap = rad_gyro.x;
-    rad_gyro.x = rad_gyro.y;
-    rad_gyro.y = -swap;
-    rad_gyro.z = -rad_gyro.z;
-
-    // Clear gyro values if there is no gyro present
-    if (only_accelerometer) {
-        rad_gyro.x = 0;
-        rad_gyro.y = 0;
-        rad_gyro.z = 0;
-    }
-
-    // Ignore drift correction if acceleration is not reliable
-    if (accel.Length() >= 0.75f && accel.Length() <= 1.25f) {
-        const f32 ax = -normal_accel.x;
-        const f32 ay = normal_accel.y;
-        const f32 az = -normal_accel.z;
-
-        // Estimated direction of gravity
-        const f32 vx = 2.0f * (q2 * q4 - q1 * q3);
-        const f32 vy = 2.0f * (q1 * q2 + q3 * q4);
-        const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
-
-        // Error is cross product between estimated direction and measured direction of gravity
-        const Common::Vec3f new_real_error = {
-            az * vx - ax * vz,
-            ay * vz - az * vy,
-            ax * vy - ay * vx,
-        };
-
-        derivative_error = new_real_error - real_error;
-        real_error = new_real_error;
-
-        // Prevent integral windup
-        if (ki != 0.0f && !IsCalibrated(0.05f)) {
-            integral_error += real_error;
-        } else {
-            integral_error = {};
-        }
-
-        // Apply feedback terms
-        if (!only_accelerometer) {
-            rad_gyro += kp * real_error;
-            rad_gyro += ki * integral_error;
-            rad_gyro += kd * derivative_error;
-        } else {
-            // Give more weight to accelerometer values to compensate for the lack of gyro
-            rad_gyro += 35.0f * kp * real_error;
-            rad_gyro += 10.0f * ki * integral_error;
-            rad_gyro += 10.0f * kd * derivative_error;
-
-            // Emulate gyro values for games that need them
-            gyro.x = -rad_gyro.y;
-            gyro.y = rad_gyro.x;
-            gyro.z = -rad_gyro.z;
-            UpdateRotation(elapsed_time);
-        }
-    }
-
-    const f32 gx = rad_gyro.y;
-    const f32 gy = rad_gyro.x;
-    const f32 gz = rad_gyro.z;
-
-    // Integrate rate of change of quaternion
-    const f32 pa = q2;
-    const f32 pb = q3;
-    const f32 pc = q4;
-    q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period);
-    q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period);
-    q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period);
-    q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period);
-
-    quat.w = q1;
-    quat.xyz[0] = q2;
-    quat.xyz[1] = q3;
-    quat.xyz[2] = q4;
-    quat = quat.Normalized();
-}
-
-std::array<Common::Vec3f, 3> MotionInput::GetOrientation() const {
-    const Common::Quaternion<float> quad{
-        .xyz = {-quat.xyz[1], -quat.xyz[0], -quat.w},
-        .w = -quat.xyz[2],
-    };
-    const std::array<float, 16> matrix4x4 = quad.ToMatrix();
-
-    return {Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]),
-            Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]),
-            Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10])};
-}
-
-Common::Vec3f MotionInput::GetAcceleration() const {
-    return accel;
-}
-
-Common::Vec3f MotionInput::GetGyroscope() const {
-    return gyro;
-}
-
-Common::Quaternion<f32> MotionInput::GetQuaternion() const {
-    return quat;
-}
-
-Common::Vec3f MotionInput::GetRotations() const {
-    return rotations;
-}
-
-Input::MotionStatus MotionInput::GetMotion() const {
-    const Common::Vec3f gyroscope = GetGyroscope();
-    const Common::Vec3f accelerometer = GetAcceleration();
-    const Common::Vec3f rotation = GetRotations();
-    const std::array<Common::Vec3f, 3> orientation = GetOrientation();
-    const Common::Quaternion<f32> quaternion = GetQuaternion();
-    return {accelerometer, gyroscope, rotation, orientation, quaternion};
-}
-
-Input::MotionStatus MotionInput::GetRandomMotion(int accel_magnitude, int gyro_magnitude) const {
-    std::random_device device;
-    std::mt19937 gen(device());
-    std::uniform_int_distribution<s16> distribution(-1000, 1000);
-    const Common::Vec3f gyroscope{
-        static_cast<f32>(distribution(gen)) * 0.001f,
-        static_cast<f32>(distribution(gen)) * 0.001f,
-        static_cast<f32>(distribution(gen)) * 0.001f,
-    };
-    const Common::Vec3f accelerometer{
-        static_cast<f32>(distribution(gen)) * 0.001f,
-        static_cast<f32>(distribution(gen)) * 0.001f,
-        static_cast<f32>(distribution(gen)) * 0.001f,
-    };
-    constexpr Common::Vec3f rotation;
-    constexpr std::array orientation{
-        Common::Vec3f{1.0f, 0.0f, 0.0f},
-        Common::Vec3f{0.0f, 1.0f, 0.0f},
-        Common::Vec3f{0.0f, 0.0f, 1.0f},
-    };
-    constexpr Common::Quaternion<f32> quaternion{
-        {0.0f, 0.0f, 0.0f},
-        1.0f,
-    };
-    return {accelerometer * accel_magnitude, gyroscope * gyro_magnitude, rotation, orientation,
-            quaternion};
-}
-
-void MotionInput::ResetOrientation() {
-    if (!reset_enabled || only_accelerometer) {
-        return;
-    }
-    if (!IsMoving(0.5f) && accel.z <= -0.9f) {
-        ++reset_counter;
-        if (reset_counter > 900) {
-            quat.w = 0;
-            quat.xyz[0] = 0;
-            quat.xyz[1] = 0;
-            quat.xyz[2] = -1;
-            SetOrientationFromAccelerometer();
-            integral_error = {};
-            reset_counter = 0;
-        }
-    } else {
-        reset_counter = 0;
-    }
-}
-
-void MotionInput::SetOrientationFromAccelerometer() {
-    int iterations = 0;
-    const f32 sample_period = 0.015f;
-
-    const auto normal_accel = accel.Normalized();
-
-    while (!IsCalibrated(0.01f) && ++iterations < 100) {
-        // Short name local variable for readability
-        f32 q1 = quat.w;
-        f32 q2 = quat.xyz[0];
-        f32 q3 = quat.xyz[1];
-        f32 q4 = quat.xyz[2];
-
-        Common::Vec3f rad_gyro;
-        const f32 ax = -normal_accel.x;
-        const f32 ay = normal_accel.y;
-        const f32 az = -normal_accel.z;
-
-        // Estimated direction of gravity
-        const f32 vx = 2.0f * (q2 * q4 - q1 * q3);
-        const f32 vy = 2.0f * (q1 * q2 + q3 * q4);
-        const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
-
-        // Error is cross product between estimated direction and measured direction of gravity
-        const Common::Vec3f new_real_error = {
-            az * vx - ax * vz,
-            ay * vz - az * vy,
-            ax * vy - ay * vx,
-        };
-
-        derivative_error = new_real_error - real_error;
-        real_error = new_real_error;
-
-        rad_gyro += 10.0f * kp * real_error;
-        rad_gyro += 5.0f * ki * integral_error;
-        rad_gyro += 10.0f * kd * derivative_error;
-
-        const f32 gx = rad_gyro.y;
-        const f32 gy = rad_gyro.x;
-        const f32 gz = rad_gyro.z;
-
-        // Integrate rate of change of quaternion
-        const f32 pa = q2;
-        const f32 pb = q3;
-        const f32 pc = q4;
-        q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period);
-        q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period);
-        q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period);
-        q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period);
-
-        quat.w = q1;
-        quat.xyz[0] = q2;
-        quat.xyz[1] = q3;
-        quat.xyz[2] = q4;
-        quat = quat.Normalized();
-    }
-}
-} // namespace InputCommon
diff --git a/src/input_common/motion_input.h b/src/input_common/motion_input.h
deleted file mode 100644
index efe74cf19a..0000000000
--- a/src/input_common/motion_input.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included
-
-#pragma once
-
-#include "common/common_types.h"
-#include "common/quaternion.h"
-#include "common/vector_math.h"
-#include "core/frontend/input.h"
-
-namespace InputCommon {
-
-class MotionInput {
-public:
-    explicit MotionInput(f32 new_kp, f32 new_ki, f32 new_kd);
-
-    MotionInput(const MotionInput&) = default;
-    MotionInput& operator=(const MotionInput&) = default;
-
-    MotionInput(MotionInput&&) = default;
-    MotionInput& operator=(MotionInput&&) = default;
-
-    void SetAcceleration(const Common::Vec3f& acceleration);
-    void SetGyroscope(const Common::Vec3f& gyroscope);
-    void SetQuaternion(const Common::Quaternion<f32>& quaternion);
-    void SetGyroDrift(const Common::Vec3f& drift);
-    void SetGyroThreshold(f32 threshold);
-
-    void EnableReset(bool reset);
-    void ResetRotations();
-
-    void UpdateRotation(u64 elapsed_time);
-    void UpdateOrientation(u64 elapsed_time);
-
-    [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const;
-    [[nodiscard]] Common::Vec3f GetAcceleration() const;
-    [[nodiscard]] Common::Vec3f GetGyroscope() const;
-    [[nodiscard]] Common::Vec3f GetRotations() const;
-    [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const;
-    [[nodiscard]] Input::MotionStatus GetMotion() const;
-    [[nodiscard]] Input::MotionStatus GetRandomMotion(int accel_magnitude,
-                                                      int gyro_magnitude) const;
-
-    [[nodiscard]] bool IsMoving(f32 sensitivity) const;
-    [[nodiscard]] bool IsCalibrated(f32 sensitivity) const;
-
-private:
-    void ResetOrientation();
-    void SetOrientationFromAccelerometer();
-
-    // PID constants
-    f32 kp;
-    f32 ki;
-    f32 kd;
-
-    // PID errors
-    Common::Vec3f real_error;
-    Common::Vec3f integral_error;
-    Common::Vec3f derivative_error;
-
-    Common::Quaternion<f32> quat{{0.0f, 0.0f, -1.0f}, 0.0f};
-    Common::Vec3f rotations;
-    Common::Vec3f accel;
-    Common::Vec3f gyro;
-    Common::Vec3f gyro_drift;
-
-    f32 gyro_threshold = 0.0f;
-    u32 reset_counter = 0;
-    bool reset_enabled = true;
-    bool only_accelerometer = true;
-};
-
-} // namespace InputCommon

From 29ae42f3e2c297898d88858861f7d860ce9fc2f3 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 17:43:13 -0500
Subject: [PATCH 15/88] input_common: Rewrite main and add the new drivers

---
 src/input_common/main.cpp | 292 ++++++++++++++++++++++++++++++++++++--
 src/input_common/main.h   |  89 +++++++-----
 2 files changed, 331 insertions(+), 50 deletions(-)

diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index da501b6ccb..46ca6b76c8 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -4,54 +4,265 @@
 
 #include <memory>
 #include <thread>
+#include "common/input.h"
 #include "common/param_package.h"
-#include "common/settings.h"
+#include "input_common/drivers/gc_adapter.h"
+#include "input_common/drivers/keyboard.h"
+#include "input_common/drivers/mouse.h"
+#include "input_common/drivers/tas_input.h"
+#include "input_common/drivers/touch_screen.h"
+#include "input_common/drivers/udp_client.h"
+#include "input_common/helpers/stick_from_buttons.h"
+#include "input_common/helpers/touch_from_buttons.h"
+#include "input_common/input_engine.h"
+#include "input_common/input_mapping.h"
+#include "input_common/input_poller.h"
 #include "input_common/main.h"
 #ifdef HAVE_SDL2
-#include "input_common/sdl/sdl.h"
+#include "input_common/drivers/sdl_driver.h"
 #endif
 
 namespace InputCommon {
 
 struct InputSubsystem::Impl {
     void Initialize() {
+        mapping_factory = std::make_shared<MappingFactory>();
+        MappingCallback mapping_callback{[this](MappingData data) { RegisterInput(data); }};
+
+        keyboard = std::make_shared<Keyboard>("keyboard");
+        keyboard->SetMappingCallback(mapping_callback);
+        keyboard_factory = std::make_shared<InputFactory>(keyboard);
+        Input::RegisterFactory<Input::InputDevice>(keyboard->GetEngineName(), keyboard_factory);
+
+        mouse = std::make_shared<Mouse>("mouse");
+        mouse->SetMappingCallback(mapping_callback);
+        mouse_factory = std::make_shared<InputFactory>(mouse);
+        Input::RegisterFactory<Input::InputDevice>(mouse->GetEngineName(), mouse_factory);
+
+        touch_screen = std::make_shared<TouchScreen>("touch");
+        touch_screen_factory = std::make_shared<InputFactory>(touch_screen);
+        Input::RegisterFactory<Input::InputDevice>(touch_screen->GetEngineName(),
+                                                   touch_screen_factory);
+
+        gcadapter = std::make_shared<GCAdapter>("gcpad");
+        gcadapter->SetMappingCallback(mapping_callback);
+        gcadapter_factory = std::make_shared<InputFactory>(gcadapter);
+        Input::RegisterFactory<Input::InputDevice>(gcadapter->GetEngineName(), gcadapter_factory);
+
+        udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
+        udp_client->SetMappingCallback(mapping_callback);
+        udp_client_factory = std::make_shared<InputFactory>(udp_client);
+        Input::RegisterFactory<Input::InputDevice>(udp_client->GetEngineName(), udp_client_factory);
+
+        tas_input = std::make_shared<TasInput::Tas>("tas");
+        tas_input->SetMappingCallback(mapping_callback);
+        tas_input_factory = std::make_shared<InputFactory>(tas_input);
+        Input::RegisterFactory<Input::InputDevice>(tas_input->GetEngineName(), tas_input_factory);
+
+#ifdef HAVE_SDL2
+        sdl = std::make_shared<SDLDriver>("sdl");
+        sdl->SetMappingCallback(mapping_callback);
+        sdl_factory = std::make_shared<InputFactory>(sdl);
+        Input::RegisterFactory<Input::InputDevice>(sdl->GetEngineName(), sdl_factory);
+#endif
+
+        Input::RegisterFactory<Input::InputDevice>("touch_from_button",
+                                                   std::make_shared<TouchFromButton>());
+        Input::RegisterFactory<Input::InputDevice>("analog_from_button",
+                                                   std::make_shared<StickFromButton>());
     }
 
     void Shutdown() {
+        Input::UnregisterFactory<Input::InputDevice>(keyboard->GetEngineName());
+        keyboard.reset();
+
+        Input::UnregisterFactory<Input::InputDevice>(mouse->GetEngineName());
+        mouse.reset();
+
+        Input::UnregisterFactory<Input::InputDevice>(touch_screen->GetEngineName());
+        touch_screen.reset();
+
+        Input::UnregisterFactory<Input::InputDevice>(gcadapter->GetEngineName());
+        gcadapter.reset();
+
+        Input::UnregisterFactory<Input::InputDevice>(udp_client->GetEngineName());
+        udp_client.reset();
+
+        Input::UnregisterFactory<Input::InputDevice>(tas_input->GetEngineName());
+        tas_input.reset();
+
+#ifdef HAVE_SDL2
+        Input::UnregisterFactory<Input::InputDevice>(sdl->GetEngineName());
+        sdl.reset();
+#endif
+
+        Input::UnregisterFactory<Input::InputDevice>("touch_from_button");
+        Input::UnregisterFactory<Input::InputDevice>("analog_from_button");
     }
 
     [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
         std::vector<Common::ParamPackage> devices = {
-            Common::ParamPackage{{"display", "Any"}, {"class", "any"}},
-            Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "keyboard"}},
+            Common::ParamPackage{{"display", "Any"}, {"engine", "any"}},
         };
-        return {};
+
+        auto keyboard_devices = keyboard->GetInputDevices();
+        devices.insert(devices.end(), keyboard_devices.begin(), keyboard_devices.end());
+        auto mouse_devices = mouse->GetInputDevices();
+        devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end());
+        auto gcadapter_devices = gcadapter->GetInputDevices();
+        devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end());
+        auto tas_input_devices = tas_input->GetInputDevices();
+        devices.insert(devices.end(), tas_input_devices.begin(), tas_input_devices.end());
+#ifdef HAVE_SDL2
+        auto sdl_devices = sdl->GetInputDevices();
+        devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
+#endif
+
+        return devices;
     }
 
     [[nodiscard]] AnalogMapping GetAnalogMappingForDevice(
         const Common::ParamPackage& params) const {
-        if (!params.Has("class") || params.Get("class", "") == "any") {
+        if (!params.Has("engine") || params.Get("engine", "") == "any") {
             return {};
         }
+        const std::string engine = params.Get("engine", "");
+        if (engine == gcadapter->GetEngineName()) {
+            return gcadapter->GetAnalogMappingForDevice(params);
+        }
+        if (engine == tas_input->GetEngineName()) {
+            return tas_input->GetAnalogMappingForDevice(params);
+        }
+#ifdef HAVE_SDL2
+        if (engine == sdl->GetEngineName()) {
+            return sdl->GetAnalogMappingForDevice(params);
+        }
+#endif
         return {};
     }
 
     [[nodiscard]] ButtonMapping GetButtonMappingForDevice(
         const Common::ParamPackage& params) const {
-        if (!params.Has("class") || params.Get("class", "") == "any") {
+        if (!params.Has("engine") || params.Get("engine", "") == "any") {
             return {};
         }
+        const std::string engine = params.Get("engine", "");
+        if (engine == gcadapter->GetEngineName()) {
+            return gcadapter->GetButtonMappingForDevice(params);
+        }
+        if (engine == tas_input->GetEngineName()) {
+            return tas_input->GetButtonMappingForDevice(params);
+        }
+#ifdef HAVE_SDL2
+        if (engine == sdl->GetEngineName()) {
+            return sdl->GetButtonMappingForDevice(params);
+        }
+#endif
         return {};
     }
 
     [[nodiscard]] MotionMapping GetMotionMappingForDevice(
         const Common::ParamPackage& params) const {
-        if (!params.Has("class") || params.Get("class", "") == "any") {
+        if (!params.Has("engine") || params.Get("engine", "") == "any") {
             return {};
         }
+        const std::string engine = params.Get("engine", "");
+        if (engine == gcadapter->GetEngineName()) {
+            return gcadapter->GetMotionMappingForDevice(params);
+        }
+#ifdef HAVE_SDL2
+        if (engine == sdl->GetEngineName()) {
+            return sdl->GetMotionMappingForDevice(params);
+        }
+#endif
         return {};
     }
 
+    std::string GetButtonName(const Common::ParamPackage& params) const {
+        if (!params.Has("engine") || params.Get("engine", "") == "any") {
+            return "Unknown";
+        }
+        const std::string engine = params.Get("engine", "");
+        if (engine == mouse->GetEngineName()) {
+            return mouse->GetUIName(params);
+        }
+        if (engine == gcadapter->GetEngineName()) {
+            return gcadapter->GetUIName(params);
+        }
+        if (engine == udp_client->GetEngineName()) {
+            return udp_client->GetUIName(params);
+        }
+        if (engine == tas_input->GetEngineName()) {
+            return tas_input->GetUIName(params);
+        }
+#ifdef HAVE_SDL2
+        if (engine == sdl->GetEngineName()) {
+            return sdl->GetUIName(params);
+        }
+#endif
+        return "Bad engine";
+    }
+
+    bool IsController(const Common::ParamPackage& params) {
+        const std::string engine = params.Get("engine", "");
+        if (engine == mouse->GetEngineName()) {
+            return true;
+        }
+        if (engine == gcadapter->GetEngineName()) {
+            return true;
+        }
+        if (engine == tas_input->GetEngineName()) {
+            return true;
+        }
+#ifdef HAVE_SDL2
+        if (engine == sdl->GetEngineName()) {
+            return true;
+        }
+#endif
+        return false;
+    }
+
+    void BeginConfiguration() {
+        keyboard->BeginConfiguration();
+        mouse->BeginConfiguration();
+        gcadapter->BeginConfiguration();
+        udp_client->BeginConfiguration();
+#ifdef HAVE_SDL2
+        sdl->BeginConfiguration();
+#endif
+    }
+
+    void EndConfiguration() {
+        keyboard->EndConfiguration();
+        mouse->EndConfiguration();
+        gcadapter->EndConfiguration();
+        udp_client->EndConfiguration();
+#ifdef HAVE_SDL2
+        sdl->EndConfiguration();
+#endif
+    }
+
+    void RegisterInput(MappingData data) {
+        mapping_factory->RegisterInput(data);
+    }
+
+    std::shared_ptr<MappingFactory> mapping_factory;
+    std::shared_ptr<Keyboard> keyboard;
+    std::shared_ptr<InputFactory> keyboard_factory;
+    std::shared_ptr<Mouse> mouse;
+    std::shared_ptr<InputFactory> mouse_factory;
+    std::shared_ptr<GCAdapter> gcadapter;
+    std::shared_ptr<InputFactory> gcadapter_factory;
+    std::shared_ptr<TouchScreen> touch_screen;
+    std::shared_ptr<InputFactory> touch_screen_factory;
+    std::shared_ptr<CemuhookUDP::UDPClient> udp_client;
+    std::shared_ptr<InputFactory> udp_client_factory;
+    std::shared_ptr<TasInput::Tas> tas_input;
+    std::shared_ptr<InputFactory> tas_input_factory;
+#ifdef HAVE_SDL2
+    std::shared_ptr<SDLDriver> sdl;
+    std::shared_ptr<InputFactory> sdl_factory;
+#endif
 };
 
 InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {}
@@ -66,6 +277,38 @@ void InputSubsystem::Shutdown() {
     impl->Shutdown();
 }
 
+Keyboard* InputSubsystem::GetKeyboard() {
+    return impl->keyboard.get();
+}
+
+const Keyboard* InputSubsystem::GetKeyboard() const {
+    return impl->keyboard.get();
+}
+
+Mouse* InputSubsystem::GetMouse() {
+    return impl->mouse.get();
+}
+
+const Mouse* InputSubsystem::GetMouse() const {
+    return impl->mouse.get();
+}
+
+TouchScreen* InputSubsystem::GetTouchScreen() {
+    return impl->touch_screen.get();
+}
+
+const TouchScreen* InputSubsystem::GetTouchScreen() const {
+    return impl->touch_screen.get();
+}
+
+TasInput::Tas* InputSubsystem::GetTas() {
+    return impl->tas_input.get();
+}
+
+const TasInput::Tas* InputSubsystem::GetTas() const {
+    return impl->tas_input.get();
+}
+
 std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const {
     return impl->GetInputDevices();
 }
@@ -82,12 +325,37 @@ MotionMapping InputSubsystem::GetMotionMappingForDevice(const Common::ParamPacka
     return impl->GetMotionMappingForDevice(device);
 }
 
-void InputSubsystem::ReloadInputDevices() {
+std::string InputSubsystem::GetButtonName(const Common::ParamPackage& params) const {
+    const std::string toggle = params.Get("toggle", false) ? "~" : "";
+    const std::string inverted = params.Get("inverted", false) ? "!" : "";
+    const std::string button_name = impl->GetButtonName(params);
+    std::string axis_direction = "";
+    if (params.Has("axis")) {
+        axis_direction = params.Get("invert", "+");
+    }
+    return fmt::format("{}{}{}{}", toggle, inverted, button_name, axis_direction);
 }
 
-std::vector<std::unique_ptr<Polling::DevicePoller>> InputSubsystem::GetPollers([
-    [maybe_unused]] Polling::DeviceType type) const {
-    return {};
+bool InputSubsystem::IsController(const Common::ParamPackage& params) const {
+    return impl->IsController(params);
+}
+
+void InputSubsystem::ReloadInputDevices() {
+    impl->udp_client.get()->ReloadSockets();
+}
+
+void InputSubsystem::BeginMapping(Polling::InputType type) {
+    impl->BeginConfiguration();
+    impl->mapping_factory->BeginMapping(type);
+}
+
+const Common::ParamPackage InputSubsystem::GetNextInput() const {
+    return impl->mapping_factory->GetNextInput();
+}
+
+void InputSubsystem::StopMapping() const {
+    impl->EndConfiguration();
+    impl->mapping_factory->StopMapping();
 }
 
 std::string GenerateKeyboardParam(int key_code) {
diff --git a/src/input_common/main.h b/src/input_common/main.h
index b504ebe54a..a4a24d076e 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -25,47 +25,26 @@ namespace Settings::NativeMotion {
 enum Values : int;
 }
 
-namespace MouseInput {
+namespace InputCommon {
+class Keyboard;
 class Mouse;
-}
+class TouchScreen;
+struct MappingData;
+} // namespace InputCommon
 
-namespace TasInput {
+namespace InputCommon::TasInput {
 class Tas;
-}
+} // namespace InputCommon::TasInput
 
 namespace InputCommon {
 namespace Polling {
-
-enum class DeviceType { Button, AnalogPreferred, Motion };
-
 /// Type of input desired for mapping purposes
 enum class InputType { None, Button, Stick, Motion, Touch };
-
-/**
- * A class that can be used to get inputs from an input device like controllers without having to
- * poll the device's status yourself
- */
-class DevicePoller {
-public:
-    virtual ~DevicePoller() = default;
-    /// Setup and start polling for inputs, should be called before GetNextInput
-    /// If a device_id is provided, events should be filtered to only include events from this
-    /// device id
-    virtual void Start(const std::string& device_id = "") = 0;
-    /// Stop polling
-    virtual void Stop() = 0;
-    /**
-     * Every call to this function returns the next input recorded since calling Start
-     * @return A ParamPackage of the recorded input, which can be used to create an InputDevice.
-     *         If there has been no input, the package is empty
-     */
-    virtual Common::ParamPackage GetNextInput() = 0;
-};
 } // namespace Polling
 
 /**
  * Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default
- * mapping for the device. This is currently only implemented for the SDL backend devices.
+ * mapping for the device.
  */
 using AnalogMapping = std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage>;
 using ButtonMapping = std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage>;
@@ -88,10 +67,34 @@ public:
     /// Unregisters all built-in input device factories and shuts them down.
     void Shutdown();
 
+    /// Retrieves the underlying keyboard device.
+    [[nodiscard]] Keyboard* GetKeyboard();
+
+    /// Retrieves the underlying keyboard device.
+    [[nodiscard]] const Keyboard* GetKeyboard() const;
+
+    /// Retrieves the underlying mouse device.
+    [[nodiscard]] Mouse* GetMouse();
+
+    /// Retrieves the underlying mouse device.
+    [[nodiscard]] const Mouse* GetMouse() const;
+
+    /// Retrieves the underlying touch screen device.
+    [[nodiscard]] TouchScreen* GetTouchScreen();
+
+    /// Retrieves the underlying touch screen device.
+    [[nodiscard]] const TouchScreen* GetTouchScreen() const;
+
+    /// Retrieves the underlying tas input device.
+    [[nodiscard]] TasInput::Tas* GetTas();
+
+    /// Retrieves the underlying  tas input  device.
+    [[nodiscard]] const TasInput::Tas* GetTas() const;
+
     /**
      * Returns all available input devices that this Factory can create a new device with.
-     * Each returned ParamPackage should have a `display` field used for display, a class field for
-     * backends to determine if this backend is meant to service the request and any other
+     * Each returned ParamPackage should have a `display` field used for display, a `engine` field
+     * for backends to determine if this backend is meant to service the request and any other
      * information needed to identify this in the backend later.
      */
     [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const;
@@ -105,23 +108,33 @@ public:
     /// Retrieves the motion mappings for the given device.
     [[nodiscard]] MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& device) const;
 
-    /// Reloads the input devices
+    /// Returns a string contaning the name of the button from the input engine.
+    [[nodiscard]] std::string GetButtonName(const Common::ParamPackage& params) const;
+
+    /// Returns true if device is a controller.
+    [[nodiscard]] bool IsController(const Common::ParamPackage& params) const;
+
+    /// Reloads the input devices.
     void ReloadInputDevices();
 
-    /// Get all DevicePoller from all backends for a specific device type
-    [[nodiscard]] std::vector<std::unique_ptr<Polling::DevicePoller>> GetPollers(
-        Polling::DeviceType type) const;
+    /// Start polling from all backends for a desired input type.
+    void BeginMapping(Polling::InputType type);
+
+    /// Returns an input event with mapping information.
+    [[nodiscard]] const Common::ParamPackage GetNextInput() const;
+
+    /// Stop polling from all backends.
+    void StopMapping() const;
 
 private:
     struct Impl;
     std::unique_ptr<Impl> impl;
 };
 
-/// Generates a serialized param package for creating a keyboard button device
+/// Generates a serialized param package for creating a keyboard button device.
 std::string GenerateKeyboardParam(int key_code);
 
-/// Generates a serialized param package for creating an analog device taking input from keyboard
+/// Generates a serialized param package for creating an analog device taking input from keyboard.
 std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
                                         int key_modifier, float modifier_scale);
-
 } // namespace InputCommon

From 737d305f6324d28a7fde882077fb7e9a0e66311f Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 19:39:08 -0500
Subject: [PATCH 16/88] yuzu: Use new input on main and bootmanager

---
 src/yuzu/bootmanager.cpp | 87 +++++++++++++++++++---------------------
 src/yuzu/bootmanager.h   |  9 ++---
 src/yuzu/main.cpp        | 25 ++++++------
 3 files changed, 56 insertions(+), 65 deletions(-)

diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 8a0ea90f9d..726f789b7f 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -27,12 +27,15 @@
 
 #include "common/assert.h"
 #include "common/microprofile.h"
+#include "common/param_package.h"
 #include "common/scm_rev.h"
 #include "common/scope_exit.h"
 #include "common/settings.h"
 #include "core/core.h"
 #include "core/frontend/framebuffer_layout.h"
-#include "input_common/keyboard.h"
+#include "input_common/drivers/keyboard.h"
+#include "input_common/drivers/mouse.h"
+#include "input_common/drivers/touch_screen.h"
 #include "input_common/main.h"
 #include "video_core/renderer_base.h"
 #include "video_core/video_core.h"
@@ -294,7 +297,6 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
     layout->setContentsMargins(0, 0, 0, 0);
     setLayout(layout);
     input_subsystem->Initialize();
-
     this->setMouseTracking(true);
 
     connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
@@ -392,34 +394,34 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
 
 void GRenderWindow::keyPressEvent(QKeyEvent* event) {
     if (!event->isAutoRepeat()) {
-       // input_subsystem->GetKeyboard()->PressKey(event->key());
+        input_subsystem->GetKeyboard()->PressKey(event->key());
     }
 }
 
 void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
     if (!event->isAutoRepeat()) {
-       // input_subsystem->GetKeyboard()->ReleaseKey(event->key());
+        input_subsystem->GetKeyboard()->ReleaseKey(event->key());
     }
 }
 
-//MouseInput::MouseButton GRenderWindow::QtButtonToMouseButton(Qt::MouseButton button) {
-//    switch (button) {
-//    case Qt::LeftButton:
-//        return MouseInput::MouseButton::Left;
-//    case Qt::RightButton:
-//        return MouseInput::MouseButton::Right;
-//    case Qt::MiddleButton:
-//        return MouseInput::MouseButton::Wheel;
-//    case Qt::BackButton:
-//        return MouseInput::MouseButton::Backward;
-//    case Qt::ForwardButton:
-//        return MouseInput::MouseButton::Forward;
-//    case Qt::TaskButton:
-//        return MouseInput::MouseButton::Task;
-//    default:
-//        return MouseInput::MouseButton::Extra;
-//    }
-//}
+InputCommon::MouseButton GRenderWindow::QtButtonToMouseButton(Qt::MouseButton button) {
+    switch (button) {
+    case Qt::LeftButton:
+        return InputCommon::MouseButton::Left;
+    case Qt::RightButton:
+        return InputCommon::MouseButton::Right;
+    case Qt::MiddleButton:
+        return InputCommon::MouseButton::Wheel;
+    case Qt::BackButton:
+        return InputCommon::MouseButton::Backward;
+    case Qt::ForwardButton:
+        return InputCommon::MouseButton::Forward;
+    case Qt::TaskButton:
+        return InputCommon::MouseButton::Task;
+    default:
+        return InputCommon::MouseButton::Extra;
+    }
+}
 
 void GRenderWindow::mousePressEvent(QMouseEvent* event) {
     // Touch input is handled in TouchBeginEvent
@@ -430,12 +432,9 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
     // coordinates and map them to the current render area
     const auto pos = mapFromGlobal(QCursor::pos());
     const auto [x, y] = ScaleTouch(pos);
-    //const auto button = QtButtonToMouseButton(event->button());
-    //input_subsystem->GetMouse()->PressButton(x, y, button);
-
-    if (event->button() == Qt::LeftButton) {
-        this->TouchPressed(x, y, 0);
-    }
+    const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
+    const auto button = QtButtonToMouseButton(event->button());
+    input_subsystem->GetMouse()->PressButton(x, y, touch_x, touch_y, button);
 
     emit MouseActivity();
 }
@@ -449,10 +448,10 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
     // coordinates and map them to the current render area
     const auto pos = mapFromGlobal(QCursor::pos());
     const auto [x, y] = ScaleTouch(pos);
+    const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
     const int center_x = width() / 2;
     const int center_y = height() / 2;
-    //input_subsystem->GetMouse()->MouseMove(x, y, center_x, center_y);
-    this->TouchMoved(x, y, 0);
+    input_subsystem->GetMouse()->MouseMove(x, y, touch_x, touch_y, center_x, center_y);
 
     if (Settings::values.mouse_panning) {
         QCursor::setPos(mapToGlobal({center_x, center_y}));
@@ -467,12 +466,8 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
         return;
     }
 
-    //const auto button = QtButtonToMouseButton(event->button());
-    //input_subsystem->GetMouse()->ReleaseButton(button);
-
-    if (event->button() == Qt::LeftButton) {
-        this->TouchReleased(0);
-    }
+    const auto button = QtButtonToMouseButton(event->button());
+    input_subsystem->GetMouse()->ReleaseButton(button);
 }
 
 void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) {
@@ -495,7 +490,7 @@ void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) {
     for (std::size_t id = 0; id < touch_ids.size(); ++id) {
         if (!TouchExist(touch_ids[id], touch_points)) {
             touch_ids[id] = 0;
-            this->TouchReleased(id + 1);
+            input_subsystem->GetTouchScreen()->TouchReleased(id);
         }
     }
 }
@@ -504,28 +499,28 @@ void GRenderWindow::TouchEndEvent() {
     for (std::size_t id = 0; id < touch_ids.size(); ++id) {
         if (touch_ids[id] != 0) {
             touch_ids[id] = 0;
-            this->TouchReleased(id + 1);
+            input_subsystem->GetTouchScreen()->TouchReleased(id);
         }
     }
 }
 
-bool GRenderWindow::TouchStart(const QTouchEvent::TouchPoint& touch_point) {
+void GRenderWindow::TouchStart(const QTouchEvent::TouchPoint& touch_point) {
     for (std::size_t id = 0; id < touch_ids.size(); ++id) {
         if (touch_ids[id] == 0) {
             touch_ids[id] = touch_point.id() + 1;
             const auto [x, y] = ScaleTouch(touch_point.pos());
-            this->TouchPressed(x, y, id + 1);
-            return true;
+            const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
+            input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id);
         }
     }
-    return false;
 }
 
 bool GRenderWindow::TouchUpdate(const QTouchEvent::TouchPoint& touch_point) {
     for (std::size_t id = 0; id < touch_ids.size(); ++id) {
         if (touch_ids[id] == static_cast<std::size_t>(touch_point.id() + 1)) {
             const auto [x, y] = ScaleTouch(touch_point.pos());
-            this->TouchMoved(x, y, id + 1);
+            const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
+            input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id);
             return true;
         }
     }
@@ -556,9 +551,9 @@ bool GRenderWindow::event(QEvent* event) {
 
 void GRenderWindow::focusOutEvent(QFocusEvent* event) {
     QWidget::focusOutEvent(event);
-    //input_subsystem->GetKeyboard()->ReleaseAllKeys();
-    //input_subsystem->GetMouse()->ReleaseAllButtons();
-    this->TouchReleased(0);
+    input_subsystem->GetKeyboard()->ReleaseAllKeys();
+    input_subsystem->GetMouse()->ReleaseAllButtons();
+    input_subsystem->GetTouchScreen()->ReleaseAllTouch();
 }
 
 void GRenderWindow::resizeEvent(QResizeEvent* event) {
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index f0784046bd..95594f81ca 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -30,11 +30,8 @@ class System;
 
 namespace InputCommon {
 class InputSubsystem;
-}
-
-namespace MouseInput {
 enum class MouseButton;
-}
+} // namespace InputCommon
 
 namespace VideoCore {
 enum class LoadCallbackStage;
@@ -165,7 +162,7 @@ public:
     void keyReleaseEvent(QKeyEvent* event) override;
 
     /// Converts a Qt mouse button into MouseInput mouse button
-    // static MouseInput::MouseButton QtButtonToMouseButton(Qt::MouseButton button);
+    static InputCommon::MouseButton QtButtonToMouseButton(Qt::MouseButton button);
 
     void mousePressEvent(QMouseEvent* event) override;
     void mouseMoveEvent(QMouseEvent* event) override;
@@ -214,7 +211,7 @@ private:
     void TouchUpdateEvent(const QTouchEvent* event);
     void TouchEndEvent();
 
-    bool TouchStart(const QTouchEvent::TouchPoint& touch_point);
+    void TouchStart(const QTouchEvent::TouchPoint& touch_point);
     bool TouchUpdate(const QTouchEvent::TouchPoint& touch_point);
     bool TouchExist(std::size_t id, const QList<QTouchEvent::TouchPoint>& touch_points) const;
 
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 663760a1ea..7f36f6e2f4 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -106,8 +106,8 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
 #include "core/loader/loader.h"
 #include "core/perf_stats.h"
 #include "core/telemetry_session.h"
+#include "input_common/drivers/tas_input.h"
 #include "input_common/main.h"
-#include "input_common/tas/tas_input.h"
 #include "ui_main.h"
 #include "util/overlay_dialog.h"
 #include "video_core/gpu.h"
@@ -838,7 +838,6 @@ void GMainWindow::InitializeWidgets() {
             controller_type = Settings::ControllerType::ProController;
             ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get(), *system);
             configure_dialog.ApplyConfiguration();
-            controller_dialog->refreshConfiguration();
         }
 
         Settings::values.use_docked_mode.SetValue(!is_docked);
@@ -922,7 +921,7 @@ void GMainWindow::InitializeDebugWidgets() {
     waitTreeWidget->hide();
     debug_menu->addAction(waitTreeWidget->toggleViewAction());
 
-    controller_dialog = new ControllerDialog(this, input_subsystem.get());
+    controller_dialog = new ControllerDialog(this);
     controller_dialog->hide();
     debug_menu->addAction(controller_dialog->toggleViewAction());
 
@@ -2708,7 +2707,6 @@ void GMainWindow::OnConfigure() {
 
         ShowTelemetryCallout();
     }
-    controller_dialog->refreshConfiguration();
     InitializeHotkeys();
 
     if (UISettings::values.theme != old_theme) {
@@ -2969,15 +2967,15 @@ void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_vie
 }
 
 QString GMainWindow::GetTasStateDescription() const {
-    //auto [tas_status, current_tas_frame, total_tas_frames] = input_subsystem->GetTas()->GetStatus();
-    //switch (tas_status) {
-    //case TasInput::TasState::Running:
-    //    return tr("TAS state: Running %1/%2").arg(current_tas_frame).arg(total_tas_frames);
-    //case TasInput::TasState::Recording:
-    //    return tr("TAS state: Recording %1").arg(total_tas_frames);
-    //case TasInput::TasState::Stopped:
-    //    return tr("TAS state: Idle %1/%2").arg(current_tas_frame).arg(total_tas_frames);
-    //default:
+    auto [tas_status, current_tas_frame, total_tas_frames] = input_subsystem->GetTas()->GetStatus();
+    switch (tas_status) {
+    case InputCommon::TasInput::TasState::Running:
+        return tr("TAS state: Running %1/%2").arg(current_tas_frame).arg(total_tas_frames);
+    case InputCommon::TasInput::TasState::Recording:
+        return tr("TAS state: Recording %1").arg(total_tas_frames);
+    case InputCommon::TasInput::TasState::Stopped:
+        return tr("TAS state: Idle %1/%2").arg(current_tas_frame).arg(total_tas_frames);
+    default:
         return tr("TAS State: Invalid");
     }
 }
@@ -3371,6 +3369,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
     UpdateUISettings();
     game_list->SaveInterfaceLayout();
     hotkey_registry.SaveHotkeys();
+    Core::System::GetInstance().HIDCore().UnloadInputDevices();
 
     // Shutdown session if the emu thread is active...
     if (emu_thread != nullptr) {

From 14b949a0da6aa600d873c88f1836921f4d9a7919 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 19:40:00 -0500
Subject: [PATCH 17/88] yuzu_cmd: Use new input

---
 src/yuzu_cmd/emu_window/emu_window_sdl2.cpp   | 72 +++++++++----------
 src/yuzu_cmd/emu_window/emu_window_sdl2.h     | 11 ++-
 .../emu_window/emu_window_sdl2_gl.cpp         |  1 -
 3 files changed, 39 insertions(+), 45 deletions(-)

diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index 87fce0c230..57f8078265 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -9,10 +9,10 @@
 #include "common/settings.h"
 #include "core/core.h"
 #include "core/perf_stats.h"
-#include "input_common/keyboard.h"
+#include "input_common/drivers/keyboard.h"
+#include "input_common/drivers/mouse.h"
+#include "input_common/drivers/touch_screen.h"
 #include "input_common/main.h"
-#include "input_common/mouse/mouse_input.h"
-#include "input_common/sdl/sdl.h"
 #include "yuzu_cmd/emu_window/emu_window_sdl2.h"
 #include "yuzu_cmd/yuzu_icon.h"
 
@@ -32,42 +32,32 @@ EmuWindow_SDL2::~EmuWindow_SDL2() {
 }
 
 void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
-    TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0), 0);
-
-    input_subsystem->GetMouse()->MouseMove(x, y, 0, 0);
+    input_subsystem->GetMouse()->MouseMove(x, y, 0, 0, 0, 0);
 }
 
-MouseInput::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) const {
+InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) const {
     switch (button) {
     case SDL_BUTTON_LEFT:
-        return MouseInput::MouseButton::Left;
+        return InputCommon::MouseButton::Left;
     case SDL_BUTTON_RIGHT:
-        return MouseInput::MouseButton::Right;
+        return InputCommon::MouseButton::Right;
     case SDL_BUTTON_MIDDLE:
-        return MouseInput::MouseButton::Wheel;
+        return InputCommon::MouseButton::Wheel;
     case SDL_BUTTON_X1:
-        return MouseInput::MouseButton::Backward;
+        return InputCommon::MouseButton::Backward;
     case SDL_BUTTON_X2:
-        return MouseInput::MouseButton::Forward;
+        return InputCommon::MouseButton::Forward;
     default:
-        return MouseInput::MouseButton::Undefined;
+        return InputCommon::MouseButton::Undefined;
     }
 }
 
 void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
     const auto mouse_button = SDLButtonToMouseButton(button);
-    if (button == SDL_BUTTON_LEFT) {
-        if (state == SDL_PRESSED) {
-            TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0), 0);
-        } else {
-            TouchReleased(0);
-        }
+    if (state == SDL_PRESSED) {
+        input_subsystem->GetMouse()->PressButton(x, y, 0, 0, mouse_button);
     } else {
-        if (state == SDL_PRESSED) {
-            input_subsystem->GetMouse()->PressButton(x, y, mouse_button);
-        } else {
-            input_subsystem->GetMouse()->ReleaseButton(mouse_button);
-        }
+        input_subsystem->GetMouse()->ReleaseButton(mouse_button);
     }
 }
 
@@ -82,29 +72,35 @@ std::pair<unsigned, unsigned> EmuWindow_SDL2::TouchToPixelPos(float touch_x, flo
             static_cast<unsigned>(std::max(std::round(touch_y), 0.0f))};
 }
 
-void EmuWindow_SDL2::OnFingerDown(float x, float y) {
-    // TODO(NeatNit): keep track of multitouch using the fingerID and a dictionary of some kind
-    // This isn't critical because the best we can do when we have that is to average them, like the
-    // 3DS does
-
+void EmuWindow_SDL2::OnFingerDown(float x, float y, std::size_t id) {
+    int width, height;
+    SDL_GetWindowSize(render_window, &width, &height);
     const auto [px, py] = TouchToPixelPos(x, y);
-    TouchPressed(px, py, 0);
+    const float fx = px * 1.0f / width;
+    const float fy = py * 1.0f / height;
+
+    input_subsystem->GetTouchScreen()->TouchPressed(fx, fy, id);
 }
 
-void EmuWindow_SDL2::OnFingerMotion(float x, float y) {
+void EmuWindow_SDL2::OnFingerMotion(float x, float y, std::size_t id) {
+    int width, height;
+    SDL_GetWindowSize(render_window, &width, &height);
     const auto [px, py] = TouchToPixelPos(x, y);
-    TouchMoved(px, py, 0);
+    const float fx = px * 1.0f / width;
+    const float fy = py * 1.0f / height;
+
+    input_subsystem->GetTouchScreen()->TouchMoved(fx, fy, id);
 }
 
 void EmuWindow_SDL2::OnFingerUp() {
-    TouchReleased(0);
+    input_subsystem->GetTouchScreen()->TouchReleased(0);
 }
 
 void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
     if (state == SDL_PRESSED) {
-        input_subsystem->GetKeyboard()->PressKey(key);
+        input_subsystem->GetKeyboard()->PressKey(static_cast<std::size_t>(key));
     } else if (state == SDL_RELEASED) {
-        input_subsystem->GetKeyboard()->ReleaseKey(key);
+        input_subsystem->GetKeyboard()->ReleaseKey(static_cast<std::size_t>(key));
     }
 }
 
@@ -205,10 +201,12 @@ void EmuWindow_SDL2::WaitEvent() {
         }
         break;
     case SDL_FINGERDOWN:
-        OnFingerDown(event.tfinger.x, event.tfinger.y);
+        OnFingerDown(event.tfinger.x, event.tfinger.y,
+                     static_cast<std::size_t>(event.tfinger.touchId));
         break;
     case SDL_FINGERMOTION:
-        OnFingerMotion(event.tfinger.x, event.tfinger.y);
+        OnFingerMotion(event.tfinger.x, event.tfinger.y,
+                       static_cast<std::size_t>(event.tfinger.touchId));
         break;
     case SDL_FINGERUP:
         OnFingerUp();
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
index 4810f87755..0af002693e 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
@@ -16,11 +16,8 @@ class System;
 
 namespace InputCommon {
 class InputSubsystem;
-}
-
-namespace MouseInput {
 enum class MouseButton;
-}
+} // namespace InputCommon
 
 class EmuWindow_SDL2 : public Core::Frontend::EmuWindow {
 public:
@@ -47,7 +44,7 @@ protected:
     void OnMouseMotion(s32 x, s32 y);
 
     /// Converts a SDL mouse button into MouseInput mouse button
-    MouseInput::MouseButton SDLButtonToMouseButton(u32 button) const;
+    InputCommon::MouseButton SDLButtonToMouseButton(u32 button) const;
 
     /// Called by WaitEvent when a mouse button is pressed or released
     void OnMouseButton(u32 button, u8 state, s32 x, s32 y);
@@ -56,10 +53,10 @@ protected:
     std::pair<unsigned, unsigned> TouchToPixelPos(float touch_x, float touch_y) const;
 
     /// Called by WaitEvent when a finger starts touching the touchscreen
-    void OnFingerDown(float x, float y);
+    void OnFingerDown(float x, float y, std::size_t id);
 
     /// Called by WaitEvent when a finger moves while touching the touchscreen
-    void OnFingerMotion(float x, float y);
+    void OnFingerMotion(float x, float y, std::size_t id);
 
     /// Called by WaitEvent when a finger stops touching the touchscreen
     void OnFingerUp();
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index a075ad08ae..70db865ec3 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -17,7 +17,6 @@
 #include "common/settings.h"
 #include "common/string_util.h"
 #include "core/core.h"
-#include "input_common/keyboard.h"
 #include "input_common/main.h"
 #include "video_core/renderer_base.h"
 #include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h"

From c3f54ff2329d79bdbb273678b5123cf0b1cd090c Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 19:43:16 -0500
Subject: [PATCH 18/88] core/hid: Add emulated controllers

---
 src/core/CMakeLists.txt              |   8 +
 src/core/hid/emulated_console.cpp    | 208 ++++++++
 src/core/hid/emulated_console.h      | 142 +++++
 src/core/hid/emulated_controller.cpp | 745 +++++++++++++++++++++++++++
 src/core/hid/emulated_controller.h   | 232 +++++++++
 src/core/hid/emulated_devices.cpp    | 349 +++++++++++++
 src/core/hid/emulated_devices.h      | 137 +++++
 src/core/hid/hid_core.cpp            | 144 ++++++
 src/core/hid/hid_core.h              |  60 +++
 9 files changed, 2025 insertions(+)
 create mode 100644 src/core/hid/emulated_console.cpp
 create mode 100644 src/core/hid/emulated_console.h
 create mode 100644 src/core/hid/emulated_controller.cpp
 create mode 100644 src/core/hid/emulated_controller.h
 create mode 100644 src/core/hid/emulated_devices.cpp
 create mode 100644 src/core/hid/emulated_devices.h
 create mode 100644 src/core/hid/hid_core.cpp
 create mode 100644 src/core/hid/hid_core.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index eddf455c08..09163fab97 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -135,6 +135,14 @@ add_library(core STATIC
     frontend/input.h
     hardware_interrupt_manager.cpp
     hardware_interrupt_manager.h
+    hid/emulated_console.cpp
+    hid/emulated_console.h
+    hid/emulated_controller.cpp
+    hid/emulated_controller.h
+    hid/emulated_devices.cpp
+    hid/emulated_devices.h
+    hid/hid_core.cpp
+    hid/hid_core.h
     hid/hid_types.h
     hid/input_converter.cpp
     hid/input_converter.h
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
new file mode 100644
index 0000000000..c65d050411
--- /dev/null
+++ b/src/core/hid/emulated_console.cpp
@@ -0,0 +1,208 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#include <fmt/format.h>
+
+#include "core/hid/emulated_console.h"
+#include "core/hid/input_converter.h"
+
+namespace Core::HID {
+EmulatedConsole::EmulatedConsole() {}
+
+EmulatedConsole::~EmulatedConsole() = default;
+
+void EmulatedConsole::ReloadFromSettings() {
+    // Using first motion device from player 1. No need to assign a special config at the moment
+    const auto& player = Settings::values.players.GetValue()[0];
+    motion_params = Common::ParamPackage(player.motions[0]);
+
+    ReloadInput();
+}
+
+void EmulatedConsole::ReloadInput() {
+    motion_devices = Input::CreateDevice<Input::InputDevice>(motion_params);
+    if (motion_devices) {
+        Input::InputCallback motion_callback{
+            [this](Input::CallbackStatus callback) { SetMotion(callback); }};
+        motion_devices->SetCallback(motion_callback);
+    }
+
+    // TODO: Fix this mess
+    std::size_t index = 0;
+    const std::string mouse_device_string =
+        fmt::format("engine:mouse,axis_x:10,axis_y:11,button:{}", index);
+    touch_devices[index] = Input::CreateDeviceFromString<Input::InputDevice>(mouse_device_string);
+    Input::InputCallback trigger_callbackk{
+        [this, index](Input::CallbackStatus callback) { SetTouch(callback, index); }};
+    touch_devices[index]->SetCallback(trigger_callbackk);
+
+    index++;
+    const auto button_index =
+        static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
+    const auto& touch_buttons = Settings::values.touch_from_button_maps[button_index].buttons;
+    for (const auto& config_entry : touch_buttons) {
+        Common::ParamPackage params{config_entry};
+        Common::ParamPackage touch_button_params;
+        const int x = params.Get("x", 0);
+        const int y = params.Get("y", 0);
+        params.Erase("x");
+        params.Erase("y");
+        touch_button_params.Set("engine", "touch_from_button");
+        touch_button_params.Set("button", params.Serialize());
+        touch_button_params.Set("x", x);
+        touch_button_params.Set("y", y);
+        touch_button_params.Set("touch_id", static_cast<int>(index));
+        LOG_ERROR(Common, "{} ", touch_button_params.Serialize());
+        touch_devices[index] =
+            Input::CreateDeviceFromString<Input::InputDevice>(touch_button_params.Serialize());
+        if (!touch_devices[index]) {
+            continue;
+        }
+
+        Input::InputCallback trigger_callback{
+            [this, index](Input::CallbackStatus callback) { SetTouch(callback, index); }};
+        touch_devices[index]->SetCallback(trigger_callback);
+        index++;
+    }
+}
+
+void EmulatedConsole::UnloadInput() {
+    motion_devices.reset();
+    for (auto& touch : touch_devices) {
+        touch.reset();
+    }
+}
+
+void EmulatedConsole::EnableConfiguration() {
+    is_configuring = true;
+    SaveCurrentConfig();
+}
+
+void EmulatedConsole::DisableConfiguration() {
+    is_configuring = false;
+}
+
+bool EmulatedConsole::IsConfiguring() const {
+    return is_configuring;
+}
+
+void EmulatedConsole::SaveCurrentConfig() {
+    if (!is_configuring) {
+        return;
+    }
+}
+
+void EmulatedConsole::RestoreConfig() {
+    if (!is_configuring) {
+        return;
+    }
+    ReloadFromSettings();
+}
+
+Common::ParamPackage EmulatedConsole::GetMotionParam() const {
+    return motion_params;
+}
+
+void EmulatedConsole::SetMotionParam(Common::ParamPackage param) {
+    motion_params = param;
+    ReloadInput();
+}
+
+void EmulatedConsole::SetMotion(Input::CallbackStatus callback) {
+    std::lock_guard lock{mutex};
+    auto& raw_status = console.motion_values.raw_status;
+    auto& emulated = console.motion_values.emulated;
+
+    raw_status = TransformToMotion(callback);
+    emulated.SetAcceleration(Common::Vec3f{
+        raw_status.accel.x.value,
+        raw_status.accel.y.value,
+        raw_status.accel.z.value,
+    });
+    emulated.SetGyroscope(Common::Vec3f{
+        raw_status.gyro.x.value,
+        raw_status.gyro.y.value,
+        raw_status.gyro.z.value,
+    });
+    emulated.UpdateRotation(raw_status.delta_timestamp);
+    emulated.UpdateOrientation(raw_status.delta_timestamp);
+
+    if (is_configuring) {
+        TriggerOnChange(ConsoleTriggerType::Motion);
+        return;
+    }
+
+    auto& motion = console.motion_state;
+    motion.accel = emulated.GetAcceleration();
+    motion.gyro = emulated.GetGyroscope();
+    motion.rotation = emulated.GetGyroscope();
+    motion.orientation = emulated.GetOrientation();
+    motion.quaternion = emulated.GetQuaternion();
+    motion.is_at_rest = emulated.IsMoving(motion_sensitivity);
+
+    TriggerOnChange(ConsoleTriggerType::Motion);
+}
+
+void EmulatedConsole::SetTouch(Input::CallbackStatus callback, [[maybe_unused]] std::size_t index) {
+    if (index >= console.touch_values.size()) {
+        return;
+    }
+    std::lock_guard lock{mutex};
+
+    console.touch_values[index] = TransformToTouch(callback);
+
+    if (is_configuring) {
+        TriggerOnChange(ConsoleTriggerType::Touch);
+        return;
+    }
+
+    console.touch_state[index] = {
+        .position = {console.touch_values[index].x.value, console.touch_values[index].y.value},
+        .id = console.touch_values[index].id,
+        .pressed = console.touch_values[index].pressed.value,
+    };
+
+    TriggerOnChange(ConsoleTriggerType::Touch);
+}
+
+ConsoleMotionValues EmulatedConsole::GetMotionValues() const {
+    return console.motion_values;
+}
+
+TouchValues EmulatedConsole::GetTouchValues() const {
+    return console.touch_values;
+}
+
+ConsoleMotion EmulatedConsole::GetMotion() const {
+    return console.motion_state;
+}
+
+TouchFingerState EmulatedConsole::GetTouch() const {
+    return console.touch_state;
+}
+
+void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) {
+    for (const std::pair<int, ConsoleUpdateCallback> poller_pair : callback_list) {
+        const ConsoleUpdateCallback& poller = poller_pair.second;
+        if (poller.on_change) {
+            poller.on_change(type);
+        }
+    }
+}
+
+int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) {
+    std::lock_guard lock{mutex};
+    callback_list.insert_or_assign(last_callback_key, update_callback);
+    return last_callback_key++;
+}
+
+void EmulatedConsole::DeleteCallback(int key) {
+    std::lock_guard lock{mutex};
+    if (!callback_list.contains(key)) {
+        LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
+        return;
+    }
+    callback_list.erase(key);
+}
+} // namespace Core::HID
diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h
new file mode 100644
index 0000000000..d9e275042c
--- /dev/null
+++ b/src/core/hid/emulated_console.h
@@ -0,0 +1,142 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <functional>
+#include <mutex>
+#include <unordered_map>
+
+#include "common/input.h"
+#include "common/param_package.h"
+#include "common/point.h"
+#include "common/quaternion.h"
+#include "common/settings.h"
+#include "common/vector_math.h"
+#include "core/hid/hid_types.h"
+#include "core/hid/motion_input.h"
+
+namespace Core::HID {
+
+struct ConsoleMotionInfo {
+    Input::MotionStatus raw_status;
+    MotionInput emulated{};
+};
+
+using ConsoleMotionDevices = std::unique_ptr<Input::InputDevice>;
+using TouchDevices = std::array<std::unique_ptr<Input::InputDevice>, 16>;
+
+using ConsoleMotionParams = Common::ParamPackage;
+using TouchParams = std::array<Common::ParamPackage, 16>;
+
+using ConsoleMotionValues = ConsoleMotionInfo;
+using TouchValues = std::array<Input::TouchStatus, 16>;
+
+struct TouchFinger {
+    u64_le last_touch{};
+    Common::Point<float> position{};
+    u32_le id{};
+    bool pressed{};
+    Core::HID::TouchAttribute attribute{};
+};
+
+struct ConsoleMotion {
+    bool is_at_rest{};
+    Common::Vec3f accel{};
+    Common::Vec3f gyro{};
+    Common::Vec3f rotation{};
+    std::array<Common::Vec3f, 3> orientation{};
+    Common::Quaternion<f32> quaternion{};
+};
+
+using TouchFingerState = std::array<TouchFinger, 16>;
+
+struct ConsoleStatus {
+    // Data from input_common
+    ConsoleMotionValues motion_values{};
+    TouchValues touch_values{};
+
+    // Data for Nintendo devices;
+    ConsoleMotion motion_state{};
+    TouchFingerState touch_state{};
+};
+
+enum class ConsoleTriggerType {
+    Motion,
+    Touch,
+    All,
+};
+
+struct ConsoleUpdateCallback {
+    std::function<void(ConsoleTriggerType)> on_change;
+};
+
+class EmulatedConsole {
+public:
+    /**
+     * TODO: Write description
+     *
+     * @param npad_id_type
+     */
+    explicit EmulatedConsole();
+    ~EmulatedConsole();
+
+    YUZU_NON_COPYABLE(EmulatedConsole);
+    YUZU_NON_MOVEABLE(EmulatedConsole);
+
+    void ReloadFromSettings();
+    void ReloadInput();
+    void UnloadInput();
+
+    void EnableConfiguration();
+    void DisableConfiguration();
+    bool IsConfiguring() const;
+    void SaveCurrentConfig();
+    void RestoreConfig();
+
+    Common::ParamPackage GetMotionParam() const;
+
+    void SetMotionParam(Common::ParamPackage param);
+
+    ConsoleMotionValues GetMotionValues() const;
+    TouchValues GetTouchValues() const;
+
+    ConsoleMotion GetMotion() const;
+    TouchFingerState GetTouch() const;
+
+    int SetCallback(ConsoleUpdateCallback update_callback);
+    void DeleteCallback(int key);
+
+private:
+    /**
+     * Sets the status of a button. Applies toggle properties to the output.
+     *
+     * @param A CallbackStatus and a button index number
+     */
+    void SetMotion(Input::CallbackStatus callback);
+    void SetTouch(Input::CallbackStatus callback, std::size_t index);
+
+    /**
+     * Triggers a callback that something has changed
+     *
+     * @param Input type of the trigger
+     */
+    void TriggerOnChange(ConsoleTriggerType type);
+
+    bool is_configuring{false};
+    f32 motion_sensitivity{0.01f};
+
+    ConsoleMotionParams motion_params;
+    TouchParams touch_params;
+
+    ConsoleMotionDevices motion_devices;
+    TouchDevices touch_devices;
+
+    mutable std::mutex mutex;
+    std::unordered_map<int, ConsoleUpdateCallback> callback_list;
+    int last_callback_key = 0;
+    ConsoleStatus console;
+};
+
+} // namespace Core::HID
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
new file mode 100644
index 0000000000..4eb5d99bc3
--- /dev/null
+++ b/src/core/hid/emulated_controller.cpp
@@ -0,0 +1,745 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#include <fmt/format.h>
+
+#include "core/hid/emulated_controller.h"
+#include "core/hid/input_converter.h"
+
+namespace Core::HID {
+constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
+constexpr s32 HID_TRIGGER_MAX = 0x7fff;
+
+EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type(npad_id_type_) {}
+
+EmulatedController::~EmulatedController() = default;
+
+NpadType EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) {
+    switch (type) {
+    case Settings::ControllerType::ProController:
+        return NpadType::ProController;
+    case Settings::ControllerType::DualJoyconDetached:
+        return NpadType::JoyconDual;
+    case Settings::ControllerType::LeftJoycon:
+        return NpadType::JoyconLeft;
+    case Settings::ControllerType::RightJoycon:
+        return NpadType::JoyconRight;
+    case Settings::ControllerType::Handheld:
+        return NpadType::Handheld;
+    case Settings::ControllerType::GameCube:
+        return NpadType::GameCube;
+    default:
+        return NpadType::ProController;
+    }
+}
+
+Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type) {
+    switch (type) {
+    case NpadType::ProController:
+        return Settings::ControllerType::ProController;
+    case NpadType::JoyconDual:
+        return Settings::ControllerType::DualJoyconDetached;
+    case NpadType::JoyconLeft:
+        return Settings::ControllerType::LeftJoycon;
+    case NpadType::JoyconRight:
+        return Settings::ControllerType::RightJoycon;
+    case NpadType::Handheld:
+        return Settings::ControllerType::Handheld;
+    case NpadType::GameCube:
+        return Settings::ControllerType::GameCube;
+    default:
+        return Settings::ControllerType::ProController;
+    }
+}
+
+void EmulatedController::ReloadFromSettings() {
+    const auto player_index = NpadIdTypeToIndex(npad_id_type);
+    const auto& player = Settings::values.players.GetValue()[player_index];
+
+    for (std::size_t index = 0; index < player.buttons.size(); ++index) {
+        button_params[index] = Common::ParamPackage(player.buttons[index]);
+    }
+    for (std::size_t index = 0; index < player.analogs.size(); ++index) {
+        stick_params[index] = Common::ParamPackage(player.analogs[index]);
+    }
+    for (std::size_t index = 0; index < player.motions.size(); ++index) {
+        motion_params[index] = Common::ParamPackage(player.motions[index]);
+    }
+    ReloadInput();
+}
+
+void EmulatedController::ReloadInput() {
+    const auto player_index = NpadIdTypeToIndex(npad_id_type);
+    const auto& player = Settings::values.players.GetValue()[player_index];
+    const auto left_side = button_params[Settings::NativeButton::ZL];
+    const auto right_side = button_params[Settings::NativeButton::ZR];
+
+    std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
+                   button_params.begin() + Settings::NativeButton::BUTTON_NS_END,
+                   button_devices.begin(), Input::CreateDevice<Input::InputDevice>);
+    std::transform(stick_params.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
+                   stick_params.begin() + Settings::NativeAnalog::STICK_HID_END,
+                   stick_devices.begin(), Input::CreateDevice<Input::InputDevice>);
+    std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
+                   motion_params.begin() + Settings::NativeMotion::MOTION_HID_END,
+                   motion_devices.begin(), Input::CreateDevice<Input::InputDevice>);
+
+    trigger_devices[0] =
+        Input::CreateDevice<Input::InputDevice>(button_params[Settings::NativeButton::ZL]);
+    trigger_devices[1] =
+        Input::CreateDevice<Input::InputDevice>(button_params[Settings::NativeButton::ZR]);
+
+    controller.colors_state.left = {
+        .body = player.body_color_left,
+        .button = player.button_color_left,
+    };
+
+    controller.colors_state.right = {
+        .body = player.body_color_right,
+        .button = player.button_color_right,
+    };
+
+    controller.colors_state.fullkey = controller.colors_state.left;
+
+    battery_devices[0] = Input::CreateDevice<Input::InputDevice>(left_side);
+    battery_devices[1] = Input::CreateDevice<Input::InputDevice>(right_side);
+
+    for (std::size_t index = 0; index < button_devices.size(); ++index) {
+        if (!button_devices[index]) {
+            continue;
+        }
+        Input::InputCallback button_callback{
+            [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }};
+        button_devices[index]->SetCallback(button_callback);
+    }
+
+    for (std::size_t index = 0; index < stick_devices.size(); ++index) {
+        if (!stick_devices[index]) {
+            continue;
+        }
+        Input::InputCallback stick_callback{
+            [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }};
+        stick_devices[index]->SetCallback(stick_callback);
+    }
+
+    for (std::size_t index = 0; index < trigger_devices.size(); ++index) {
+        if (!trigger_devices[index]) {
+            continue;
+        }
+        Input::InputCallback trigger_callback{
+            [this, index](Input::CallbackStatus callback) { SetTrigger(callback, index); }};
+        trigger_devices[index]->SetCallback(trigger_callback);
+    }
+
+    for (std::size_t index = 0; index < battery_devices.size(); ++index) {
+        if (!battery_devices[index]) {
+            continue;
+        }
+        Input::InputCallback battery_callback{
+            [this, index](Input::CallbackStatus callback) { SetBattery(callback, index); }};
+        battery_devices[index]->SetCallback(battery_callback);
+    }
+
+    for (std::size_t index = 0; index < motion_devices.size(); ++index) {
+        if (!motion_devices[index]) {
+            continue;
+        }
+        Input::InputCallback motion_callback{
+            [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }};
+        motion_devices[index]->SetCallback(motion_callback);
+    }
+
+    SetNpadType(MapSettingsTypeToNPad(player.controller_type));
+
+    if (player.connected) {
+        Connect();
+    } else {
+        Disconnect();
+    }
+}
+
+void EmulatedController::UnloadInput() {
+    for (auto& button : button_devices) {
+        button.reset();
+    }
+    for (auto& stick : stick_devices) {
+        stick.reset();
+    }
+    for (auto& motion : motion_devices) {
+        motion.reset();
+    }
+    for (auto& trigger : trigger_devices) {
+        trigger.reset();
+    }
+    for (auto& battery : battery_devices) {
+        battery.reset();
+    }
+}
+
+void EmulatedController::EnableConfiguration() {
+    is_configuring = true;
+    SaveCurrentConfig();
+}
+
+void EmulatedController::DisableConfiguration() {
+    is_configuring = false;
+}
+
+bool EmulatedController::IsConfiguring() const {
+    return is_configuring;
+}
+
+void EmulatedController::SaveCurrentConfig() {
+    if (!is_configuring) {
+        return;
+    }
+
+    const auto player_index = NpadIdTypeToIndex(npad_id_type);
+    auto& player = Settings::values.players.GetValue()[player_index];
+
+    for (std::size_t index = 0; index < player.buttons.size(); ++index) {
+        player.buttons[index] = button_params[index].Serialize();
+    }
+    for (std::size_t index = 0; index < player.analogs.size(); ++index) {
+        player.analogs[index] = stick_params[index].Serialize();
+    }
+    for (std::size_t index = 0; index < player.motions.size(); ++index) {
+        player.motions[index] = motion_params[index].Serialize();
+    }
+}
+
+void EmulatedController::RestoreConfig() {
+    if (!is_configuring) {
+        return;
+    }
+    ReloadFromSettings();
+}
+
+std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices() const {
+    std::vector<Common::ParamPackage> devices;
+    for (const auto& param : button_params) {
+        if (!param.Has("engine")) {
+            continue;
+        }
+        const auto devices_it = std::find_if(
+            devices.begin(), devices.end(), [param](const Common::ParamPackage param_) {
+                return param.Get("engine", "") == param_.Get("engine", "") &&
+                       param.Get("guid", "") == param_.Get("guid", "") &&
+                       param.Get("port", "") == param_.Get("port", "");
+            });
+        if (devices_it != devices.end()) {
+            continue;
+        }
+        Common::ParamPackage device{};
+        device.Set("engine", param.Get("engine", ""));
+        device.Set("guid", param.Get("guid", ""));
+        device.Set("port", param.Get("port", ""));
+        devices.push_back(device);
+    }
+
+    for (const auto& param : stick_params) {
+        if (!param.Has("engine")) {
+            continue;
+        }
+        if (param.Get("engine", "") == "analog_from_button") {
+            continue;
+        }
+        const auto devices_it = std::find_if(
+            devices.begin(), devices.end(), [param](const Common::ParamPackage param_) {
+                return param.Get("engine", "") == param_.Get("engine", "") &&
+                       param.Get("guid", "") == param_.Get("guid", "") &&
+                       param.Get("port", "") == param_.Get("port", "");
+            });
+        if (devices_it != devices.end()) {
+            continue;
+        }
+        Common::ParamPackage device{};
+        device.Set("engine", param.Get("engine", ""));
+        device.Set("guid", param.Get("guid", ""));
+        device.Set("port", param.Get("port", ""));
+        devices.push_back(device);
+    }
+    return devices;
+}
+
+Common::ParamPackage EmulatedController::GetButtonParam(std::size_t index) const {
+    if (index >= button_params.size()) {
+        return {};
+    }
+    return button_params[index];
+}
+
+Common::ParamPackage EmulatedController::GetStickParam(std::size_t index) const {
+    if (index >= stick_params.size()) {
+        return {};
+    }
+    return stick_params[index];
+}
+
+Common::ParamPackage EmulatedController::GetMotionParam(std::size_t index) const {
+    if (index >= motion_params.size()) {
+        return {};
+    }
+    return motion_params[index];
+}
+
+void EmulatedController::SetButtonParam(std::size_t index, Common::ParamPackage param) {
+    if (index >= button_params.size()) {
+        return;
+    }
+    button_params[index] = param;
+    ReloadInput();
+}
+
+void EmulatedController::SetStickParam(std::size_t index, Common::ParamPackage param) {
+    if (index >= stick_params.size()) {
+        return;
+    }
+    stick_params[index] = param;
+    ReloadInput();
+}
+
+void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage param) {
+    if (index >= motion_params.size()) {
+        return;
+    }
+    motion_params[index] = param;
+    ReloadInput();
+}
+
+void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t index) {
+    if (index >= controller.button_values.size()) {
+        return;
+    }
+    std::lock_guard lock{mutex};
+    bool value_changed = false;
+    const auto new_status = TransformToButton(callback);
+    auto& current_status = controller.button_values[index];
+    current_status.toggle = new_status.toggle;
+
+    // Update button status with current
+    if (!current_status.toggle) {
+        current_status.locked = false;
+        if (current_status.value != new_status.value) {
+            current_status.value = new_status.value;
+            value_changed = true;
+        }
+    } else {
+        // Toggle button and lock status
+        if (new_status.value && !current_status.locked) {
+            current_status.locked = true;
+            current_status.value = !current_status.value;
+            value_changed = true;
+        }
+
+        // Unlock button ready for next press
+        if (!new_status.value && current_status.locked) {
+            current_status.locked = false;
+        }
+    }
+
+    if (!value_changed) {
+        return;
+    }
+
+    if (is_configuring) {
+        controller.npad_button_state.raw = NpadButton::None;
+        controller.debug_pad_button_state.raw = 0;
+        TriggerOnChange(ControllerTriggerType::Button);
+        return;
+    }
+
+    switch (index) {
+    case Settings::NativeButton::A:
+        controller.npad_button_state.a.Assign(current_status.value);
+        controller.debug_pad_button_state.a.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::B:
+        controller.npad_button_state.b.Assign(current_status.value);
+        controller.debug_pad_button_state.b.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::X:
+        controller.npad_button_state.x.Assign(current_status.value);
+        controller.debug_pad_button_state.x.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::Y:
+        controller.npad_button_state.y.Assign(current_status.value);
+        controller.debug_pad_button_state.y.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::LStick:
+        controller.npad_button_state.stick_l.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::RStick:
+        controller.npad_button_state.stick_r.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::L:
+        controller.npad_button_state.l.Assign(current_status.value);
+        controller.debug_pad_button_state.l.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::R:
+        controller.npad_button_state.r.Assign(current_status.value);
+        controller.debug_pad_button_state.r.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::ZL:
+        controller.npad_button_state.zl.Assign(current_status.value);
+        controller.debug_pad_button_state.zl.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::ZR:
+        controller.npad_button_state.zr.Assign(current_status.value);
+        controller.debug_pad_button_state.zr.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::Plus:
+        controller.npad_button_state.plus.Assign(current_status.value);
+        controller.debug_pad_button_state.plus.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::Minus:
+        controller.npad_button_state.minus.Assign(current_status.value);
+        controller.debug_pad_button_state.minus.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::DLeft:
+        controller.npad_button_state.left.Assign(current_status.value);
+        controller.debug_pad_button_state.d_left.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::DUp:
+        controller.npad_button_state.up.Assign(current_status.value);
+        controller.debug_pad_button_state.d_up.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::DRight:
+        controller.npad_button_state.right.Assign(current_status.value);
+        controller.debug_pad_button_state.d_right.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::DDown:
+        controller.npad_button_state.down.Assign(current_status.value);
+        controller.debug_pad_button_state.d_down.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::SL:
+        controller.npad_button_state.left_sl.Assign(current_status.value);
+        controller.npad_button_state.right_sl.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::SR:
+        controller.npad_button_state.left_sr.Assign(current_status.value);
+        controller.npad_button_state.right_sr.Assign(current_status.value);
+        break;
+    case Settings::NativeButton::Home:
+    case Settings::NativeButton::Screenshot:
+        break;
+    }
+    TriggerOnChange(ControllerTriggerType::Button);
+}
+
+void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t index) {
+    if (index >= controller.stick_values.size()) {
+        return;
+    }
+    std::lock_guard lock{mutex};
+    controller.stick_values[index] = TransformToStick(callback);
+
+    if (is_configuring) {
+        controller.analog_stick_state.left = {};
+        controller.analog_stick_state.right = {};
+        TriggerOnChange(ControllerTriggerType::Stick);
+        return;
+    }
+
+    const AnalogStickState stick{
+        .x = static_cast<s32>(controller.stick_values[index].x.value * HID_JOYSTICK_MAX),
+        .y = static_cast<s32>(controller.stick_values[index].y.value * HID_JOYSTICK_MAX),
+    };
+
+    switch (index) {
+    case Settings::NativeAnalog::LStick:
+        controller.analog_stick_state.left = stick;
+        controller.npad_button_state.stick_l_left.Assign(controller.stick_values[index].left);
+        controller.npad_button_state.stick_l_up.Assign(controller.stick_values[index].up);
+        controller.npad_button_state.stick_l_right.Assign(controller.stick_values[index].right);
+        controller.npad_button_state.stick_l_down.Assign(controller.stick_values[index].down);
+        break;
+    case Settings::NativeAnalog::RStick:
+        controller.analog_stick_state.right = stick;
+        controller.npad_button_state.stick_r_left.Assign(controller.stick_values[index].left);
+        controller.npad_button_state.stick_r_up.Assign(controller.stick_values[index].up);
+        controller.npad_button_state.stick_r_right.Assign(controller.stick_values[index].right);
+        controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down);
+        break;
+    }
+
+    TriggerOnChange(ControllerTriggerType::Stick);
+}
+
+void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t index) {
+    if (index >= controller.trigger_values.size()) {
+        return;
+    }
+    std::lock_guard lock{mutex};
+    controller.trigger_values[index] = TransformToTrigger(callback);
+
+    if (is_configuring) {
+        controller.gc_trigger_state.left = 0;
+        controller.gc_trigger_state.right = 0;
+        TriggerOnChange(ControllerTriggerType::Trigger);
+        return;
+    }
+
+    const auto trigger = controller.trigger_values[index];
+
+    switch (index) {
+    case Settings::NativeTrigger::LTrigger:
+        controller.gc_trigger_state.left = static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX);
+        controller.npad_button_state.zl.Assign(trigger.pressed);
+        break;
+    case Settings::NativeTrigger::RTrigger:
+        controller.gc_trigger_state.right =
+            static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX);
+        controller.npad_button_state.zr.Assign(trigger.pressed);
+        break;
+    }
+
+    TriggerOnChange(ControllerTriggerType::Trigger);
+}
+
+void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t index) {
+    if (index >= controller.motion_values.size()) {
+        return;
+    }
+    std::lock_guard lock{mutex};
+    auto& raw_status = controller.motion_values[index].raw_status;
+    auto& emulated = controller.motion_values[index].emulated;
+
+    raw_status = TransformToMotion(callback);
+    emulated.SetAcceleration(Common::Vec3f{
+        raw_status.accel.x.value,
+        raw_status.accel.y.value,
+        raw_status.accel.z.value,
+    });
+    emulated.SetGyroscope(Common::Vec3f{
+        raw_status.gyro.x.value,
+        raw_status.gyro.y.value,
+        raw_status.gyro.z.value,
+    });
+    emulated.UpdateRotation(raw_status.delta_timestamp);
+    emulated.UpdateOrientation(raw_status.delta_timestamp);
+
+    if (is_configuring) {
+        TriggerOnChange(ControllerTriggerType::Motion);
+        return;
+    }
+
+    auto& motion = controller.motion_state[index];
+    motion.accel = emulated.GetAcceleration();
+    motion.gyro = emulated.GetGyroscope();
+    motion.rotation = emulated.GetGyroscope();
+    motion.orientation = emulated.GetOrientation();
+    motion.is_at_rest = emulated.IsMoving(motion_sensitivity);
+
+    TriggerOnChange(ControllerTriggerType::Motion);
+}
+
+void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t index) {
+    if (index >= controller.battery_values.size()) {
+        return;
+    }
+    std::lock_guard lock{mutex};
+    controller.battery_values[index] = TransformToBattery(callback);
+
+    if (is_configuring) {
+        TriggerOnChange(ControllerTriggerType::Battery);
+        return;
+    }
+
+    bool is_charging = false;
+    bool is_powered = false;
+    BatteryLevel battery_level = 0;
+    switch (controller.battery_values[index]) {
+    case Input::BatteryLevel::Charging:
+        is_charging = true;
+        is_powered = true;
+        battery_level = 6;
+        break;
+    case Input::BatteryLevel::Medium:
+        battery_level = 6;
+        break;
+    case Input::BatteryLevel::Low:
+        battery_level = 4;
+        break;
+    case Input::BatteryLevel::Critical:
+        battery_level = 2;
+        break;
+    case Input::BatteryLevel::Empty:
+        battery_level = 0;
+        break;
+    case Input::BatteryLevel::Full:
+    default:
+        is_powered = true;
+        battery_level = 8;
+        break;
+    }
+
+    switch (index) {
+    case 0:
+        controller.battery_state.left = {
+            .is_powered = is_powered,
+            .is_charging = is_charging,
+            .battery_level = battery_level,
+        };
+        break;
+    case 1:
+        controller.battery_state.right = {
+            .is_powered = is_powered,
+            .is_charging = is_charging,
+            .battery_level = battery_level,
+        };
+        break;
+    case 2:
+        controller.battery_state.dual = {
+            .is_powered = is_powered,
+            .is_charging = is_charging,
+            .battery_level = battery_level,
+        };
+        break;
+    }
+    TriggerOnChange(ControllerTriggerType::Battery);
+}
+
+bool EmulatedController::SetVibration([[maybe_unused]] std::size_t device_index,
+                                      [[maybe_unused]] VibrationValue vibration) {
+    return false;
+}
+
+int EmulatedController::TestVibration(std::size_t device_index) {
+    return 1;
+}
+
+void EmulatedController::Connect() {
+    std::lock_guard lock{mutex};
+    if (is_connected) {
+        LOG_WARNING(Service_HID, "Tried to turn on a connected controller {}", npad_id_type);
+        return;
+    }
+    is_connected = true;
+    TriggerOnChange(ControllerTriggerType::Connected);
+}
+
+void EmulatedController::Disconnect() {
+    std::lock_guard lock{mutex};
+    if (!is_connected) {
+        LOG_WARNING(Service_HID, "Tried to turn off a disconnected controller {}", npad_id_type);
+        return;
+    }
+    is_connected = false;
+    TriggerOnChange(ControllerTriggerType::Disconnected);
+}
+
+bool EmulatedController::IsConnected() const {
+    return is_connected;
+}
+
+bool EmulatedController::IsVibrationEnabled() const {
+    return is_vibration_enabled;
+}
+
+NpadIdType EmulatedController::GetNpadIdType() const {
+    return npad_id_type;
+}
+
+NpadType EmulatedController::GetNpadType() const {
+    return npad_type;
+}
+
+void EmulatedController::SetNpadType(NpadType npad_type_) {
+    std::lock_guard lock{mutex};
+    if (npad_type == npad_type_) {
+        return;
+    }
+    npad_type = npad_type_;
+    TriggerOnChange(ControllerTriggerType::Type);
+}
+
+ButtonValues EmulatedController::GetButtonsValues() const {
+    return controller.button_values;
+}
+
+SticksValues EmulatedController::GetSticksValues() const {
+    return controller.stick_values;
+}
+
+TriggerValues EmulatedController::GetTriggersValues() const {
+    return controller.trigger_values;
+}
+
+ControllerMotionValues EmulatedController::GetMotionValues() const {
+    return controller.motion_values;
+}
+
+ColorValues EmulatedController::GetColorsValues() const {
+    return controller.color_values;
+}
+
+BatteryValues EmulatedController::GetBatteryValues() const {
+    return controller.battery_values;
+}
+
+NpadButtonState EmulatedController::GetNpadButtons() const {
+    if (is_configuring) {
+        return {};
+    }
+    return controller.npad_button_state;
+}
+
+DebugPadButton EmulatedController::GetDebugPadButtons() const {
+    if (is_configuring) {
+        return {};
+    }
+    return controller.debug_pad_button_state;
+}
+
+AnalogSticks EmulatedController::GetSticks() const {
+    if (is_configuring) {
+        return {};
+    }
+    return controller.analog_stick_state;
+}
+
+NpadGcTriggerState EmulatedController::GetTriggers() const {
+    if (is_configuring) {
+        return {};
+    }
+    return controller.gc_trigger_state;
+}
+
+MotionState EmulatedController::GetMotions() const {
+    return controller.motion_state;
+}
+
+ControllerColors EmulatedController::GetColors() const {
+    return controller.colors_state;
+}
+
+BatteryLevelState EmulatedController::GetBattery() const {
+    return controller.battery_state;
+}
+
+void EmulatedController::TriggerOnChange(ControllerTriggerType type) {
+    for (const std::pair<int, ControllerUpdateCallback> poller_pair : callback_list) {
+        const ControllerUpdateCallback& poller = poller_pair.second;
+        if (poller.on_change) {
+            poller.on_change(type);
+        }
+    }
+}
+
+int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) {
+    std::lock_guard lock{mutex};
+    callback_list.insert_or_assign(last_callback_key, update_callback);
+    return last_callback_key++;
+}
+
+void EmulatedController::DeleteCallback(int key) {
+    std::lock_guard lock{mutex};
+    if (!callback_list.contains(key)) {
+        LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
+        return;
+    }
+    callback_list.erase(key);
+}
+} // namespace Core::HID
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
new file mode 100644
index 0000000000..94db9b00be
--- /dev/null
+++ b/src/core/hid/emulated_controller.h
@@ -0,0 +1,232 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <functional>
+#include <mutex>
+#include <unordered_map>
+
+#include "common/input.h"
+#include "common/param_package.h"
+#include "common/point.h"
+#include "common/quaternion.h"
+#include "common/settings.h"
+#include "common/vector_math.h"
+#include "core/hid/hid_types.h"
+#include "core/hid/motion_input.h"
+
+namespace Core::HID {
+
+struct ControllerMotionInfo {
+    Input::MotionStatus raw_status;
+    MotionInput emulated{};
+};
+
+using ButtonDevices =
+    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeButton::NumButtons>;
+using StickDevices =
+    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeAnalog::NumAnalogs>;
+using ControllerMotionDevices =
+    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeMotion::NumMotions>;
+using TriggerDevices =
+    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
+using BatteryDevices = std::array<std::unique_ptr<Input::InputDevice>, 2>;
+
+using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
+using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
+using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>;
+using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>;
+using BatteryParams = std::array<Common::ParamPackage, 2>;
+
+using ButtonValues = std::array<Input::ButtonStatus, Settings::NativeButton::NumButtons>;
+using SticksValues = std::array<Input::StickStatus, Settings::NativeAnalog::NumAnalogs>;
+using TriggerValues = std::array<Input::TriggerStatus, Settings::NativeTrigger::NumTriggers>;
+using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>;
+using ColorValues = std::array<Input::BodyColorStatus, 3>;
+using BatteryValues = std::array<Input::BatteryStatus, 3>;
+using VibrationValues = std::array<Input::VibrationStatus, 2>;
+
+struct AnalogSticks {
+    AnalogStickState left;
+    AnalogStickState right;
+};
+
+struct ControllerColors {
+    NpadControllerColor fullkey;
+    NpadControllerColor left;
+    NpadControllerColor right;
+};
+
+struct BatteryLevelState {
+    NpadPowerInfo dual;
+    NpadPowerInfo left;
+    NpadPowerInfo right;
+};
+
+struct ControllerMotion {
+    bool is_at_rest;
+    Common::Vec3f accel{};
+    Common::Vec3f gyro{};
+    Common::Vec3f rotation{};
+    std::array<Common::Vec3f, 3> orientation{};
+};
+
+using MotionState = std::array<ControllerMotion, 2>;
+
+struct ControllerStatus {
+    // Data from input_common
+    ButtonValues button_values{};
+    SticksValues stick_values{};
+    ControllerMotionValues motion_values{};
+    TriggerValues trigger_values{};
+    ColorValues color_values{};
+    BatteryValues battery_values{};
+    VibrationValues vibration_values{};
+
+    // Data for Nintendo devices
+    NpadButtonState npad_button_state{};
+    DebugPadButton debug_pad_button_state{};
+    AnalogSticks analog_stick_state{};
+    MotionState motion_state{};
+    NpadGcTriggerState gc_trigger_state{};
+    ControllerColors colors_state{};
+    BatteryLevelState battery_state{};
+};
+enum class ControllerTriggerType {
+    Button,
+    Stick,
+    Trigger,
+    Motion,
+    Color,
+    Battery,
+    Vibration,
+    Connected,
+    Disconnected,
+    Type,
+    All,
+};
+
+struct ControllerUpdateCallback {
+    std::function<void(ControllerTriggerType)> on_change;
+};
+
+class EmulatedController {
+public:
+    /**
+     * TODO: Write description
+     *
+     * @param npad_id_type
+     */
+    explicit EmulatedController(NpadIdType npad_id_type_);
+    ~EmulatedController();
+
+    YUZU_NON_COPYABLE(EmulatedController);
+    YUZU_NON_MOVEABLE(EmulatedController);
+
+    static NpadType MapSettingsTypeToNPad(Settings::ControllerType type);
+    static Settings::ControllerType MapNPadToSettingsType(NpadType type);
+
+    /// Gets the NpadIdType for this controller.
+    NpadIdType GetNpadIdType() const;
+
+    /// Sets the NpadType for this controller.
+    void SetNpadType(NpadType npad_type_);
+
+    /// Gets the NpadType for this controller.
+    NpadType GetNpadType() const;
+
+    void Connect();
+    void Disconnect();
+
+    bool IsConnected() const;
+    bool IsVibrationEnabled() const;
+
+    void ReloadFromSettings();
+    void ReloadInput();
+    void UnloadInput();
+
+    void EnableConfiguration();
+    void DisableConfiguration();
+    bool IsConfiguring() const;
+    void SaveCurrentConfig();
+    void RestoreConfig();
+
+    std::vector<Common::ParamPackage> GetMappedDevices() const;
+
+    Common::ParamPackage GetButtonParam(std::size_t index) const;
+    Common::ParamPackage GetStickParam(std::size_t index) const;
+    Common::ParamPackage GetMotionParam(std::size_t index) const;
+
+    void SetButtonParam(std::size_t index, Common::ParamPackage param);
+    void SetStickParam(std::size_t index, Common::ParamPackage param);
+    void SetMotionParam(std::size_t index, Common::ParamPackage param);
+
+    ButtonValues GetButtonsValues() const;
+    SticksValues GetSticksValues() const;
+    TriggerValues GetTriggersValues() const;
+    ControllerMotionValues GetMotionValues() const;
+    ColorValues GetColorsValues() const;
+    BatteryValues GetBatteryValues() const;
+
+    NpadButtonState GetNpadButtons() const;
+    DebugPadButton GetDebugPadButtons() const;
+    AnalogSticks GetSticks() const;
+    NpadGcTriggerState GetTriggers() const;
+    MotionState GetMotions() const;
+    ControllerColors GetColors() const;
+    BatteryLevelState GetBattery() const;
+
+    bool SetVibration(std::size_t device_index, VibrationValue vibration);
+    int TestVibration(std::size_t device_index);
+
+    int SetCallback(ControllerUpdateCallback update_callback);
+    void DeleteCallback(int key);
+
+private:
+    /**
+     * Sets the status of a button. Applies toggle properties to the output.
+     *
+     * @param A CallbackStatus and a button index number
+     */
+    void SetButton(Input::CallbackStatus callback, std::size_t index);
+    void SetStick(Input::CallbackStatus callback, std::size_t index);
+    void SetTrigger(Input::CallbackStatus callback, std::size_t index);
+    void SetMotion(Input::CallbackStatus callback, std::size_t index);
+    void SetBattery(Input::CallbackStatus callback, std::size_t index);
+
+    /**
+     * Triggers a callback that something has changed
+     *
+     * @param Input type of the trigger
+     */
+    void TriggerOnChange(ControllerTriggerType type);
+
+    NpadIdType npad_id_type;
+    NpadType npad_type{NpadType::None};
+    bool is_connected{false};
+    bool is_configuring{false};
+    bool is_vibration_enabled{true};
+    f32 motion_sensitivity{0.01f};
+
+    ButtonParams button_params;
+    StickParams stick_params;
+    ControllerMotionParams motion_params;
+    TriggerParams trigger_params;
+    BatteryParams battery_params;
+
+    ButtonDevices button_devices;
+    StickDevices stick_devices;
+    ControllerMotionDevices motion_devices;
+    TriggerDevices trigger_devices;
+    BatteryDevices battery_devices;
+    // VibrationDevices vibration_devices;
+
+    mutable std::mutex mutex;
+    std::unordered_map<int, ControllerUpdateCallback> callback_list;
+    int last_callback_key = 0;
+    ControllerStatus controller;
+};
+
+} // namespace Core::HID
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
new file mode 100644
index 0000000000..3caf90714a
--- /dev/null
+++ b/src/core/hid/emulated_devices.cpp
@@ -0,0 +1,349 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#include <fmt/format.h>
+
+#include "core/hid/emulated_devices.h"
+#include "core/hid/input_converter.h"
+
+namespace Core::HID {
+
+EmulatedDevices::EmulatedDevices() {}
+
+EmulatedDevices::~EmulatedDevices() = default;
+
+void EmulatedDevices::ReloadFromSettings() {
+    const auto& mouse = Settings::values.mouse_buttons;
+
+    for (std::size_t index = 0; index < mouse.size(); ++index) {
+        mouse_button_params[index] = Common::ParamPackage(mouse[index]);
+    }
+    ReloadInput();
+}
+
+void EmulatedDevices::ReloadInput() {
+    std::transform(mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_BEGIN,
+                   mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_END,
+                   mouse_button_devices.begin(), Input::CreateDevice<Input::InputDevice>);
+
+    std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(),
+                   keyboard_devices.begin(), Input::CreateDeviceFromString<Input::InputDevice>);
+
+    std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(),
+                   keyboard_modifier_devices.begin(),
+                   Input::CreateDeviceFromString<Input::InputDevice>);
+
+    for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) {
+        if (!mouse_button_devices[index]) {
+            continue;
+        }
+        Input::InputCallback button_callback{
+            [this, index](Input::CallbackStatus callback) { SetMouseButton(callback, index); }};
+        mouse_button_devices[index]->SetCallback(button_callback);
+    }
+
+    for (std::size_t index = 0; index < keyboard_devices.size(); ++index) {
+        if (!keyboard_devices[index]) {
+            continue;
+        }
+        Input::InputCallback button_callback{
+            [this, index](Input::CallbackStatus callback) { SetKeyboardButton(callback, index); }};
+        keyboard_devices[index]->SetCallback(button_callback);
+    }
+
+    for (std::size_t index = 0; index < keyboard_modifier_devices.size(); ++index) {
+        if (!keyboard_modifier_devices[index]) {
+            continue;
+        }
+        Input::InputCallback button_callback{[this, index](Input::CallbackStatus callback) {
+            SetKeyboardModifier(callback, index);
+        }};
+        keyboard_modifier_devices[index]->SetCallback(button_callback);
+    }
+}
+
+void EmulatedDevices::UnloadInput() {
+    for (auto& button : mouse_button_devices) {
+        button.reset();
+    }
+    for (auto& button : keyboard_devices) {
+        button.reset();
+    }
+    for (auto& button : keyboard_modifier_devices) {
+        button.reset();
+    }
+}
+
+void EmulatedDevices::EnableConfiguration() {
+    is_configuring = true;
+    SaveCurrentConfig();
+}
+
+void EmulatedDevices::DisableConfiguration() {
+    is_configuring = false;
+}
+
+bool EmulatedDevices::IsConfiguring() const {
+    return is_configuring;
+}
+
+void EmulatedDevices::SaveCurrentConfig() {
+    if (!is_configuring) {
+        return;
+    }
+
+    auto& mouse = Settings::values.mouse_buttons;
+
+    for (std::size_t index = 0; index < mouse.size(); ++index) {
+        mouse[index] = mouse_button_params[index].Serialize();
+    }
+}
+
+void EmulatedDevices::RestoreConfig() {
+    if (!is_configuring) {
+        return;
+    }
+    ReloadFromSettings();
+}
+
+Common::ParamPackage EmulatedDevices::GetMouseButtonParam(std::size_t index) const {
+    if (index >= mouse_button_params.size()) {
+        return {};
+    }
+    return mouse_button_params[index];
+}
+
+void EmulatedDevices::SetButtonParam(std::size_t index, Common::ParamPackage param) {
+    if (index >= mouse_button_params.size()) {
+        return;
+    }
+    mouse_button_params[index] = param;
+    ReloadInput();
+}
+
+void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::size_t index) {
+    if (index >= device_status.keyboard_values.size()) {
+        return;
+    }
+    std::lock_guard lock{mutex};
+    bool value_changed = false;
+    const auto new_status = TransformToButton(callback);
+    auto& current_status = device_status.keyboard_values[index];
+    current_status.toggle = new_status.toggle;
+
+    // Update button status with current
+    if (!current_status.toggle) {
+        current_status.locked = false;
+        if (current_status.value != new_status.value) {
+            current_status.value = new_status.value;
+            value_changed = true;
+        }
+    } else {
+        // Toggle button and lock status
+        if (new_status.value && !current_status.locked) {
+            current_status.locked = true;
+            current_status.value = !current_status.value;
+            value_changed = true;
+        }
+
+        // Unlock button ready for next press
+        if (!new_status.value && current_status.locked) {
+            current_status.locked = false;
+        }
+    }
+
+    if (!value_changed) {
+        return;
+    }
+
+    if (is_configuring) {
+        TriggerOnChange(DeviceTriggerType::Keyboard);
+        return;
+    }
+
+    // TODO(german77): Do this properly
+    // switch (index) {
+    // case Settings::NativeKeyboard::A:
+    //    interface_status.keyboard_state.a.Assign(current_status.value);
+    //    break;
+    //    ....
+    //}
+
+    TriggerOnChange(DeviceTriggerType::Keyboard);
+}
+
+void EmulatedDevices::SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index) {
+    if (index >= device_status.keyboard_moddifier_values.size()) {
+        return;
+    }
+    std::lock_guard lock{mutex};
+    bool value_changed = false;
+    const auto new_status = TransformToButton(callback);
+    auto& current_status = device_status.keyboard_moddifier_values[index];
+    current_status.toggle = new_status.toggle;
+
+    // Update button status with current
+    if (!current_status.toggle) {
+        current_status.locked = false;
+        if (current_status.value != new_status.value) {
+            current_status.value = new_status.value;
+            value_changed = true;
+        }
+    } else {
+        // Toggle button and lock status
+        if (new_status.value && !current_status.locked) {
+            current_status.locked = true;
+            current_status.value = !current_status.value;
+            value_changed = true;
+        }
+
+        // Unlock button ready for next press
+        if (!new_status.value && current_status.locked) {
+            current_status.locked = false;
+        }
+    }
+
+    if (!value_changed) {
+        return;
+    }
+
+    if (is_configuring) {
+        TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
+        return;
+    }
+
+    switch (index) {
+    case Settings::NativeKeyboard::LeftControl:
+    case Settings::NativeKeyboard::RightControl:
+        device_status.keyboard_moddifier_state.control.Assign(current_status.value);
+        break;
+    case Settings::NativeKeyboard::LeftShift:
+    case Settings::NativeKeyboard::RightShift:
+        device_status.keyboard_moddifier_state.shift.Assign(current_status.value);
+        break;
+    case Settings::NativeKeyboard::LeftAlt:
+        device_status.keyboard_moddifier_state.left_alt.Assign(current_status.value);
+        break;
+    case Settings::NativeKeyboard::RightAlt:
+        device_status.keyboard_moddifier_state.right_alt.Assign(current_status.value);
+        break;
+    case Settings::NativeKeyboard::CapsLock:
+        device_status.keyboard_moddifier_state.caps_lock.Assign(current_status.value);
+        break;
+    case Settings::NativeKeyboard::ScrollLock:
+        device_status.keyboard_moddifier_state.scroll_lock.Assign(current_status.value);
+        break;
+    case Settings::NativeKeyboard::NumLock:
+        device_status.keyboard_moddifier_state.num_lock.Assign(current_status.value);
+        break;
+    }
+
+    TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
+}
+
+void EmulatedDevices::SetMouseButton(Input::CallbackStatus callback, std::size_t index) {
+    if (index >= device_status.mouse_button_values.size()) {
+        return;
+    }
+    std::lock_guard lock{mutex};
+    bool value_changed = false;
+    const auto new_status = TransformToButton(callback);
+    auto& current_status = device_status.mouse_button_values[index];
+    current_status.toggle = new_status.toggle;
+
+    // Update button status with current
+    if (!current_status.toggle) {
+        current_status.locked = false;
+        if (current_status.value != new_status.value) {
+            current_status.value = new_status.value;
+            value_changed = true;
+        }
+    } else {
+        // Toggle button and lock status
+        if (new_status.value && !current_status.locked) {
+            current_status.locked = true;
+            current_status.value = !current_status.value;
+            value_changed = true;
+        }
+
+        // Unlock button ready for next press
+        if (!new_status.value && current_status.locked) {
+            current_status.locked = false;
+        }
+    }
+
+    if (!value_changed) {
+        return;
+    }
+
+    if (is_configuring) {
+        TriggerOnChange(DeviceTriggerType::Mouse);
+        return;
+    }
+
+    switch (index) {
+    case Settings::NativeMouseButton::Left:
+        device_status.mouse_button_state.left.Assign(current_status.value);
+        break;
+    case Settings::NativeMouseButton::Right:
+        device_status.mouse_button_state.right.Assign(current_status.value);
+        break;
+    case Settings::NativeMouseButton::Middle:
+        device_status.mouse_button_state.middle.Assign(current_status.value);
+        break;
+    case Settings::NativeMouseButton::Forward:
+        device_status.mouse_button_state.forward.Assign(current_status.value);
+        break;
+    case Settings::NativeMouseButton::Back:
+        device_status.mouse_button_state.back.Assign(current_status.value);
+        break;
+    }
+
+    TriggerOnChange(DeviceTriggerType::Mouse);
+}
+
+MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const {
+    return device_status.mouse_button_values;
+}
+
+KeyboardKey EmulatedDevices::GetKeyboard() const {
+    return device_status.keyboard_state;
+}
+
+KeyboardModifier EmulatedDevices::GetKeyboardModifier() const {
+    return device_status.keyboard_moddifier_state;
+}
+
+MouseButton EmulatedDevices::GetMouseButtons() const {
+    return device_status.mouse_button_state;
+}
+
+MousePosition EmulatedDevices::GetMousePosition() const {
+    return device_status.mouse_position_state;
+}
+
+void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) {
+    for (const std::pair<int, InterfaceUpdateCallback> poller_pair : callback_list) {
+        const InterfaceUpdateCallback& poller = poller_pair.second;
+        if (poller.on_change) {
+            poller.on_change(type);
+        }
+    }
+}
+
+int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) {
+    std::lock_guard lock{mutex};
+    callback_list.insert_or_assign(last_callback_key, update_callback);
+    return last_callback_key++;
+}
+
+void EmulatedDevices::DeleteCallback(int key) {
+    std::lock_guard lock{mutex};
+    if (!callback_list.contains(key)) {
+        LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
+        return;
+    }
+    callback_list.erase(key);
+}
+} // namespace Core::HID
diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h
new file mode 100644
index 0000000000..6f728eff55
--- /dev/null
+++ b/src/core/hid/emulated_devices.h
@@ -0,0 +1,137 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <functional>
+#include <mutex>
+#include <unordered_map>
+
+#include "common/input.h"
+#include "common/param_package.h"
+#include "common/settings.h"
+#include "core/hid/hid_types.h"
+#include "core/hid/motion_input.h"
+
+namespace Core::HID {
+
+using KeyboardDevices =
+    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeKeyboard::NumKeyboardKeys>;
+using KeyboardModifierDevices =
+    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeKeyboard::NumKeyboardMods>;
+using MouseButtonDevices =
+    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeMouseButton::NumMouseButtons>;
+
+using MouseButtonParams =
+    std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons>;
+
+using KeyboardValues = std::array<Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardKeys>;
+using KeyboardModifierValues =
+    std::array<Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardMods>;
+using MouseButtonValues =
+    std::array<Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>;
+
+struct MousePosition {
+    s32 x;
+    s32 y;
+    s32 delta_wheel_x;
+    s32 delta_wheel_y;
+};
+
+struct DeviceStatus {
+    // Data from input_common
+    KeyboardValues keyboard_values{};
+    KeyboardModifierValues keyboard_moddifier_values{};
+    MouseButtonValues mouse_button_values{};
+
+    // Data for Nintendo devices
+    KeyboardKey keyboard_state{};
+    KeyboardModifier keyboard_moddifier_state{};
+    MouseButton mouse_button_state{};
+    MousePosition mouse_position_state{};
+};
+
+enum class DeviceTriggerType {
+    Keyboard,
+    KeyboardModdifier,
+    Mouse,
+};
+
+struct InterfaceUpdateCallback {
+    std::function<void(DeviceTriggerType)> on_change;
+};
+
+class EmulatedDevices {
+public:
+    /**
+     * TODO: Write description
+     *
+     * @param npad_id_type
+     */
+    explicit EmulatedDevices();
+    ~EmulatedDevices();
+
+    YUZU_NON_COPYABLE(EmulatedDevices);
+    YUZU_NON_MOVEABLE(EmulatedDevices);
+
+    void ReloadFromSettings();
+    void ReloadInput();
+    void UnloadInput();
+
+    void EnableConfiguration();
+    void DisableConfiguration();
+    bool IsConfiguring() const;
+    void SaveCurrentConfig();
+    void RestoreConfig();
+
+    std::vector<Common::ParamPackage> GetMappedDevices() const;
+
+    Common::ParamPackage GetMouseButtonParam(std::size_t index) const;
+
+    void SetButtonParam(std::size_t index, Common::ParamPackage param);
+
+    KeyboardValues GetKeyboardValues() const;
+    KeyboardModifierValues GetKeyboardModdifierValues() const;
+    MouseButtonValues GetMouseButtonsValues() const;
+
+    KeyboardKey GetKeyboard() const;
+    KeyboardModifier GetKeyboardModifier() const;
+    MouseButton GetMouseButtons() const;
+    MousePosition GetMousePosition() const;
+
+    int SetCallback(InterfaceUpdateCallback update_callback);
+    void DeleteCallback(int key);
+
+private:
+    /**
+     * Sets the status of a button. Applies toggle properties to the output.
+     *
+     * @param A CallbackStatus and a button index number
+     */
+    void SetKeyboardButton(Input::CallbackStatus callback, std::size_t index);
+    void SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index);
+    void SetMouseButton(Input::CallbackStatus callback, std::size_t index);
+
+    /**
+     * Triggers a callback that something has changed
+     *
+     * @param Input type of the trigger
+     */
+    void TriggerOnChange(DeviceTriggerType type);
+
+    bool is_configuring{false};
+
+    MouseButtonParams mouse_button_params;
+
+    KeyboardDevices keyboard_devices;
+    KeyboardModifierDevices keyboard_modifier_devices;
+    MouseButtonDevices mouse_button_devices;
+
+    mutable std::mutex mutex;
+    std::unordered_map<int, InterfaceUpdateCallback> callback_list;
+    int last_callback_key = 0;
+    DeviceStatus device_status;
+};
+
+} // namespace Core::HID
diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp
new file mode 100644
index 0000000000..ee76db1106
--- /dev/null
+++ b/src/core/hid/hid_core.cpp
@@ -0,0 +1,144 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/assert.h"
+#include "core/hid/hid_core.h"
+
+namespace Core::HID {
+
+HIDCore::HIDCore()
+    : player_1{std::make_unique<EmulatedController>(NpadIdType::Player1)},
+      player_2{std::make_unique<EmulatedController>(NpadIdType::Player2)},
+      player_3{std::make_unique<EmulatedController>(NpadIdType::Player3)},
+      player_4{std::make_unique<EmulatedController>(NpadIdType::Player4)},
+      player_5{std::make_unique<EmulatedController>(NpadIdType::Player5)},
+      player_6{std::make_unique<EmulatedController>(NpadIdType::Player6)},
+      player_7{std::make_unique<EmulatedController>(NpadIdType::Player7)},
+      player_8{std::make_unique<EmulatedController>(NpadIdType::Player8)},
+      other{std::make_unique<EmulatedController>(NpadIdType::Other)},
+      handheld{std::make_unique<EmulatedController>(NpadIdType::Handheld)},
+      console{std::make_unique<EmulatedConsole>()}, devices{std::make_unique<EmulatedDevices>()} {}
+
+HIDCore::~HIDCore() = default;
+
+EmulatedController* HIDCore::GetEmulatedController(NpadIdType npad_id_type) {
+    switch (npad_id_type) {
+    case NpadIdType::Player1:
+        return player_1.get();
+    case NpadIdType::Player2:
+        return player_2.get();
+    case NpadIdType::Player3:
+        return player_3.get();
+    case NpadIdType::Player4:
+        return player_4.get();
+    case NpadIdType::Player5:
+        return player_5.get();
+    case NpadIdType::Player6:
+        return player_6.get();
+    case NpadIdType::Player7:
+        return player_7.get();
+    case NpadIdType::Player8:
+        return player_8.get();
+    case NpadIdType::Other:
+        return other.get();
+    case NpadIdType::Handheld:
+        return handheld.get();
+    case NpadIdType::Invalid:
+    default:
+        UNREACHABLE_MSG("Invalid NpadIdType={}", npad_id_type);
+        return nullptr;
+    }
+}
+
+const EmulatedController* HIDCore::GetEmulatedController(NpadIdType npad_id_type) const {
+    switch (npad_id_type) {
+    case NpadIdType::Player1:
+        return player_1.get();
+    case NpadIdType::Player2:
+        return player_2.get();
+    case NpadIdType::Player3:
+        return player_3.get();
+    case NpadIdType::Player4:
+        return player_4.get();
+    case NpadIdType::Player5:
+        return player_5.get();
+    case NpadIdType::Player6:
+        return player_6.get();
+    case NpadIdType::Player7:
+        return player_7.get();
+    case NpadIdType::Player8:
+        return player_8.get();
+    case NpadIdType::Other:
+        return other.get();
+    case NpadIdType::Handheld:
+        return handheld.get();
+    case NpadIdType::Invalid:
+    default:
+        UNREACHABLE_MSG("Invalid NpadIdType={}", npad_id_type);
+        return nullptr;
+    }
+}
+EmulatedConsole* HIDCore::GetEmulatedConsole() {
+    return console.get();
+}
+
+const EmulatedConsole* HIDCore::GetEmulatedConsole() const {
+    return console.get();
+}
+
+EmulatedDevices* HIDCore::GetEmulatedDevices() {
+    return devices.get();
+}
+
+const EmulatedDevices* HIDCore::GetEmulatedDevices() const {
+    return devices.get();
+}
+
+EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) {
+    return GetEmulatedController(IndexToNpadIdType(index));
+}
+
+const EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) const {
+    return GetEmulatedController(IndexToNpadIdType(index));
+}
+
+void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) {
+    supported_style_tag.raw = style_tag.raw;
+}
+
+NpadStyleTag HIDCore::GetSupportedStyleTag() const {
+    return supported_style_tag;
+}
+
+void HIDCore::ReloadInputDevices() {
+    player_1->ReloadFromSettings();
+    player_2->ReloadFromSettings();
+    player_3->ReloadFromSettings();
+    player_4->ReloadFromSettings();
+    player_5->ReloadFromSettings();
+    player_6->ReloadFromSettings();
+    player_7->ReloadFromSettings();
+    player_8->ReloadFromSettings();
+    other->ReloadFromSettings();
+    handheld->ReloadFromSettings();
+    console->ReloadFromSettings();
+    devices->ReloadFromSettings();
+}
+
+void HIDCore::UnloadInputDevices() {
+    player_1->UnloadInput();
+    player_2->UnloadInput();
+    player_3->UnloadInput();
+    player_4->UnloadInput();
+    player_5->UnloadInput();
+    player_6->UnloadInput();
+    player_7->UnloadInput();
+    player_8->UnloadInput();
+    other->UnloadInput();
+    handheld->UnloadInput();
+    console->UnloadInput();
+    devices->UnloadInput();
+}
+
+} // namespace Core::HID
diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h
new file mode 100644
index 0000000000..f11f48b617
--- /dev/null
+++ b/src/core/hid/hid_core.h
@@ -0,0 +1,60 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+
+#include "core/hid/emulated_console.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/emulated_devices.h"
+
+namespace Core::HID {
+
+class HIDCore {
+public:
+    explicit HIDCore();
+    ~HIDCore();
+
+    YUZU_NON_COPYABLE(HIDCore);
+    YUZU_NON_MOVEABLE(HIDCore);
+
+    EmulatedController* GetEmulatedController(NpadIdType npad_id_type);
+    const EmulatedController* GetEmulatedController(NpadIdType npad_id_type) const;
+
+    EmulatedController* GetEmulatedControllerByIndex(std::size_t index);
+    const EmulatedController* GetEmulatedControllerByIndex(std::size_t index) const;
+
+    EmulatedConsole* GetEmulatedConsole();
+    const EmulatedConsole* GetEmulatedConsole() const;
+
+    EmulatedDevices* GetEmulatedDevices();
+    const EmulatedDevices* GetEmulatedDevices() const;
+
+    void SetSupportedStyleTag(NpadStyleTag style_tag);
+    NpadStyleTag GetSupportedStyleTag() const;
+
+    // Reloads all input devices from settings
+    void ReloadInputDevices();
+
+    // Removes all callbacks from input common
+    void UnloadInputDevices();
+
+private:
+    std::unique_ptr<EmulatedController> player_1;
+    std::unique_ptr<EmulatedController> player_2;
+    std::unique_ptr<EmulatedController> player_3;
+    std::unique_ptr<EmulatedController> player_4;
+    std::unique_ptr<EmulatedController> player_5;
+    std::unique_ptr<EmulatedController> player_6;
+    std::unique_ptr<EmulatedController> player_7;
+    std::unique_ptr<EmulatedController> player_8;
+    std::unique_ptr<EmulatedController> other;
+    std::unique_ptr<EmulatedController> handheld;
+    std::unique_ptr<EmulatedConsole> console;
+    std::unique_ptr<EmulatedDevices> devices;
+    NpadStyleTag supported_style_tag;
+};
+
+} // namespace Core::HID

From 967cca10ff5721cc942f557c3e0a20c07f5aa45e Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 19:44:34 -0500
Subject: [PATCH 19/88] core: Register HID

---
 src/core/core.cpp | 14 +++++++++++---
 src/core/core.h   | 10 ++++++++++
 src/yuzu/main.cpp |  5 ++++-
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/src/core/core.cpp b/src/core/core.cpp
index 07448fd295..473ab9f817 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -27,6 +27,7 @@
 #include "core/file_sys/vfs_concat.h"
 #include "core/file_sys/vfs_real.h"
 #include "core/hardware_interrupt_manager.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/kernel/k_process.h"
 #include "core/hle/kernel/k_scheduler.h"
 #include "core/hle/kernel/kernel.h"
@@ -126,7 +127,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
 
 struct System::Impl {
     explicit Impl(System& system)
-        : kernel{system}, fs_controller{system}, memory{system},
+        : kernel{system}, fs_controller{system}, memory{system}, hid_core{},
           cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {}
 
     SystemResultStatus Run() {
@@ -391,6 +392,7 @@ struct System::Impl {
     std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
     std::unique_ptr<Core::DeviceMemory> device_memory;
     Core::Memory::Memory memory;
+    Core::HID::HIDCore hid_core;
     CpuManager cpu_manager;
     std::atomic_bool is_powered_on{};
     bool exit_lock = false;
@@ -615,6 +617,14 @@ const Kernel::KernelCore& System::Kernel() const {
     return impl->kernel;
 }
 
+HID::HIDCore& System::HIDCore() {
+    return impl->hid_core;
+}
+
+const HID::HIDCore& System::HIDCore() const {
+    return impl->hid_core;
+}
+
 Timing::CoreTiming& System::CoreTiming() {
     return impl->core_timing;
 }
@@ -825,8 +835,6 @@ void System::ApplySettings() {
     if (IsPoweredOn()) {
         Renderer().RefreshBaseSettings();
     }
-
-    Service::HID::ReloadInputDevices();
 }
 
 } // namespace Core
diff --git a/src/core/core.h b/src/core/core.h
index 01bc0a2c77..5a031efb0b 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -89,6 +89,10 @@ namespace Core::Hardware {
 class InterruptManager;
 }
 
+namespace Core::HID {
+class HIDCore;
+}
+
 namespace Core {
 
 class ARM_Interface;
@@ -285,6 +289,12 @@ public:
     /// Provides a constant reference to the kernel instance.
     [[nodiscard]] const Kernel::KernelCore& Kernel() const;
 
+    /// Gets a mutable reference to the HID interface
+    [[nodiscard]] HID::HIDCore& HIDCore();
+
+    /// Gets an immutable reference to the HID interface.
+    [[nodiscard]] const HID::HIDCore& HIDCore() const;
+
     /// Provides a reference to the internal PerfStats instance.
     [[nodiscard]] Core::PerfStats& GetPerfStats();
 
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 7f36f6e2f4..19cb5313fd 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -26,6 +26,7 @@
 #include "core/frontend/applets/controller.h"
 #include "core/frontend/applets/general_frontend.h"
 #include "core/frontend/applets/software_keyboard.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/service/acc/profile_manager.h"
 #include "core/hle/service/am/applet_ae.h"
 #include "core/hle/service/am/applet_oe.h"
@@ -227,6 +228,8 @@ GMainWindow::GMainWindow()
     ConnectMenuEvents();
     ConnectWidgetEvents();
 
+    Core::System::GetInstance().HIDCore().ReloadInputDevices();
+
     const auto branch_name = std::string(Common::g_scm_branch);
     const auto description = std::string(Common::g_scm_desc);
     const auto build_id = std::string(Common::g_build_id);
@@ -2969,7 +2972,7 @@ void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_vie
 QString GMainWindow::GetTasStateDescription() const {
     auto [tas_status, current_tas_frame, total_tas_frames] = input_subsystem->GetTas()->GetStatus();
     switch (tas_status) {
-    case InputCommon::TasInput::TasState::Running:
+    case InputCommon::TasInput::TasState::Running :
         return tr("TAS state: Running %1/%2").arg(current_tas_frame).arg(total_tas_frames);
     case InputCommon::TasInput::TasState::Recording:
         return tr("TAS state: Recording %1").arg(total_tas_frames);

From c405a19b73fa1e084918a2d39336363cd0f8b567 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 19:47:45 -0500
Subject: [PATCH 20/88] yuzu: Update frontend

---
 src/yuzu/configuration/config.cpp             |   1 -
 src/yuzu/configuration/configure_input.cpp    |  16 +-
 src/yuzu/configuration/configure_input.h      |   3 +-
 .../configuration/configure_input_player.cpp  | 928 +++++++-----------
 .../configuration/configure_input_player.h    |  49 +-
 .../configuration/configure_input_player.ui   |  10 -
 .../configure_input_player_widget.cpp         | 597 ++++++-----
 .../configure_input_player_widget.h           | 133 +--
 .../configuration/configure_motion_touch.cpp  |   4 +-
 .../configure_mouse_advanced.cpp              |  57 +-
 .../configuration/configure_mouse_advanced.h  |   8 +-
 .../configure_touch_from_button.cpp           |  27 +-
 .../configure_touch_from_button.h             |   5 -
 13 files changed, 825 insertions(+), 1013 deletions(-)

diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 2b670ddfd0..56af075072 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -11,7 +11,6 @@
 #include "core/hle/service/acc/profile_manager.h"
 #include "core/hle/service/hid/controllers/npad.h"
 #include "input_common/main.h"
-#include "input_common/udp/client.h"
 #include "yuzu/configuration/config.h"
 
 namespace FS = Common::FS;
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 1599299db2..61513865f4 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -73,7 +73,7 @@ ConfigureInput::ConfigureInput(Core::System& system_, QWidget* parent)
 
 ConfigureInput::~ConfigureInput() = default;
 
-void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
+void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, Core::System& system,
                                 std::size_t max_players) {
     player_controllers = {
         new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem, profiles.get(),
@@ -184,22 +184,8 @@ QList<QWidget*> ConfigureInput::GetSubTabs() const {
 void ConfigureInput::ApplyConfiguration() {
     for (auto* controller : player_controllers) {
         controller->ApplyConfiguration();
-        controller->TryDisconnectSelectedController();
     }
 
-    // This emulates a delay between disconnecting and reconnecting controllers as some games
-    // do not respond to a change in controller type if it was instantaneous.
-    using namespace std::chrono_literals;
-    std::this_thread::sleep_for(150ms);
-
-    for (auto* controller : player_controllers) {
-        controller->TryConnectSelectedController();
-    }
-
-    // This emulates a delay between disconnecting and reconnecting controllers as some games
-    // do not respond to a change in controller type if it was instantaneous.
-    std::this_thread::sleep_for(150ms);
-
     advanced->ApplyConfiguration();
 
     const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h
index 4cafa3dab7..6e5edad589 100644
--- a/src/yuzu/configuration/configure_input.h
+++ b/src/yuzu/configuration/configure_input.h
@@ -42,7 +42,8 @@ public:
     ~ConfigureInput() override;
 
     /// Initializes the input dialog with the given input subsystem.
-    void Initialize(InputCommon::InputSubsystem* input_subsystem_, std::size_t max_players = 8);
+    void Initialize(InputCommon::InputSubsystem* input_subsystem_, Core::System& system,
+                    std::size_t max_players = 8);
 
     /// Save all button configurations to settings file.
     void ApplyConfiguration();
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 09f0b219bf..adc9706f14 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -13,9 +13,11 @@
 #include <QTimer>
 #include "common/param_package.h"
 #include "core/core.h"
-#include "core/hle/service/hid/controllers/npad.h"
-#include "core/hle/service/hid/hid.h"
-#include "core/hle/service/sm/sm.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
+#include "core/hid/hid_types.h"
+#include "input_common/drivers/keyboard.h"
+#include "input_common/drivers/mouse.h"
 #include "input_common/main.h"
 #include "ui_configure_input_player.h"
 #include "yuzu/bootmanager.h"
@@ -26,8 +28,6 @@
 #include "yuzu/configuration/input_profiles.h"
 #include "yuzu/util/limitable_input_dialog.h"
 
-using namespace Service::HID;
-
 const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM>
     ConfigureInputPlayer::analog_sub_buttons{{
         "up",
@@ -40,31 +40,8 @@ namespace {
 
 constexpr std::size_t HANDHELD_INDEX = 8;
 
-void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index,
-                      bool connected, Core::System& system) {
-    if (!system.IsPoweredOn()) {
-        return;
-    }
-    Service::SM::ServiceManager& sm = system.ServiceManager();
-
-    auto& npad = sm.GetService<Hid>("hid")->GetAppletResource()->GetController<Controller_NPad>(
-        HidController::NPad);
-
-    npad.UpdateControllerAt(npad.MapSettingsTypeToNPad(controller_type), npad_index, connected);
-}
-
 QString GetKeyName(int key_code) {
     switch (key_code) {
-    case Qt::LeftButton:
-        return QObject::tr("Click 0");
-    case Qt::RightButton:
-        return QObject::tr("Click 1");
-    case Qt::MiddleButton:
-        return QObject::tr("Click 2");
-    case Qt::BackButton:
-        return QObject::tr("Click 3");
-    case Qt::ForwardButton:
-        return QObject::tr("Click 4");
     case Qt::Key_Shift:
         return QObject::tr("Shift");
     case Qt::Key_Control:
@@ -94,95 +71,26 @@ void SetAnalogParam(const Common::ParamPackage& input_param, Common::ParamPackag
     }
     analog_param.Set(button_name, input_param.Serialize());
 }
+} // namespace
 
-QString ButtonToText(const Common::ParamPackage& param) {
+QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
     if (!param.Has("engine")) {
         return QObject::tr("[not set]");
     }
 
+    // Retrieve the names from Qt
     if (param.Get("engine", "") == "keyboard") {
         const QString button_str = GetKeyName(param.Get("code", 0));
         const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
         return QObject::tr("%1%2").arg(toggle, button_str);
     }
 
-    if (param.Get("engine", "") == "gcpad") {
-        if (param.Has("axis")) {
-            const QString axis_str = QString::fromStdString(param.Get("axis", ""));
-            const QString direction_str = QString::fromStdString(param.Get("direction", ""));
-
-            return QObject::tr("GC Axis %1%2").arg(axis_str, direction_str);
-        }
-        if (param.Has("button")) {
-            const QString button_str = QString::number(int(std::log2(param.Get("button", 0))));
-            return QObject::tr("GC Button %1").arg(button_str);
-        }
-        return GetKeyName(param.Get("code", 0));
-    }
-
-    if (param.Get("engine", "") == "tas") {
-        if (param.Has("axis")) {
-            const QString axis_str = QString::fromStdString(param.Get("axis", ""));
-
-            return QObject::tr("TAS Axis %1").arg(axis_str);
-        }
-        if (param.Has("button")) {
-            const QString button_str = QString::number(int(std::log2(param.Get("button", 0))));
-            return QObject::tr("TAS Btn %1").arg(button_str);
-        }
-        return GetKeyName(param.Get("code", 0));
-    }
-
-    if (param.Get("engine", "") == "cemuhookudp") {
-        if (param.Has("pad_index")) {
-            const QString motion_str = QString::fromStdString(param.Get("pad_index", ""));
-            return QObject::tr("Motion %1").arg(motion_str);
-        }
-        return GetKeyName(param.Get("code", 0));
-    }
-
-    if (param.Get("engine", "") == "sdl") {
-        if (param.Has("hat")) {
-            const QString hat_str = QString::fromStdString(param.Get("hat", ""));
-            const QString direction_str = QString::fromStdString(param.Get("direction", ""));
-
-            return QObject::tr("Hat %1 %2").arg(hat_str, direction_str);
-        }
-
-        if (param.Has("axis")) {
-            const QString axis_str = QString::fromStdString(param.Get("axis", ""));
-            const QString direction_str = QString::fromStdString(param.Get("direction", ""));
-
-            return QObject::tr("Axis %1%2").arg(axis_str, direction_str);
-        }
-
-        if (param.Has("button")) {
-            const QString button_str = QString::fromStdString(param.Get("button", ""));
-            const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
-
-            return QObject::tr("%1Button %2").arg(toggle, button_str);
-        }
-
-        if (param.Has("motion")) {
-            return QObject::tr("SDL Motion");
-        }
-
-        return {};
-    }
-
-    if (param.Get("engine", "") == "mouse") {
-        if (param.Has("button")) {
-            const QString button_str = QString::number(int(param.Get("button", 0)));
-            const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
-            return QObject::tr("%1Click %2").arg(toggle, button_str);
-        }
-        return GetKeyName(param.Get("code", 0));
-    }
-
-    return QObject::tr("[unknown]");
+    std::string button_name = input_subsystem->GetButtonName(param);
+    return QString::fromStdString(button_name);
 }
 
-QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) {
+QString ConfigureInputPlayer::AnalogToText(const Common::ParamPackage& param,
+                                           const std::string& dir) {
     if (!param.Has("engine")) {
         return QObject::tr("[not set]");
     }
@@ -191,39 +99,39 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir)
         return ButtonToText(Common::ParamPackage{param.Get(dir, "")});
     }
 
+    if (!param.Has("axis_x") || !param.Has("axis_y")) {
+        return QObject::tr("[unknown]");
+    }
+
     const auto engine_str = param.Get("engine", "");
     const QString axis_x_str = QString::fromStdString(param.Get("axis_x", ""));
     const QString axis_y_str = QString::fromStdString(param.Get("axis_y", ""));
     const bool invert_x = param.Get("invert_x", "+") == "-";
     const bool invert_y = param.Get("invert_y", "+") == "-";
-    if (engine_str == "sdl" || engine_str == "gcpad" || engine_str == "mouse" ||
-        engine_str == "tas") {
-        if (dir == "modifier") {
-            return QObject::tr("[unused]");
-        }
 
-        if (dir == "left") {
-            const QString invert_x_str = QString::fromStdString(invert_x ? "+" : "-");
-            return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str);
-        }
-        if (dir == "right") {
-            const QString invert_x_str = QString::fromStdString(invert_x ? "-" : "+");
-            return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str);
-        }
-        if (dir == "up") {
-            const QString invert_y_str = QString::fromStdString(invert_y ? "-" : "+");
-            return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str);
-        }
-        if (dir == "down") {
-            const QString invert_y_str = QString::fromStdString(invert_y ? "+" : "-");
-            return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str);
-        }
-
-        return {};
+    if (dir == "modifier") {
+        return QObject::tr("[unused]");
     }
+
+    if (dir == "left") {
+        const QString invert_x_str = QString::fromStdString(invert_x ? "+" : "-");
+        return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str);
+    }
+    if (dir == "right") {
+        const QString invert_x_str = QString::fromStdString(invert_x ? "-" : "+");
+        return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str);
+    }
+    if (dir == "up") {
+        const QString invert_y_str = QString::fromStdString(invert_y ? "-" : "+");
+        return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str);
+    }
+    if (dir == "down") {
+        const QString invert_y_str = QString::fromStdString(invert_y ? "+" : "-");
+        return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str);
+    }
+
     return QObject::tr("[unknown]");
 }
-} // namespace
 
 ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index,
                                            QWidget* bottom_row,
@@ -234,6 +142,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
       debug(debug), input_subsystem{input_subsystem_}, profiles(profiles_),
       timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()),
       bottom_row(bottom_row), system{system_} {
+
+    emulated_controller = system_.HIDCore().GetEmulatedControllerByIndex(player_index);
+    emulated_controller->EnableConfiguration();
     ui->setupUi(this);
 
     setFocusPolicy(Qt::ClickFocus);
@@ -275,31 +186,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
     analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup};
     analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange};
 
-    const auto ConfigureButtonClick = [&](QPushButton* button, std::size_t button_id,
-                                          Common::ParamPackage* param, int default_val,
-                                          InputCommon::Polling::DeviceType type) {
-        connect(button, &QPushButton::clicked, [=, this] {
-            HandleClick(
-                button, button_id,
-                [=, this](Common::ParamPackage params) {
-                    // Workaround for ZL & ZR for analog triggers like on XBOX
-                    // controllers. Analog triggers (from controllers like the XBOX
-                    // controller) would not work due to a different range of their
-                    // signals (from 0 to 255 on analog triggers instead of -32768 to
-                    // 32768 on analog joysticks). The SDL driver misinterprets analog
-                    // triggers as analog joysticks.
-                    // TODO: reinterpret the signal range for analog triggers to map the
-                    // values correctly. This is required for the correct emulation of
-                    // the analog triggers of the GameCube controller.
-                    if (button == ui->buttonZL || button == ui->buttonZR) {
-                        params.Set("direction", "+");
-                        params.Set("threshold", "0.5");
-                    }
-                    *param = std::move(params);
-                },
-                type);
-        });
-    };
+    ui->controllerFrame->SetController(emulated_controller);
 
     for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
         auto* const button = button_map[button_id];
@@ -308,34 +195,52 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
             continue;
         }
 
-        ConfigureButtonClick(button_map[button_id], button_id, &buttons_param[button_id],
-                             Config::default_buttons[button_id],
-                             InputCommon::Polling::DeviceType::Button);
+        connect(button, &QPushButton::clicked, [=, this] {
+            HandleClick(
+                button, button_id,
+                [=, this](Common::ParamPackage params) {
+                    emulated_controller->SetButtonParam(button_id, params);
+                },
+                InputCommon::Polling::InputType::Button);
+        });
 
         button->setContextMenuPolicy(Qt::CustomContextMenu);
         connect(button, &QPushButton::customContextMenuRequested,
                 [=, this](const QPoint& menu_location) {
                     QMenu context_menu;
+                    Common::ParamPackage param = emulated_controller->GetButtonParam(button_id);
                     context_menu.addAction(tr("Clear"), [&] {
-                        buttons_param[button_id].Clear();
+                        emulated_controller->SetButtonParam(button_id, {});
                         button_map[button_id]->setText(tr("[not set]"));
                     });
-                    if (buttons_param[button_id].Has("toggle")) {
+                    if (param.Has("button") || param.Has("hat")) {
                         context_menu.addAction(tr("Toggle button"), [&] {
-                            const bool toggle_value =
-                                !buttons_param[button_id].Get("toggle", false);
-                            buttons_param[button_id].Set("toggle", toggle_value);
-                            button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
+                            const bool toggle_value = !param.Get("toggle", false);
+                            param.Set("toggle", toggle_value);
+                            button_map[button_id]->setText(ButtonToText(param));
+                            emulated_controller->SetButtonParam(button_id, param);
+                        });
+                        context_menu.addAction(tr("Invert button"), [&] {
+                            const bool toggle_value = !param.Get("inverted", false);
+                            param.Set("inverted", toggle_value);
+                            button_map[button_id]->setText(ButtonToText(param));
+                            emulated_controller->SetButtonParam(button_id, param);
                         });
                     }
-                    if (buttons_param[button_id].Has("threshold")) {
+                    if (param.Has("axis")) {
+                        context_menu.addAction(tr("Invert axis"), [&] {
+                            const bool toggle_value = !(param.Get("invert", "+") == "-");
+                            param.Set("invert", toggle_value ? "-" : "+");
+                            button_map[button_id]->setText(ButtonToText(param));
+                            emulated_controller->SetButtonParam(button_id, param);
+                        });
                         context_menu.addAction(tr("Set threshold"), [&] {
-                            const int button_threshold = static_cast<int>(
-                                buttons_param[button_id].Get("threshold", 0.5f) * 100.0f);
+                            const int button_threshold =
+                                static_cast<int>(param.Get("threshold", 0.5f) * 100.0f);
                             const int new_threshold = QInputDialog::getInt(
                                 this, tr("Set threshold"), tr("Choose a value between 0% and 100%"),
                                 button_threshold, 0, 100);
-                            buttons_param[button_id].Set("threshold", new_threshold / 100.0f);
+                            param.Set("threshold", new_threshold / 100.0f);
 
                             if (button_id == Settings::NativeButton::ZL) {
                                 ui->sliderZLThreshold->setValue(new_threshold);
@@ -343,11 +248,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
                             if (button_id == Settings::NativeButton::ZR) {
                                 ui->sliderZRThreshold->setValue(new_threshold);
                             }
+                            emulated_controller->SetButtonParam(button_id, param);
                         });
                     }
-
                     context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
-                    ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
                 });
     }
 
@@ -357,9 +261,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
             continue;
         }
 
-        ConfigureButtonClick(motion_map[motion_id], motion_id, &motions_param[motion_id],
-                             Config::default_motions[motion_id],
-                             InputCommon::Polling::DeviceType::Motion);
+        connect(button, &QPushButton::clicked, [=, this] {
+            HandleClick(
+                button, motion_id,
+                [=, this](Common::ParamPackage params) {
+                    emulated_controller->SetMotionParam(motion_id, params);
+                },
+                InputCommon::Polling::InputType::Motion);
+        });
 
         button->setContextMenuPolicy(Qt::CustomContextMenu);
 
@@ -367,7 +276,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
                 [=, this](const QPoint& menu_location) {
                     QMenu context_menu;
                     context_menu.addAction(tr("Clear"), [&] {
-                        motions_param[motion_id].Clear();
+                        emulated_controller->SetMotionParam(motion_id, {});
                         motion_map[motion_id]->setText(tr("[not set]"));
                     });
                     context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location));
@@ -375,16 +284,22 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
     }
 
     connect(ui->sliderZLThreshold, &QSlider::valueChanged, [=, this] {
-        if (buttons_param[Settings::NativeButton::ZL].Has("threshold")) {
+        Common::ParamPackage param =
+            emulated_controller->GetButtonParam(Settings::NativeButton::ZL);
+        if (param.Has("threshold")) {
             const auto slider_value = ui->sliderZLThreshold->value();
-            buttons_param[Settings::NativeButton::ZL].Set("threshold", slider_value / 100.0f);
+            param.Set("threshold", slider_value / 100.0f);
+            emulated_controller->SetButtonParam(Settings::NativeButton::ZL, param);
         }
     });
 
     connect(ui->sliderZRThreshold, &QSlider::valueChanged, [=, this] {
-        if (buttons_param[Settings::NativeButton::ZR].Has("threshold")) {
+        Common::ParamPackage param =
+            emulated_controller->GetButtonParam(Settings::NativeButton::ZR);
+        if (param.Has("threshold")) {
             const auto slider_value = ui->sliderZRThreshold->value();
-            buttons_param[Settings::NativeButton::ZR].Set("threshold", slider_value / 100.0f);
+            param.Set("threshold", slider_value / 100.0f);
+            emulated_controller->SetButtonParam(Settings::NativeButton::ZR, param);
         }
     });
 
@@ -412,45 +327,45 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
                 HandleClick(
                     analog_map_buttons[analog_id][sub_button_id], analog_id,
                     [=, this](const Common::ParamPackage& params) {
-                        SetAnalogParam(params, analogs_param[analog_id],
-                                       analog_sub_buttons[sub_button_id]);
+                        Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
+                        SetAnalogParam(params, param, analog_sub_buttons[sub_button_id]);
+                        emulated_controller->SetStickParam(analog_id, param);
                     },
-                    InputCommon::Polling::DeviceType::AnalogPreferred);
+                    InputCommon::Polling::InputType::Stick);
             });
 
             analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
 
-            connect(
-                analog_button, &QPushButton::customContextMenuRequested,
-                [=, this](const QPoint& menu_location) {
-                    QMenu context_menu;
-                    context_menu.addAction(tr("Clear"), [&] {
-                        analogs_param[analog_id].Clear();
-                        analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));
+            connect(analog_button, &QPushButton::customContextMenuRequested,
+                    [=, this](const QPoint& menu_location) {
+                        QMenu context_menu;
+                        Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
+                        context_menu.addAction(tr("Clear"), [&] {
+                            emulated_controller->SetStickParam(analog_id, {});
+                            analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));
+                        });
+                        context_menu.addAction(tr("Invert axis"), [&] {
+                            if (sub_button_id == 2 || sub_button_id == 3) {
+                                const bool invert_value = param.Get("invert_x", "+") == "-";
+                                const std::string invert_str = invert_value ? "+" : "-";
+                                param.Set("invert_x", invert_str);
+                                emulated_controller->SetStickParam(analog_id, param);
+                            }
+                            if (sub_button_id == 0 || sub_button_id == 1) {
+                                const bool invert_value = param.Get("invert_y", "+") == "-";
+                                const std::string invert_str = invert_value ? "+" : "-";
+                                param.Set("invert_y", invert_str);
+                                emulated_controller->SetStickParam(analog_id, param);
+                            }
+                            for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM;
+                                 ++sub_button_id) {
+                                analog_map_buttons[analog_id][sub_button_id]->setText(
+                                    AnalogToText(param, analog_sub_buttons[sub_button_id]));
+                            }
+                        });
+                        context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(
+                            menu_location));
                     });
-                    context_menu.addAction(tr("Invert axis"), [&] {
-                        if (sub_button_id == 2 || sub_button_id == 3) {
-                            const bool invert_value =
-                                analogs_param[analog_id].Get("invert_x", "+") == "-";
-                            const std::string invert_str = invert_value ? "+" : "-";
-                            analogs_param[analog_id].Set("invert_x", invert_str);
-                        }
-                        if (sub_button_id == 0 || sub_button_id == 1) {
-                            const bool invert_value =
-                                analogs_param[analog_id].Get("invert_y", "+") == "-";
-                            const std::string invert_str = invert_value ? "+" : "-";
-                            analogs_param[analog_id].Set("invert_y", invert_str);
-                        }
-                        for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM;
-                             ++sub_button_id) {
-                            analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText(
-                                analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
-                        }
-                    });
-                    context_menu.exec(
-                        analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(menu_location));
-                    ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
-                });
         }
 
         // Handle clicks for the modifier buttons as well.
@@ -458,9 +373,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
             HandleClick(
                 analog_map_modifier_button[analog_id], analog_id,
                 [=, this](const Common::ParamPackage& params) {
-                    analogs_param[analog_id].Set("modifier", params.Serialize());
+                    Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
+                    param.Set("modifier", params.Serialize());
+                    emulated_controller->SetStickParam(analog_id, param);
                 },
-                InputCommon::Polling::DeviceType::Button);
+                InputCommon::Polling::InputType::Button);
         });
 
         analog_map_modifier_button[analog_id]->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -468,18 +385,21 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
         connect(analog_map_modifier_button[analog_id], &QPushButton::customContextMenuRequested,
                 [=, this](const QPoint& menu_location) {
                     QMenu context_menu;
+                    Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
                     context_menu.addAction(tr("Clear"), [&] {
-                        analogs_param[analog_id].Set("modifier", "");
+                        param.Set("modifier", "");
                         analog_map_modifier_button[analog_id]->setText(tr("[not set]"));
+                        emulated_controller->SetStickParam(analog_id, param);
                     });
                     context_menu.addAction(tr("Toggle button"), [&] {
                         Common::ParamPackage modifier_param =
-                            Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")};
+                            Common::ParamPackage{param.Get("modifier", "")};
                         const bool toggle_value = !modifier_param.Get("toggle", false);
                         modifier_param.Set("toggle", toggle_value);
-                        analogs_param[analog_id].Set("modifier", modifier_param.Serialize());
+                        param.Set("modifier", modifier_param.Serialize());
                         analog_map_modifier_button[analog_id]->setText(
                             ButtonToText(modifier_param));
+                        emulated_controller->SetStickParam(analog_id, param);
                     });
                     context_menu.exec(
                         analog_map_modifier_button[analog_id]->mapToGlobal(menu_location));
@@ -487,37 +407,39 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
 
         connect(analog_map_range_spinbox[analog_id], qOverload<int>(&QSpinBox::valueChanged),
                 [=, this] {
+                    Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
                     const auto spinbox_value = analog_map_range_spinbox[analog_id]->value();
-                    analogs_param[analog_id].Set("range", spinbox_value / 100.0f);
-                    ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
+                    param.Set("range", spinbox_value / 100.0f);
+                    emulated_controller->SetStickParam(analog_id, param);
                 });
 
         connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] {
+            Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
             const auto slider_value = analog_map_deadzone_slider[analog_id]->value();
             analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value));
-            analogs_param[analog_id].Set("deadzone", slider_value / 100.0f);
-            ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
+            param.Set("deadzone", slider_value / 100.0f);
+            emulated_controller->SetStickParam(analog_id, param);
         });
 
         connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] {
+            Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
             const auto slider_value = analog_map_modifier_slider[analog_id]->value();
             analog_map_modifier_label[analog_id]->setText(
                 tr("Modifier Range: %1%").arg(slider_value));
-            analogs_param[analog_id].Set("modifier_scale", slider_value / 100.0f);
+            param.Set("modifier_scale", slider_value / 100.0f);
+            emulated_controller->SetStickParam(analog_id, param);
         });
     }
 
     // Player Connected checkbox
-    connect(ui->groupConnectedController, &QGroupBox::toggled, [this](bool checked) {
-        emit Connected(checked);
-        ui->controllerFrame->SetConnectedStatus(checked);
-    });
+    connect(ui->groupConnectedController, &QGroupBox::toggled,
+            [this](bool checked) { emit Connected(checked); });
 
     if (player_index == 0) {
         connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged),
                 [this](int index) {
                     emit HandheldStateChanged(GetControllerTypeFromIndex(index) ==
-                                              Settings::ControllerType::Handheld);
+                                              Core::HID::NpadType::Handheld);
                 });
     }
 
@@ -534,13 +456,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
         SetConnectableControllers();
     }
 
-    UpdateControllerIcon();
     UpdateControllerAvailableButtons();
     UpdateControllerEnabledButtons();
     UpdateControllerButtonNames();
     UpdateMotionButtons();
     connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) {
-        UpdateControllerIcon();
         UpdateControllerAvailableButtons();
         UpdateControllerEnabledButtons();
         UpdateControllerButtonNames();
@@ -560,13 +480,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
     connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
 
     connect(poll_timer.get(), &QTimer::timeout, [this] {
-        Common::ParamPackage params;
-        for (auto& poller : device_pollers) {
-            params = poller->GetNextInput();
-            if (params.Has("engine") && IsInputAcceptable(params)) {
-                SetPollingResult(params, false);
-                return;
-            }
+        const auto& params = input_subsystem->GetNextInput();
+        if (params.Has("engine") && IsInputAcceptable(params)) {
+            SetPollingResult(params, false);
+            return;
         }
     });
 
@@ -582,110 +499,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
             &ConfigureInputPlayer::SaveProfile);
 
     LoadConfiguration();
-    ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
-    ui->controllerFrame->SetConnectedStatus(ui->groupConnectedController->isChecked());
 }
 
-ConfigureInputPlayer::~ConfigureInputPlayer() = default;
+ConfigureInputPlayer::~ConfigureInputPlayer() {
+    emulated_controller->DisableConfiguration();
+};
 
 void ConfigureInputPlayer::ApplyConfiguration() {
-    auto& player = Settings::values.players.GetValue()[player_index];
-    auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons;
-    auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs;
-
-    std::transform(buttons_param.begin(), buttons_param.end(), buttons.begin(),
-                   [](const Common::ParamPackage& param) { return param.Serialize(); });
-    std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(),
-                   [](const Common::ParamPackage& param) { return param.Serialize(); });
-
-    if (debug) {
-        return;
-    }
-
-    auto& motions = player.motions;
-
-    std::transform(motions_param.begin(), motions_param.end(), motions.begin(),
-                   [](const Common::ParamPackage& param) { return param.Serialize(); });
-
-    // Apply configuration for handheld
-    if (player_index == 0) {
-        auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
-        const auto handheld_connected = handheld.connected;
-        handheld = player;
-        handheld.connected = handheld_connected;
-    }
-}
-
-void ConfigureInputPlayer::TryConnectSelectedController() {
-    auto& player = Settings::values.players.GetValue()[player_index];
-
-    const auto controller_type =
-        GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
-    const auto player_connected = ui->groupConnectedController->isChecked() &&
-                                  controller_type != Settings::ControllerType::Handheld;
-
-    // Connect Handheld depending on Player 1's controller configuration.
-    if (player_index == 0) {
-        auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
-        const auto handheld_connected = ui->groupConnectedController->isChecked() &&
-                                        controller_type == Settings::ControllerType::Handheld;
-        // Connect only if handheld is going from disconnected to connected
-        if (!handheld.connected && handheld_connected) {
-            UpdateController(controller_type, HANDHELD_INDEX, true, system);
-        }
-        handheld.connected = handheld_connected;
-    }
-
-    if (player.controller_type == controller_type && player.connected == player_connected) {
-        // Set vibration devices in the event that the input device has changed.
-        ConfigureVibration::SetVibrationDevices(player_index);
-        return;
-    }
-
-    player.controller_type = controller_type;
-    player.connected = player_connected;
-
-    ConfigureVibration::SetVibrationDevices(player_index);
-
-    if (!player.connected) {
-        return;
-    }
-
-    UpdateController(controller_type, player_index, true, system);
-}
-
-void ConfigureInputPlayer::TryDisconnectSelectedController() {
-    const auto& player = Settings::values.players.GetValue()[player_index];
-
-    const auto controller_type =
-        GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
-    const auto player_connected = ui->groupConnectedController->isChecked() &&
-                                  controller_type != Settings::ControllerType::Handheld;
-
-    // Disconnect Handheld depending on Player 1's controller configuration.
-    if (player_index == 0 && player.controller_type == Settings::ControllerType::Handheld) {
-        const auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
-        const auto handheld_connected = ui->groupConnectedController->isChecked() &&
-                                        controller_type == Settings::ControllerType::Handheld;
-        // Disconnect only if handheld is going from connected to disconnected
-        if (handheld.connected && !handheld_connected) {
-            UpdateController(controller_type, HANDHELD_INDEX, false, system);
-        }
-        return;
-    }
-
-    // Do not do anything if the controller configuration has not changed.
-    if (player.controller_type == controller_type && player.connected == player_connected) {
-        return;
-    }
-
-    // Do not disconnect if the controller is already disconnected
-    if (!player.connected) {
-        return;
-    }
-
-    // Disconnect the controller first.
-    UpdateController(controller_type, player_index, false, system);
+    emulated_controller->SaveCurrentConfig();
 }
 
 void ConfigureInputPlayer::showEvent(QShowEvent* event) {
@@ -710,34 +531,11 @@ void ConfigureInputPlayer::RetranslateUI() {
 }
 
 void ConfigureInputPlayer::LoadConfiguration() {
-    auto& player = Settings::values.players.GetValue()[player_index];
-    if (debug) {
-        std::transform(Settings::values.debug_pad_buttons.begin(),
-                       Settings::values.debug_pad_buttons.end(), buttons_param.begin(),
-                       [](const std::string& str) { return Common::ParamPackage(str); });
-        std::transform(Settings::values.debug_pad_analogs.begin(),
-                       Settings::values.debug_pad_analogs.end(), analogs_param.begin(),
-                       [](const std::string& str) { return Common::ParamPackage(str); });
-    } else {
-        std::transform(player.buttons.begin(), player.buttons.end(), buttons_param.begin(),
-                       [](const std::string& str) { return Common::ParamPackage(str); });
-        std::transform(player.analogs.begin(), player.analogs.end(), analogs_param.begin(),
-                       [](const std::string& str) { return Common::ParamPackage(str); });
-        std::transform(player.motions.begin(), player.motions.end(), motions_param.begin(),
-                       [](const std::string& str) { return Common::ParamPackage(str); });
-    }
-
     UpdateUI();
     UpdateInputDeviceCombobox();
-
-    if (debug) {
-        return;
-    }
-
-    ui->comboControllerType->setCurrentIndex(GetIndexFromControllerType(player.controller_type));
-    ui->groupConnectedController->setChecked(
-        player.connected ||
-        (player_index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected));
+    const int comboBoxIndex = GetIndexFromControllerType(emulated_controller->GetNpadType());
+    ui->comboControllerType->setCurrentIndex(comboBoxIndex);
+    ui->groupConnectedController->setChecked(emulated_controller->IsConnected());
 }
 
 void ConfigureInputPlayer::ConnectPlayer(bool connected) {
@@ -751,48 +549,63 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
         return;
     }
 
-    // Find the first button that isn't empty.
-    const auto button_param =
-        std::find_if(buttons_param.begin(), buttons_param.end(),
-                     [](const Common::ParamPackage param) { return param.Has("engine"); });
-    const bool buttons_empty = button_param == buttons_param.end();
-
-    const auto current_engine = button_param->Get("engine", "");
-    const auto current_guid = button_param->Get("guid", "");
-    const auto current_port = button_param->Get("port", "");
-
-    const bool is_keyboard_mouse = current_engine == "keyboard" || current_engine == "mouse";
-
+    const auto devices = emulated_controller->GetMappedDevices();
     UpdateInputDevices();
 
-    if (buttons_empty) {
+    if (devices.empty()) {
         return;
     }
 
-    const bool all_one_device =
-        std::all_of(buttons_param.begin(), buttons_param.end(),
-                    [current_engine, current_guid, current_port,
-                     is_keyboard_mouse](const Common::ParamPackage param) {
-                        if (is_keyboard_mouse) {
-                            return !param.Has("engine") || param.Get("engine", "") == "keyboard" ||
-                                   param.Get("engine", "") == "mouse";
-                        }
-                        return !param.Has("engine") || (param.Get("engine", "") == current_engine &&
-                                                        param.Get("guid", "") == current_guid &&
-                                                        param.Get("port", "") == current_port);
-                    });
+    if (devices.size() > 2) {
+        ui->comboDevices->setCurrentIndex(0);
+        return;
+    }
 
-    if (all_one_device) {
-        if (is_keyboard_mouse) {
-            ui->comboDevices->setCurrentIndex(1);
-            return;
-        }
+    const auto first_engine = devices[0].Get("engine", "");
+    const auto first_guid = devices[0].Get("guid", "");
+    const auto first_port = devices[0].Get("port", "");
+
+    if (devices.size() == 1) {
+        const auto devices_it =
+            std::find_if(input_devices.begin(), input_devices.end(),
+                         [first_engine, first_guid, first_port](const Common::ParamPackage param) {
+                             return param.Get("engine", "") == first_engine &&
+                                    param.Get("guid", "") == first_guid &&
+                                    param.Get("port", "") == first_port;
+                         });
+        const int device_index =
+            devices_it != input_devices.end()
+                ? static_cast<int>(std::distance(input_devices.begin(), devices_it))
+                : 0;
+        ui->comboDevices->setCurrentIndex(device_index);
+        return;
+    }
+
+    const auto second_engine = devices[1].Get("engine", "");
+    const auto second_guid = devices[1].Get("guid", "");
+    const auto second_port = devices[1].Get("port", "");
+
+    const bool is_keyboard_mouse = (first_engine == "keyboard" || first_engine == "mouse") &&
+                                   (second_engine == "keyboard" || second_engine == "mouse");
+
+    if (is_keyboard_mouse) {
+        ui->comboDevices->setCurrentIndex(2);
+        return;
+    }
+
+    const bool is_engine_equal = first_engine == second_engine;
+    const bool is_port_equal = first_port == second_port;
+
+    if (is_engine_equal && is_port_equal) {
         const auto devices_it = std::find_if(
             input_devices.begin(), input_devices.end(),
-            [current_engine, current_guid, current_port](const Common::ParamPackage param) {
-                return param.Get("class", "") == current_engine &&
-                       param.Get("guid", "") == current_guid &&
-                       param.Get("port", "") == current_port;
+            [first_engine, first_guid, second_guid, first_port](const Common::ParamPackage param) {
+                const bool is_guid_valid =
+                    (param.Get("guid", "") == first_guid &&
+                     param.Get("guid2", "") == second_guid) ||
+                    (param.Get("guid", "") == second_guid && param.Get("guid2", "") == first_guid);
+                return param.Get("engine", "") == first_engine && is_guid_valid &&
+                       param.Get("port", "") == first_port;
             });
         const int device_index =
             devices_it != input_devices.end()
@@ -814,8 +627,7 @@ void ConfigureInputPlayer::ClearAll() {
         if (button == nullptr) {
             continue;
         }
-
-        buttons_param[button_id].Clear();
+        emulated_controller->SetButtonParam(button_id, {});
     }
 
     for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
@@ -824,8 +636,7 @@ void ConfigureInputPlayer::ClearAll() {
             if (analog_button == nullptr) {
                 continue;
             }
-
-            analogs_param[analog_id].Clear();
+            emulated_controller->SetStickParam(analog_id, {});
         }
     }
 
@@ -834,8 +645,7 @@ void ConfigureInputPlayer::ClearAll() {
         if (motion_button == nullptr) {
             continue;
         }
-
-        motions_param[motion_id].Clear();
+        emulated_controller->SetMotionParam(motion_id, {});
     }
 
     UpdateUI();
@@ -844,26 +654,31 @@ void ConfigureInputPlayer::ClearAll() {
 
 void ConfigureInputPlayer::UpdateUI() {
     for (int button = 0; button < Settings::NativeButton::NumButtons; ++button) {
-        button_map[button]->setText(ButtonToText(buttons_param[button]));
+        const Common::ParamPackage param = emulated_controller->GetButtonParam(button);
+        button_map[button]->setText(ButtonToText(param));
     }
 
-    if (buttons_param[Settings::NativeButton::ZL].Has("threshold")) {
-        const int button_threshold = static_cast<int>(
-            buttons_param[Settings::NativeButton::ZL].Get("threshold", 0.5f) * 100.0f);
+    const Common::ParamPackage ZL_param =
+        emulated_controller->GetButtonParam(Settings::NativeButton::ZL);
+    if (ZL_param.Has("threshold")) {
+        const int button_threshold = static_cast<int>(ZL_param.Get("threshold", 0.5f) * 100.0f);
         ui->sliderZLThreshold->setValue(button_threshold);
     }
 
-    if (buttons_param[Settings::NativeButton::ZR].Has("threshold")) {
-        const int button_threshold = static_cast<int>(
-            buttons_param[Settings::NativeButton::ZR].Get("threshold", 0.5f) * 100.0f);
+    const Common::ParamPackage ZR_param =
+        emulated_controller->GetButtonParam(Settings::NativeButton::ZR);
+    if (ZR_param.Has("threshold")) {
+        const int button_threshold = static_cast<int>(ZR_param.Get("threshold", 0.5f) * 100.0f);
         ui->sliderZRThreshold->setValue(button_threshold);
     }
 
     for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
-        motion_map[motion_id]->setText(ButtonToText(motions_param[motion_id]));
+        const Common::ParamPackage param = emulated_controller->GetMotionParam(motion_id);
+        motion_map[motion_id]->setText(ButtonToText(param));
     }
 
     for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
+        const Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
         for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
             auto* const analog_button = analog_map_buttons[analog_id][sub_button_id];
 
@@ -871,12 +686,11 @@ void ConfigureInputPlayer::UpdateUI() {
                 continue;
             }
 
-            analog_button->setText(
-                AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
+            analog_button->setText(AnalogToText(param, analog_sub_buttons[sub_button_id]));
         }
 
         analog_map_modifier_button[analog_id]->setText(
-            ButtonToText(Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")}));
+            ButtonToText(Common::ParamPackage{param.Get("modifier", "")}));
 
         const auto deadzone_label = analog_map_deadzone_label[analog_id];
         const auto deadzone_slider = analog_map_deadzone_slider[analog_id];
@@ -887,26 +701,14 @@ void ConfigureInputPlayer::UpdateUI() {
         const auto range_spinbox = analog_map_range_spinbox[analog_id];
 
         int slider_value;
-        auto& param = analogs_param[analog_id];
-        const bool is_controller =
-            param.Get("engine", "") == "sdl" || param.Get("engine", "") == "gcpad" ||
-            param.Get("engine", "") == "mouse" || param.Get("engine", "") == "tas";
+        const bool is_controller = input_subsystem->IsController(param);
 
         if (is_controller) {
-            if (!param.Has("deadzone")) {
-                param.Set("deadzone", 0.1f);
-            }
-            slider_value = static_cast<int>(param.Get("deadzone", 0.1f) * 100);
+            slider_value = static_cast<int>(param.Get("deadzone", 0.15f) * 100);
             deadzone_label->setText(tr("Deadzone: %1%").arg(slider_value));
             deadzone_slider->setValue(slider_value);
-            if (!param.Has("range")) {
-                param.Set("range", 1.0f);
-            }
             range_spinbox->setValue(static_cast<int>(param.Get("range", 1.0f) * 100));
         } else {
-            if (!param.Has("modifier_scale")) {
-                param.Set("modifier_scale", 0.5f);
-            }
             slider_value = static_cast<int>(param.Get("modifier_scale", 0.5f) * 100);
             modifier_label->setText(tr("Modifier Range: %1%").arg(slider_value));
             modifier_slider->setValue(slider_value);
@@ -918,49 +720,48 @@ void ConfigureInputPlayer::UpdateUI() {
         modifier_label->setVisible(!is_controller);
         modifier_slider->setVisible(!is_controller);
         range_groupbox->setVisible(is_controller);
-        ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
     }
 }
 
 void ConfigureInputPlayer::SetConnectableControllers() {
     const auto add_controllers = [this](bool enable_all,
-                                        Controller_NPad::NpadStyleSet npad_style_set = {}) {
+                                        Core::HID::NpadStyleTag npad_style_set = {}) {
         index_controller_type_pairs.clear();
         ui->comboControllerType->clear();
 
         if (enable_all || npad_style_set.fullkey == 1) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Settings::ControllerType::ProController);
+                                                     Core::HID::NpadType::ProController);
             ui->comboControllerType->addItem(tr("Pro Controller"));
         }
 
         if (enable_all || npad_style_set.joycon_dual == 1) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Settings::ControllerType::DualJoyconDetached);
+                                                     Core::HID::NpadType::JoyconDual);
             ui->comboControllerType->addItem(tr("Dual Joycons"));
         }
 
         if (enable_all || npad_style_set.joycon_left == 1) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Settings::ControllerType::LeftJoycon);
+                                                     Core::HID::NpadType::JoyconLeft);
             ui->comboControllerType->addItem(tr("Left Joycon"));
         }
 
         if (enable_all || npad_style_set.joycon_right == 1) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Settings::ControllerType::RightJoycon);
+                                                     Core::HID::NpadType::JoyconRight);
             ui->comboControllerType->addItem(tr("Right Joycon"));
         }
 
         if (player_index == 0 && (enable_all || npad_style_set.handheld == 1)) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Settings::ControllerType::Handheld);
+                                                     Core::HID::NpadType::Handheld);
             ui->comboControllerType->addItem(tr("Handheld"));
         }
 
         if (enable_all || npad_style_set.gamecube == 1) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Settings::ControllerType::GameCube);
+                                                     Core::HID::NpadType::GameCube);
             ui->comboControllerType->addItem(tr("GameCube Controller"));
         }
     };
@@ -970,27 +771,22 @@ void ConfigureInputPlayer::SetConnectableControllers() {
         return;
     }
 
-    Service::SM::ServiceManager& sm = system.ServiceManager();
-
-    auto& npad = sm.GetService<Hid>("hid")->GetAppletResource()->GetController<Controller_NPad>(
-        HidController::NPad);
-
-    add_controllers(false, npad.GetSupportedStyleSet());
+    add_controllers(false, system.HIDCore().GetSupportedStyleTag());
 }
 
-Settings::ControllerType ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const {
+Core::HID::NpadType ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const {
     const auto it =
         std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(),
                      [index](const auto& pair) { return pair.first == index; });
 
     if (it == index_controller_type_pairs.end()) {
-        return Settings::ControllerType::ProController;
+        return Core::HID::NpadType::ProController;
     }
 
     return it->second;
 }
 
-int ConfigureInputPlayer::GetIndexFromControllerType(Settings::ControllerType type) const {
+int ConfigureInputPlayer::GetIndexFromControllerType(Core::HID::NpadType type) const {
     const auto it =
         std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(),
                      [type](const auto& pair) { return pair.second == type; });
@@ -1005,52 +801,15 @@ int ConfigureInputPlayer::GetIndexFromControllerType(Settings::ControllerType ty
 void ConfigureInputPlayer::UpdateInputDevices() {
     input_devices = input_subsystem->GetInputDevices();
     ui->comboDevices->clear();
-    for (auto& device : input_devices) {
-        const std::string display = device.Get("display", "Unknown");
-        ui->comboDevices->addItem(QString::fromStdString(display), {});
-        if (display == "TAS") {
-            device.Set("pad", static_cast<u8>(player_index));
-        }
+    for (auto device : input_devices) {
+        ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {});
     }
 }
 
-void ConfigureInputPlayer::UpdateControllerIcon() {
-    // We aren't using Qt's built in theme support here since we aren't drawing an icon (and its
-    // "nonstandard" to use an image through the icon support)
-    const QString stylesheet = [this] {
-        switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) {
-        case Settings::ControllerType::ProController:
-            return QStringLiteral("image: url(:/controller/pro_controller%0)");
-        case Settings::ControllerType::DualJoyconDetached:
-            return QStringLiteral("image: url(:/controller/dual_joycon%0)");
-        case Settings::ControllerType::LeftJoycon:
-            return QStringLiteral("image: url(:/controller/single_joycon_left_vertical%0)");
-        case Settings::ControllerType::RightJoycon:
-            return QStringLiteral("image: url(:/controller/single_joycon_right_vertical%0)");
-        case Settings::ControllerType::Handheld:
-            return QStringLiteral("image: url(:/controller/handheld%0)");
-        default:
-            return QString{};
-        }
-    }();
-
-    const QString theme = [] {
-        if (QIcon::themeName().contains(QStringLiteral("dark"))) {
-            return QStringLiteral("_dark");
-        } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
-            return QStringLiteral("_midnight");
-        } else {
-            return QString{};
-        }
-    }();
-    ui->controllerFrame->SetControllerType(
-        GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()));
-}
-
 void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
     auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
     if (debug) {
-        layout = Settings::ControllerType::ProController;
+        layout = Core::HID::NpadType::ProController;
     }
 
     // List of all the widgets that will be hidden by any of the following layouts that need
@@ -1075,15 +834,15 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
 
     std::vector<QWidget*> layout_hidden;
     switch (layout) {
-    case Settings::ControllerType::ProController:
-    case Settings::ControllerType::DualJoyconDetached:
-    case Settings::ControllerType::Handheld:
+    case Core::HID::NpadType::ProController:
+    case Core::HID::NpadType::JoyconDual:
+    case Core::HID::NpadType::Handheld:
         layout_hidden = {
             ui->buttonShoulderButtonsSLSR,
             ui->horizontalSpacerShoulderButtonsWidget2,
         };
         break;
-    case Settings::ControllerType::LeftJoycon:
+    case Core::HID::NpadType::JoyconLeft:
         layout_hidden = {
             ui->horizontalSpacerShoulderButtonsWidget2,
             ui->buttonShoulderButtonsRight,
@@ -1091,7 +850,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
             ui->bottomRight,
         };
         break;
-    case Settings::ControllerType::RightJoycon:
+    case Core::HID::NpadType::JoyconRight:
         layout_hidden = {
             ui->horizontalSpacerShoulderButtonsWidget,
             ui->buttonShoulderButtonsLeft,
@@ -1099,7 +858,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
             ui->bottomLeft,
         };
         break;
-    case Settings::ControllerType::GameCube:
+    case Core::HID::NpadType::GameCube:
         layout_hidden = {
             ui->buttonShoulderButtonsSLSR,
             ui->horizontalSpacerShoulderButtonsWidget2,
@@ -1107,6 +866,8 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
             ui->buttonMiscButtonsScreenshotGroup,
         };
         break;
+    default:
+        break;
     }
 
     for (auto* widget : layout_hidden) {
@@ -1117,13 +878,12 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
 void ConfigureInputPlayer::UpdateControllerEnabledButtons() {
     auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
     if (debug) {
-        layout = Settings::ControllerType::ProController;
+        layout = Core::HID::NpadType::ProController;
     }
 
     // List of all the widgets that will be disabled by any of the following layouts that need
     // "enabled" after the controller type changes
-    const std::array<QWidget*, 4> layout_enable = {
-        ui->buttonHome,
+    const std::array<QWidget*, 3> layout_enable = {
         ui->buttonLStickPressedGroup,
         ui->groupRStickPressed,
         ui->buttonShoulderButtonsButtonLGroup,
@@ -1135,17 +895,13 @@ void ConfigureInputPlayer::UpdateControllerEnabledButtons() {
 
     std::vector<QWidget*> layout_disable;
     switch (layout) {
-    case Settings::ControllerType::ProController:
-    case Settings::ControllerType::DualJoyconDetached:
-    case Settings::ControllerType::Handheld:
-    case Settings::ControllerType::LeftJoycon:
-    case Settings::ControllerType::RightJoycon:
-        // TODO(wwylele): enable this when we actually emulate it
-        layout_disable = {
-            ui->buttonHome,
-        };
+    case Core::HID::NpadType::ProController:
+    case Core::HID::NpadType::JoyconDual:
+    case Core::HID::NpadType::Handheld:
+    case Core::HID::NpadType::JoyconLeft:
+    case Core::HID::NpadType::JoyconRight:
         break;
-    case Settings::ControllerType::GameCube:
+    case Core::HID::NpadType::GameCube:
         layout_disable = {
             ui->buttonHome,
             ui->buttonLStickPressedGroup,
@@ -1153,6 +909,8 @@ void ConfigureInputPlayer::UpdateControllerEnabledButtons() {
             ui->buttonShoulderButtonsButtonLGroup,
         };
         break;
+    default:
+        break;
     }
 
     for (auto* widget : layout_disable) {
@@ -1170,24 +928,24 @@ void ConfigureInputPlayer::UpdateMotionButtons() {
 
     // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller.
     switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) {
-    case Settings::ControllerType::ProController:
-    case Settings::ControllerType::LeftJoycon:
-    case Settings::ControllerType::Handheld:
+    case Core::HID::NpadType::ProController:
+    case Core::HID::NpadType::JoyconLeft:
+    case Core::HID::NpadType::Handheld:
         // Show "Motion 1" and hide "Motion 2".
         ui->buttonMotionLeftGroup->show();
         ui->buttonMotionRightGroup->hide();
         break;
-    case Settings::ControllerType::RightJoycon:
+    case Core::HID::NpadType::JoyconRight:
         // Show "Motion 2" and hide "Motion 1".
         ui->buttonMotionLeftGroup->hide();
         ui->buttonMotionRightGroup->show();
         break;
-    case Settings::ControllerType::GameCube:
+    case Core::HID::NpadType::GameCube:
         // Hide both "Motion 1/2".
         ui->buttonMotionLeftGroup->hide();
         ui->buttonMotionRightGroup->hide();
         break;
-    case Settings::ControllerType::DualJoyconDetached:
+    case Core::HID::NpadType::JoyconDual:
     default:
         // Show both "Motion 1/2".
         ui->buttonMotionLeftGroup->show();
@@ -1199,15 +957,15 @@ void ConfigureInputPlayer::UpdateMotionButtons() {
 void ConfigureInputPlayer::UpdateControllerButtonNames() {
     auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
     if (debug) {
-        layout = Settings::ControllerType::ProController;
+        layout = Core::HID::NpadType::ProController;
     }
 
     switch (layout) {
-    case Settings::ControllerType::ProController:
-    case Settings::ControllerType::DualJoyconDetached:
-    case Settings::ControllerType::Handheld:
-    case Settings::ControllerType::LeftJoycon:
-    case Settings::ControllerType::RightJoycon:
+    case Core::HID::NpadType::ProController:
+    case Core::HID::NpadType::JoyconDual:
+    case Core::HID::NpadType::Handheld:
+    case Core::HID::NpadType::JoyconLeft:
+    case Core::HID::NpadType::JoyconRight:
         ui->buttonMiscButtonsPlusGroup->setTitle(tr("Plus"));
         ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("ZL"));
         ui->buttonShoulderButtonsZRGroup->setTitle(tr("ZR"));
@@ -1215,7 +973,7 @@ void ConfigureInputPlayer::UpdateControllerButtonNames() {
         ui->LStick->setTitle(tr("Left Stick"));
         ui->RStick->setTitle(tr("Right Stick"));
         break;
-    case Settings::ControllerType::GameCube:
+    case Core::HID::NpadType::GameCube:
         ui->buttonMiscButtonsPlusGroup->setTitle(tr("Start / Pause"));
         ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("L"));
         ui->buttonShoulderButtonsZRGroup->setTitle(tr("R"));
@@ -1223,6 +981,8 @@ void ConfigureInputPlayer::UpdateControllerButtonNames() {
         ui->LStick->setTitle(tr("Control Stick"));
         ui->RStick->setTitle(tr("C-Stick"));
         break;
+    default:
+        break;
     }
 }
 
@@ -1231,26 +991,93 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
         return;
     }
 
+    for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
+        const auto* const button = button_map[button_id];
+        if (button == nullptr) {
+            continue;
+        }
+        emulated_controller->SetButtonParam(button_id, {});
+    }
+
+    for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
+        for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
+            const auto* const analog_button = analog_map_buttons[analog_id][sub_button_id];
+            if (analog_button == nullptr) {
+                continue;
+            }
+            emulated_controller->SetStickParam(analog_id, {});
+        }
+    }
+
+    for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
+        const auto* const motion_button = motion_map[motion_id];
+        if (motion_button == nullptr) {
+            continue;
+        }
+        emulated_controller->SetMotionParam(motion_id, {});
+    }
+
+    // Reset keyboard bindings
     if (ui->comboDevices->currentIndex() == 1) {
-        // Reset keyboard bindings
         for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
-            buttons_param[button_id] = Common::ParamPackage{
-                InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])};
+            emulated_controller->SetButtonParam(
+                button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
+                               Config::default_buttons[button_id])});
         }
         for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
+            Common::ParamPackage analog_param{};
             for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
                 Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
                     Config::default_analogs[analog_id][sub_button_id])};
-                SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]);
+                SetAnalogParam(params, analog_param, analog_sub_buttons[sub_button_id]);
             }
 
-            analogs_param[analog_id].Set("modifier", InputCommon::GenerateKeyboardParam(
-                                                         Config::default_stick_mod[analog_id]));
+            analog_param.Set("modifier", InputCommon::GenerateKeyboardParam(
+                                             Config::default_stick_mod[analog_id]));
+            emulated_controller->SetStickParam(analog_id, analog_param);
         }
 
         for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
-            motions_param[motion_id] = Common::ParamPackage{
-                InputCommon::GenerateKeyboardParam(Config::default_motions[motion_id])};
+            emulated_controller->SetMotionParam(
+                motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
+                               Config::default_motions[motion_id])});
+        }
+
+        UpdateUI();
+        return;
+    }
+
+    // Reset keyboard with mouse bindings
+    if (ui->comboDevices->currentIndex() == 2) {
+        for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
+            emulated_controller->SetButtonParam(
+                button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
+                               Config::default_buttons[button_id])});
+        }
+
+        Common::ParamPackage left_analog_param{};
+        for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
+            Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
+                Config::default_analogs[Settings::NativeAnalog::LStick][sub_button_id])};
+            SetAnalogParam(params, left_analog_param, analog_sub_buttons[sub_button_id]);
+        }
+        left_analog_param.Set("modifier",
+                              InputCommon::GenerateKeyboardParam(
+                                  Config::default_stick_mod[Settings::NativeAnalog::LStick]));
+        emulated_controller->SetStickParam(Settings::NativeAnalog::LStick, left_analog_param);
+
+        Common::ParamPackage right_analog_param{};
+        right_analog_param.Set("engine", "mouse");
+        right_analog_param.Set("port", 0);
+        right_analog_param.Set("axis_x", 0);
+        right_analog_param.Set("axis_y", 1);
+        emulated_controller->SetStickParam(Settings::NativeAnalog::RStick,
+                                           std::move(right_analog_param));
+
+        for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
+            emulated_controller->SetMotionParam(
+                motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
+                               Config::default_motions[motion_id])});
         }
 
         UpdateUI();
@@ -1262,14 +1089,17 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
     auto button_mapping = input_subsystem->GetButtonMappingForDevice(device);
     auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device);
     auto motion_mapping = input_subsystem->GetMotionMappingForDevice(device);
-    for (std::size_t i = 0; i < buttons_param.size(); ++i) {
-        buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)];
+    for (std::size_t i = 0; i < button_mapping.size(); ++i) {
+        emulated_controller->SetButtonParam(
+            i, button_mapping[static_cast<Settings::NativeButton::Values>(i)]);
     }
-    for (std::size_t i = 0; i < analogs_param.size(); ++i) {
-        analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)];
+    for (std::size_t i = 0; i < analog_mapping.size(); ++i) {
+        emulated_controller->SetStickParam(
+            i, analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]);
     }
-    for (std::size_t i = 0; i < motions_param.size(); ++i) {
-        motions_param[i] = motion_mapping[static_cast<Settings::NativeMotion::Values>(i)];
+    for (std::size_t i = 0; i < motion_mapping.size(); ++i) {
+        emulated_controller->SetMotionParam(
+            i, motion_mapping[static_cast<Settings::NativeMotion::Values>(i)]);
     }
 
     UpdateUI();
@@ -1278,7 +1108,7 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
 void ConfigureInputPlayer::HandleClick(
     QPushButton* button, std::size_t button_id,
     std::function<void(const Common::ParamPackage&)> new_input_setter,
-    InputCommon::Polling::DeviceType type) {
+    InputCommon::Polling::InputType type) {
     if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) {
         button->setText(tr("Shake!"));
     } else {
@@ -1286,25 +1116,16 @@ void ConfigureInputPlayer::HandleClick(
     }
     button->setFocus();
 
-    // The first two input devices are always Any and Keyboard/Mouse. If the user filtered to a
-    // controller, then they don't want keyboard/mouse input
-    want_keyboard_mouse = ui->comboDevices->currentIndex() < 2;
-
     input_setter = new_input_setter;
 
-    device_pollers = input_subsystem->GetPollers(type);
-
-    for (auto& poller : device_pollers) {
-        poller->Start();
-    }
+    input_subsystem->BeginMapping(type);
 
     QWidget::grabMouse();
     QWidget::grabKeyboard();
 
-
-    if (type == InputCommon::Polling::DeviceType::Button) {
+    if (type == InputCommon::Polling::InputType::Button) {
         ui->controllerFrame->BeginMappingButton(button_id);
-    } else if (type == InputCommon::Polling::DeviceType::AnalogPreferred) {
+    } else if (type == InputCommon::Polling::InputType::Stick) {
         ui->controllerFrame->BeginMappingAnalog(button_id);
     }
 
@@ -1315,14 +1136,11 @@ void ConfigureInputPlayer::HandleClick(
 void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) {
     timeout_timer->stop();
     poll_timer->stop();
-    for (auto& poller : device_pollers) {
-        poller->Stop();
-    }
+    input_subsystem->StopMapping();
 
     QWidget::releaseMouse();
     QWidget::releaseKeyboard();
 
-
     if (!abort) {
         (*input_setter)(params);
     }
@@ -1340,13 +1158,14 @@ bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params)
     }
 
     // Keyboard/Mouse
-    if (ui->comboDevices->currentIndex() == 1) {
+    if (ui->comboDevices->currentIndex() == 2) {
         return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse";
     }
 
     const auto current_input_device = input_devices[ui->comboDevices->currentIndex()];
-    return params.Get("engine", "") == current_input_device.Get("class", "") &&
-           params.Get("guid", "") == current_input_device.Get("guid", "") &&
+    return params.Get("engine", "") == current_input_device.Get("engine", "") &&
+           (params.Get("guid", "") == current_input_device.Get("guid", "") ||
+            params.Get("guid", "") == current_input_device.Get("guid2", "")) &&
            params.Get("port", "") == current_input_device.Get("port", "");
 }
 
@@ -1355,25 +1174,18 @@ void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
         return;
     }
 
-    //const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
+    const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
+    input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button);
 }
 
 void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
+    event->ignore();
     if (!input_setter || !event) {
         return;
     }
-
     if (event->key() != Qt::Key_Escape) {
-        if (want_keyboard_mouse) {
-            SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())},
-                             false);
-        } else {
-            // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling
-            return;
-        }
+        input_subsystem->GetKeyboard()->PressKey(event->key());
     }
-
-    SetPollingResult({}, true);
 }
 
 void ConfigureInputPlayer::CreateProfile() {
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index 39b44b8a56..02d6920f1e 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -38,14 +38,22 @@ class InputSubsystem;
 }
 
 namespace InputCommon::Polling {
-class DevicePoller;
-enum class DeviceType;
+enum class InputType;
 } // namespace InputCommon::Polling
 
 namespace Ui {
 class ConfigureInputPlayer;
 }
 
+namespace Core {
+class System;
+}
+
+namespace Core::HID {
+class EmulatedController;
+enum class NpadType : u8;
+} // namespace Core::HID
+
 class ConfigureInputPlayer : public QWidget {
     Q_OBJECT
 
@@ -59,18 +67,6 @@ public:
     /// Save all button configurations to settings file.
     void ApplyConfiguration();
 
-    /**
-     * Attempts to connect the currently selected controller in the HID backend.
-     * This function will not do anything if it is not connected in the frontend.
-     */
-    void TryConnectSelectedController();
-
-    /**
-     * Attempts to disconnect the currently selected controller in the HID backend.
-     * This function will not do anything if the configuration has not changed.
-     */
-    void TryDisconnectSelectedController();
-
     /// Set the connection state checkbox (used to sync state).
     void ConnectPlayer(bool connected);
 
@@ -104,6 +100,10 @@ protected:
     void showEvent(QShowEvent* event) override;
 
 private:
+    QString ButtonToText(const Common::ParamPackage& param);
+
+    QString AnalogToText(const Common::ParamPackage& param, const std::string& dir);
+
     void changeEvent(QEvent* event) override;
     void RetranslateUI();
 
@@ -113,7 +113,7 @@ private:
     /// Called when the button was pressed.
     void HandleClick(QPushButton* button, std::size_t button_id,
                      std::function<void(const Common::ParamPackage&)> new_input_setter,
-                     InputCommon::Polling::DeviceType type);
+                     InputCommon::Polling::InputType type);
 
     /// Finish polling and configure input using the input_setter.
     void SetPollingResult(const Common::ParamPackage& params, bool abort);
@@ -134,17 +134,14 @@ private:
     void SetConnectableControllers();
 
     /// Gets the Controller Type for a given controller combobox index.
-    Settings::ControllerType GetControllerTypeFromIndex(int index) const;
+    Core::HID::NpadType GetControllerTypeFromIndex(int index) const;
 
     /// Gets the controller combobox index for a given Controller Type.
-    int GetIndexFromControllerType(Settings::ControllerType type) const;
+    int GetIndexFromControllerType(Core::HID::NpadType type) const;
 
     /// Update the available input devices.
     void UpdateInputDevices();
 
-    /// Update the current controller icon.
-    void UpdateControllerIcon();
-
     /// Hides and disables controller settings based on the current controller type.
     void UpdateControllerAvailableButtons();
 
@@ -185,7 +182,7 @@ private:
     std::unique_ptr<QTimer> poll_timer;
 
     /// Stores a pair of "Connected Controllers" combobox index and Controller Type enum.
-    std::vector<std::pair<int, Settings::ControllerType>> index_controller_type_pairs;
+    std::vector<std::pair<int, Core::HID::NpadType>> index_controller_type_pairs;
 
     static constexpr int PLAYER_COUNT = 8;
     std::array<QCheckBox*, PLAYER_COUNT> player_connected_checkbox;
@@ -193,9 +190,7 @@ private:
     /// This will be the the setting function when an input is awaiting configuration.
     std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
 
-    std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param;
-    std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param;
-    std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions> motions_param;
+    Core::HID::EmulatedController* emulated_controller;
 
     static constexpr int ANALOG_SUB_BUTTONS_NUM = 4;
 
@@ -221,15 +216,9 @@ private:
 
     static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons;
 
-    std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
-
     /// A flag to indicate that the "Map Analog Stick" pop-up has been shown and accepted once.
     bool map_analog_stick_accepted{};
 
-    /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false,
-    /// keyboard events are ignored.
-    bool want_keyboard_mouse{};
-
     /// List of physical devices users can map with. If a SDL backed device is selected, then you
     /// can use this device to get a default mapping.
     std::vector<Common::ParamPackage> input_devices;
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui
index e7433912b8..14ca02fd84 100644
--- a/src/yuzu/configuration/configure_input_player.ui
+++ b/src/yuzu/configuration/configure_input_player.ui
@@ -148,16 +148,6 @@
               <height>21</height>
              </size>
             </property>
-            <item>
-             <property name="text">
-              <string>Any</string>
-             </property>
-            </item>
-            <item>
-             <property name="text">
-              <string>Keyboard/Mouse</string>
-             </property>
-            </item>
            </widget>
           </item>
           <item>
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index f31f86339e..03d29f194e 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -6,10 +6,11 @@
 #include <QMenu>
 #include <QPainter>
 #include <QTimer>
+#include "core/core.h"
 #include "yuzu/configuration/configure_input_player_widget.h"
 
 PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) {
-    UpdateColors();
+    is_controller_set = false;
     QTimer* timer = new QTimer(this);
     connect(timer, &QTimer::timeout, this, QOverload<>::of(&PlayerControlPreview::UpdateInput));
 
@@ -17,38 +18,11 @@ PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) {
     timer->start(16);
 }
 
-PlayerControlPreview::~PlayerControlPreview() = default;
-
-void PlayerControlPreview::SetPlayerInput(std::size_t index, const ButtonParam& buttons_param,
-                                          const AnalogParam& analogs_param) {
-    player_index = index;
-    Settings::ButtonsRaw buttonss;
-    Settings::AnalogsRaw analogs;
-    std::transform(buttons_param.begin(), buttons_param.end(), buttonss.begin(),
-                   [](const Common::ParamPackage& param) { return param.Serialize(); });
-    std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(),
-                   [](const Common::ParamPackage& param) { return param.Serialize(); });
-
-    std::transform(buttonss.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
-                   buttonss.begin() + Settings::NativeButton::BUTTON_NS_END, buttons.begin(),
-                   Input::CreateDevice<Input::ButtonDevice>);
-    std::transform(analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
-                   analogs.begin() + Settings::NativeAnalog::STICK_HID_END, sticks.begin(),
-                   Input::CreateDevice<Input::AnalogDevice>);
-    UpdateColors();
-}
-void PlayerControlPreview::SetPlayerInputRaw(std::size_t index,
-                                             const Settings::ButtonsRaw& buttons_,
-                                             Settings::AnalogsRaw analogs_) {
-    player_index = index;
-    std::transform(buttons_.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
-                   buttons_.begin() + Settings::NativeButton::BUTTON_NS_END, buttons.begin(),
-                   Input::CreateDevice<Input::ButtonDevice>);
-    std::transform(analogs_.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
-                   analogs_.begin() + Settings::NativeAnalog::STICK_HID_END, sticks.begin(),
-                   Input::CreateDevice<Input::AnalogDevice>);
-    UpdateColors();
-}
+PlayerControlPreview::~PlayerControlPreview() {
+    if (is_controller_set) {
+        controller->DeleteCallback(callback_key);
+    }
+};
 
 PlayerControlPreview::LedPattern PlayerControlPreview::GetColorPattern(std::size_t index,
                                                                        bool player_on) {
@@ -78,20 +52,16 @@ PlayerControlPreview::LedPattern PlayerControlPreview::GetColorPattern(std::size
     }
 }
 
-void PlayerControlPreview::SetConnectedStatus(bool checked) {
-    LedPattern led_pattern = GetColorPattern(player_index, checked);
-
-    led_color[0] = led_pattern.position1 ? colors.led_on : colors.led_off;
-    led_color[1] = led_pattern.position2 ? colors.led_on : colors.led_off;
-    led_color[2] = led_pattern.position3 ? colors.led_on : colors.led_off;
-    led_color[3] = led_pattern.position4 ? colors.led_on : colors.led_off;
-    is_enabled = checked;
-    ResetInputs();
-}
-
-void PlayerControlPreview::SetControllerType(const Settings::ControllerType type) {
-    controller_type = type;
-    UpdateColors();
+void PlayerControlPreview::SetController(Core::HID::EmulatedController* controller_) {
+    if (is_controller_set) {
+        controller->DeleteCallback(callback_key);
+    }
+    is_controller_set = true;
+    controller = controller_;
+    Core::HID::ControllerUpdateCallback engine_callback{
+        [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); }};
+    callback_key = controller->SetCallback(engine_callback);
+    ControllerUpdate(Core::HID::ControllerTriggerType::All);
 }
 
 void PlayerControlPreview::BeginMappingButton(std::size_t index) {
@@ -162,79 +132,99 @@ void PlayerControlPreview::UpdateColors() {
 }
 
 void PlayerControlPreview::ResetInputs() {
-    for (std::size_t index = 0; index < button_values.size(); ++index) {
-        button_values[index] = false;
-    }
-
-    for (std::size_t index = 0; index < axis_values.size(); ++index) {
-        axis_values[index].properties = {0, 1, 0};
-        axis_values[index].value = {0, 0};
-        axis_values[index].raw_value = {0, 0};
-    }
+    button_values.fill({
+        .value = false,
+    });
+    stick_values.fill({
+        .x = {.value = 0, .properties = {0, 1, 0}},
+        .y = {.value = 0, .properties = {0, 1, 0}},
+    });
+    trigger_values.fill({
+        .analog = {.value = 0, .properties = {0, 1, 0}},
+        .pressed = false,
+    });
     update();
 }
 
-void PlayerControlPreview::UpdateInput() {
-    if (!is_enabled && !mapping_active && !Settings::values.tas_enable) {
+void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType type) {
+    if (type == Core::HID::ControllerTriggerType::All) {
+        ControllerUpdate(Core::HID::ControllerTriggerType::Color);
+        ControllerUpdate(Core::HID::ControllerTriggerType::Type);
+        ControllerUpdate(Core::HID::ControllerTriggerType::Connected);
+        ControllerUpdate(Core::HID::ControllerTriggerType::Button);
+        ControllerUpdate(Core::HID::ControllerTriggerType::Stick);
+        ControllerUpdate(Core::HID::ControllerTriggerType::Trigger);
+        ControllerUpdate(Core::HID::ControllerTriggerType::Battery);
         return;
     }
-    bool input_changed = false;
-    const auto& button_state = buttons;
-    for (std::size_t index = 0; index < button_values.size(); ++index) {
-        bool value = false;
-        if (index < Settings::NativeButton::BUTTON_NS_END) {
-            value = button_state[index]->GetStatus();
-        }
-        bool blink = mapping_active && index == button_mapping_index;
-        if (analog_mapping_index == Settings::NativeAnalog::NUM_STICKS_HID) {
-            blink &= blink_counter > 25;
-        }
-        if (button_values[index] != value || blink) {
-            input_changed = true;
-        }
-        button_values[index] = value || blink;
+
+    switch (type) {
+    case Core::HID::ControllerTriggerType::Connected:
+    case Core::HID::ControllerTriggerType::Disconnected:
+        is_connected = controller->IsConnected();
+        needs_redraw = true;
+        break;
+    case Core::HID::ControllerTriggerType::Type:
+        controller_type = controller->GetNpadType();
+        needs_redraw = true;
+        break;
+    case Core::HID::ControllerTriggerType::Color:
+        UpdateColors();
+        needs_redraw = true;
+        break;
+    case Core::HID::ControllerTriggerType::Button:
+        button_values = controller->GetButtonsValues();
+        needs_redraw = true;
+        break;
+    case Core::HID::ControllerTriggerType::Stick:
+        using namespace Settings::NativeAnalog;
+        stick_values = controller->GetSticksValues();
+        // Y axis is inverted
+        stick_values[LStick].y.value = -stick_values[LStick].y.value;
+        stick_values[LStick].y.raw_value = -stick_values[LStick].y.raw_value;
+        stick_values[RStick].y.value = -stick_values[RStick].y.value;
+        stick_values[RStick].y.raw_value = -stick_values[RStick].y.raw_value;
+        needs_redraw = true;
+        break;
+    case Core::HID::ControllerTriggerType::Trigger:
+        trigger_values = controller->GetTriggersValues();
+        needs_redraw = true;
+        break;
+    case Core::HID::ControllerTriggerType::Battery:
+        battery_values = controller->GetBatteryValues();
+        needs_redraw = true;
+        break;
+    default:
+        break;
     }
+}
 
-    const auto& analog_state = sticks;
-    for (std::size_t index = 0; index < axis_values.size(); ++index) {
-        const auto [stick_x_f, stick_y_f] = analog_state[index]->GetStatus();
-        const auto [stick_x_rf, stick_y_rf] = analog_state[index]->GetRawStatus();
+void PlayerControlPreview::UpdateInput() {
+    if (mapping_active) {
 
-        if (static_cast<int>(stick_x_rf * 45) !=
-                static_cast<int>(axis_values[index].raw_value.x() * 45) ||
-            static_cast<int>(-stick_y_rf * 45) !=
-                static_cast<int>(axis_values[index].raw_value.y() * 45)) {
-            input_changed = true;
+        for (std::size_t index = 0; index < button_values.size(); ++index) {
+            bool blink = index == button_mapping_index;
+            if (analog_mapping_index == Settings::NativeAnalog::NumAnalogs) {
+                blink &= blink_counter > 25;
+            }
+            if (button_values[index].value != blink) {
+                needs_redraw = true;
+            }
+            button_values[index].value = blink;
         }
 
-        axis_values[index].properties = analog_state[index]->GetAnalogProperties();
-        axis_values[index].value = QPointF(stick_x_f, -stick_y_f);
-        axis_values[index].raw_value = QPointF(stick_x_rf, -stick_y_rf);
-
-        const bool blink_analog = mapping_active && index == analog_mapping_index;
-        if (blink_analog) {
-            input_changed = true;
-            axis_values[index].value =
-                QPointF(blink_counter < 25 ? -blink_counter / 25.0f : 0,
-                        blink_counter > 25 ? -(blink_counter - 25) / 25.0f : 0);
+        for (std::size_t index = 0; index < stick_values.size(); ++index) {
+            const bool blink_analog = index == analog_mapping_index;
+            if (blink_analog) {
+                needs_redraw = true;
+                stick_values[index].x.value = blink_counter < 25 ? -blink_counter / 25.0f : 0;
+                stick_values[index].y.value =
+                    blink_counter > 25 ? -(blink_counter - 25) / 25.0f : 0;
+            }
         }
     }
-
-    if (input_changed) {
+    if (needs_redraw) {
         update();
-        if (controller_callback.input != nullptr) {
-            ControllerInput input{
-                .axis_values = {std::pair<float, float>{
-                                    axis_values[Settings::NativeAnalog::LStick].value.x(),
-                                    axis_values[Settings::NativeAnalog::LStick].value.y()},
-                                std::pair<float, float>{
-                                    axis_values[Settings::NativeAnalog::RStick].value.x(),
-                                    axis_values[Settings::NativeAnalog::RStick].value.y()}},
-                .button_values = button_values,
-                .changed = true,
-            };
-            controller_callback.input(std::move(input));
-        }
     }
 
     if (mapping_active) {
@@ -242,10 +232,6 @@ void PlayerControlPreview::UpdateInput() {
     }
 }
 
-void PlayerControlPreview::SetCallBack(ControllerCallback callback_) {
-    controller_callback = std::move(callback_);
-}
-
 void PlayerControlPreview::paintEvent(QPaintEvent* event) {
     QFrame::paintEvent(event);
     QPainter p(this);
@@ -253,22 +239,22 @@ void PlayerControlPreview::paintEvent(QPaintEvent* event) {
     const QPointF center = rect().center();
 
     switch (controller_type) {
-    case Settings::ControllerType::Handheld:
+    case Core::HID::NpadType::Handheld:
         DrawHandheldController(p, center);
         break;
-    case Settings::ControllerType::DualJoyconDetached:
+    case Core::HID::NpadType::JoyconDual:
         DrawDualController(p, center);
         break;
-    case Settings::ControllerType::LeftJoycon:
+    case Core::HID::NpadType::JoyconLeft:
         DrawLeftController(p, center);
         break;
-    case Settings::ControllerType::RightJoycon:
+    case Core::HID::NpadType::JoyconRight:
         DrawRightController(p, center);
         break;
-    case Settings::ControllerType::GameCube:
+    case Core::HID::NpadType::GameCube:
         DrawGCController(p, center);
         break;
-    case Settings::ControllerType::ProController:
+    case Core::HID::NpadType::ProController:
     default:
         DrawProController(p, center);
         break;
@@ -281,7 +267,7 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
 
         // Sideview left joystick
         DrawJoystickSideview(p, center + QPoint(142, -69),
-                             -axis_values[Settings::NativeAnalog::LStick].value.y(), 1.15f,
+                             -stick_values[Settings::NativeAnalog::LStick].y.value, 1.15f,
                              button_values[LStick]);
 
         // Topview D-pad buttons
@@ -292,7 +278,7 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
 
         // Topview left joystick
         DrawJoystickSideview(p, center + QPointF(-140.5f, -28),
-                             -axis_values[Settings::NativeAnalog::LStick].value.x() + 15.0f, 1.15f,
+                             -stick_values[Settings::NativeAnalog::LStick].x.value + 15.0f, 1.15f,
                              button_values[LStick]);
 
         // Topview minus button
@@ -334,8 +320,10 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
     {
         // Draw joysticks
         using namespace Settings::NativeAnalog;
-        DrawJoystick(p, center + QPointF(9, -69) + (axis_values[LStick].value * 8), 1.8f,
-                     button_values[Settings::NativeButton::LStick]);
+        DrawJoystick(p,
+                     center + QPointF(9, -69) +
+                         (QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value) * 8),
+                     1.8f, button_values[Settings::NativeButton::LStick]);
         DrawRawJoystick(p, center + QPointF(-140, 90), QPointF(0, 0));
     }
 
@@ -384,6 +372,9 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
     p.setPen(colors.font2);
     p.setBrush(colors.font2);
     DrawCircle(p, center + QPoint(26, 71), 5);
+
+    // Draw battery
+    DrawBattery(p, center + QPoint(-170, -140), battery_values[0]);
 }
 
 void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) {
@@ -392,20 +383,22 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
 
         // Sideview right joystick
         DrawJoystickSideview(p, center + QPoint(173 - 315, 11),
-                             axis_values[Settings::NativeAnalog::RStick].value.y() + 10.0f, 1.15f,
+                             stick_values[Settings::NativeAnalog::RStick].y.value + 10.0f, 1.15f,
                              button_values[Settings::NativeButton::RStick]);
 
+        // Topview right joystick
+        DrawJoystickSideview(p, center + QPointF(140, -28),
+                             -stick_values[Settings::NativeAnalog::RStick].x.value + 15.0f, 1.15f,
+                             button_values[RStick]);
+
         // Topview face buttons
         p.setPen(colors.outline);
         button_color = colors.button;
         DrawRoundButton(p, center + QPoint(163, -21), button_values[A], 11, 5, Direction::Up);
+        DrawRoundButton(p, center + QPoint(140, -21), button_values[B], 11, 5, Direction::Up);
+        DrawRoundButton(p, center + QPoint(140, -21), button_values[X], 11, 5, Direction::Up);
         DrawRoundButton(p, center + QPoint(117, -21), button_values[Y], 11, 5, Direction::Up);
 
-        // Topview right joystick
-        DrawJoystickSideview(p, center + QPointF(140, -28),
-                             -axis_values[Settings::NativeAnalog::RStick].value.x() + 15.0f, 1.15f,
-                             button_values[RStick]);
-
         // Topview plus button
         p.setPen(colors.outline);
         button_color = colors.button;
@@ -448,8 +441,10 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
     {
         // Draw joysticks
         using namespace Settings::NativeAnalog;
-        DrawJoystick(p, center + QPointF(-9, 11) + (axis_values[RStick].value * 8), 1.8f,
-                     button_values[Settings::NativeButton::RStick]);
+        DrawJoystick(p,
+                     center + QPointF(-9, 11) +
+                         (QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value) * 8),
+                     1.8f, button_values[Settings::NativeButton::RStick]);
         DrawRawJoystick(p, QPointF(0, 0), center + QPointF(140, 90));
     }
 
@@ -503,6 +498,9 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
     p.setPen(colors.transparent);
     p.setBrush(colors.font2);
     DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5);
+
+    // Draw battery
+    DrawBattery(p, center + QPoint(110, -140), battery_values[1]);
 }
 
 void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) {
@@ -512,17 +510,19 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
         // Left/Right trigger
         DrawDualTriggers(p, center, button_values[L], button_values[R]);
 
+        // Topview right joystick
+        DrawJoystickSideview(p, center + QPointF(180, -78),
+                             -stick_values[Settings::NativeAnalog::RStick].x.value + 15.0f, 1,
+                             button_values[RStick]);
+
         // Topview face buttons
         p.setPen(colors.outline);
         button_color = colors.button;
         DrawRoundButton(p, center + QPoint(200, -71), button_values[A], 10, 5, Direction::Up);
+        DrawRoundButton(p, center + QPoint(180, -71), button_values[B], 10, 5, Direction::Up);
+        DrawRoundButton(p, center + QPoint(180, -71), button_values[X], 10, 5, Direction::Up);
         DrawRoundButton(p, center + QPoint(160, -71), button_values[Y], 10, 5, Direction::Up);
 
-        // Topview right joystick
-        DrawJoystickSideview(p, center + QPointF(180, -78),
-                             -axis_values[Settings::NativeAnalog::RStick].value.x() + 15.0f, 1,
-                             button_values[RStick]);
-
         // Topview plus button
         p.setPen(colors.outline);
         button_color = colors.button;
@@ -538,7 +538,7 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
 
         // Topview left joystick
         DrawJoystickSideview(p, center + QPointF(-180.5f, -78),
-                             -axis_values[Settings::NativeAnalog::LStick].value.x() + 15.0f, 1,
+                             -stick_values[Settings::NativeAnalog::LStick].x.value + 15.0f, 1,
                              button_values[LStick]);
 
         // Topview minus button
@@ -557,13 +557,13 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
     {
         // Draw joysticks
         using namespace Settings::NativeAnalog;
-        const auto& l_stick = axis_values[LStick];
+        const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value);
         const auto l_button = button_values[Settings::NativeButton::LStick];
-        const auto& r_stick = axis_values[RStick];
+        const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value);
         const auto r_button = button_values[Settings::NativeButton::RStick];
 
-        DrawJoystick(p, center + QPointF(-65, -65) + (l_stick.value * 7), 1.62f, l_button);
-        DrawJoystick(p, center + QPointF(65, 12) + (r_stick.value * 7), 1.62f, r_button);
+        DrawJoystick(p, center + QPointF(-65, -65) + (l_stick * 7), 1.62f, l_button);
+        DrawJoystick(p, center + QPointF(65, 12) + (r_stick * 7), 1.62f, r_button);
         DrawRawJoystick(p, center + QPointF(-180, 90), center + QPointF(180, 90));
     }
 
@@ -634,6 +634,10 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
     p.setPen(colors.transparent);
     p.setBrush(colors.font2);
     DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f);
+
+    // Draw battery
+    DrawBattery(p, center + QPoint(-100, -160), battery_values[0]);
+    DrawBattery(p, center + QPoint(40, -160), battery_values[1]);
 }
 
 void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) {
@@ -643,13 +647,13 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
     {
         // Draw joysticks
         using namespace Settings::NativeAnalog;
-        const auto& l_stick = axis_values[LStick];
+        const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value);
         const auto l_button = button_values[Settings::NativeButton::LStick];
-        const auto& r_stick = axis_values[RStick];
+        const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value);
         const auto r_button = button_values[Settings::NativeButton::RStick];
 
-        DrawJoystick(p, center + QPointF(-171, -41) + (l_stick.value * 4), 1.0f, l_button);
-        DrawJoystick(p, center + QPointF(171, 8) + (r_stick.value * 4), 1.0f, r_button);
+        DrawJoystick(p, center + QPointF(-171, -41) + (l_stick * 4), 1.0f, l_button);
+        DrawJoystick(p, center + QPointF(171, 8) + (r_stick * 4), 1.0f, r_button);
         DrawRawJoystick(p, center + QPointF(-50, 0), center + QPointF(50, 0));
     }
 
@@ -732,6 +736,11 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
     p.setPen(colors.transparent);
     p.setBrush(colors.font2);
     DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f);
+
+    // Draw battery
+    DrawBattery(p, center + QPoint(-200, 110), battery_values[0]);
+    DrawBattery(p, center + QPoint(-30, 110), battery_values[1]);
+    DrawBattery(p, center + QPoint(130, 110), battery_values[2]);
 }
 
 void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) {
@@ -741,9 +750,11 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
     {
         // Draw joysticks
         using namespace Settings::NativeAnalog;
-        DrawProJoystick(p, center + QPointF(-111, -55), axis_values[LStick].value, 11,
+        const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value);
+        const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value);
+        DrawProJoystick(p, center + QPointF(-111, -55), l_stick, 11,
                         button_values[Settings::NativeButton::LStick]);
-        DrawProJoystick(p, center + QPointF(51, 0), axis_values[RStick].value, 11,
+        DrawProJoystick(p, center + QPointF(51, 0), r_stick, 11,
                         button_values[Settings::NativeButton::RStick]);
         DrawRawJoystick(p, center + QPointF(-50, 105), center + QPointF(50, 105));
     }
@@ -817,24 +828,26 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
     p.setPen(colors.transparent);
     p.setBrush(colors.font2);
     DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f);
+
+    // Draw battery
+    DrawBattery(p, center + QPoint(-30, -165), battery_values[0]);
 }
 
 void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
-    DrawGCTriggers(p, center, button_values[Settings::NativeButton::ZL],
-                   button_values[Settings::NativeButton::ZR]);
+    DrawGCTriggers(p, center, trigger_values[0], trigger_values[1]);
     DrawGCButtonZ(p, center, button_values[Settings::NativeButton::R]);
     DrawGCBody(p, center);
     {
         // Draw joysticks
         using namespace Settings::NativeAnalog;
-        DrawGCJoystick(p, center + QPointF(-111, -44) + (axis_values[LStick].value * 10), false);
+        const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value);
+        const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value);
+        DrawGCJoystick(p, center + QPointF(-111, -44) + (l_stick * 10), {});
         button_color = colors.button2;
-        DrawCircleButton(p, center + QPointF(61, 37) + (axis_values[RStick].value * 9.5f), false,
-                         15);
+        DrawCircleButton(p, center + QPointF(61, 37) + (r_stick * 9.5f), {}, 15);
         p.setPen(colors.transparent);
         p.setBrush(colors.font);
-        DrawSymbol(p, center + QPointF(61, 37) + (axis_values[RStick].value * 9.5f), Symbol::C,
-                   1.0f);
+        DrawSymbol(p, center + QPointF(61, 37) + (r_stick * 9.5f), Symbol::C, 1.0f);
         DrawRawJoystick(p, center + QPointF(-198, -125), center + QPointF(198, -125));
     }
 
@@ -871,6 +884,9 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
     // Minus and Plus buttons
     p.setPen(colors.outline);
     DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8);
+
+    // Draw battery
+    DrawBattery(p, center + QPoint(-30, -165), battery_values[0]);
 }
 
 constexpr std::array<float, 13 * 2> symbol_a = {
@@ -1939,8 +1955,9 @@ void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) {
     }
 }
 
-void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, bool left_pressed,
-                                           bool right_pressed) {
+void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center,
+                                           const Input::ButtonStatus& left_pressed,
+                                           const Input::ButtonStatus& right_pressed) {
     std::array<QPointF, pro_left_trigger.size() / 2> qleft_trigger;
     std::array<QPointF, pro_left_trigger.size() / 2> qright_trigger;
     std::array<QPointF, pro_body_top.size()> qbody_top;
@@ -1949,8 +1966,10 @@ void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, bo
         const float trigger_x = pro_left_trigger[point * 2 + 0];
         const float trigger_y = pro_left_trigger[point * 2 + 1];
 
-        qleft_trigger[point] = center + QPointF(trigger_x, trigger_y + (left_pressed ? 2 : 0));
-        qright_trigger[point] = center + QPointF(-trigger_x, trigger_y + (right_pressed ? 2 : 0));
+        qleft_trigger[point] =
+            center + QPointF(trigger_x, trigger_y + (left_pressed.value ? 2 : 0));
+        qright_trigger[point] =
+            center + QPointF(-trigger_x, trigger_y + (right_pressed.value ? 2 : 0));
     }
 
     for (std::size_t point = 0; point < pro_body_top.size() / 2; ++point) {
@@ -1967,16 +1986,17 @@ void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, bo
     DrawPolygon(p, qbody_top);
 
     // Left trigger
-    p.setBrush(left_pressed ? colors.highlight : colors.button);
+    p.setBrush(left_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qleft_trigger);
 
     // Right trigger
-    p.setBrush(right_pressed ? colors.highlight : colors.button);
+    p.setBrush(right_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qright_trigger);
 }
 
-void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, bool left_pressed,
-                                          bool right_pressed) {
+void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center,
+                                          Input::TriggerStatus left_trigger,
+                                          Input::TriggerStatus right_trigger) {
     std::array<QPointF, left_gc_trigger.size() / 2> qleft_trigger;
     std::array<QPointF, left_gc_trigger.size() / 2> qright_trigger;
 
@@ -1984,32 +2004,37 @@ void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, boo
         const float trigger_x = left_gc_trigger[point * 2 + 0];
         const float trigger_y = left_gc_trigger[point * 2 + 1];
 
-        qleft_trigger[point] = center + QPointF(trigger_x, trigger_y + (left_pressed ? 10 : 0));
-        qright_trigger[point] = center + QPointF(-trigger_x, trigger_y + (right_pressed ? 10 : 0));
+        qleft_trigger[point] =
+            center + QPointF(trigger_x, trigger_y + (left_trigger.analog.value * 10.0f));
+        qright_trigger[point] =
+            center + QPointF(-trigger_x, trigger_y + (right_trigger.analog.value * 10.0f));
     }
 
     // Left trigger
     p.setPen(colors.outline);
-    p.setBrush(left_pressed ? colors.highlight : colors.button);
+    p.setBrush(left_trigger.pressed ? colors.highlight : colors.button);
     DrawPolygon(p, qleft_trigger);
 
     // Right trigger
-    p.setBrush(right_pressed ? colors.highlight : colors.button);
+    p.setBrush(right_trigger.pressed ? colors.highlight : colors.button);
     DrawPolygon(p, qright_trigger);
 
     // Draw L text
     p.setPen(colors.transparent);
     p.setBrush(colors.font);
-    DrawSymbol(p, center + QPointF(-132, -119 + (left_pressed ? 10 : 0)), Symbol::L, 1.7f);
+    DrawSymbol(p, center + QPointF(-132, -119 + (left_trigger.analog.value * 10.0f)), Symbol::L,
+               1.7f);
 
     // Draw R text
     p.setPen(colors.transparent);
     p.setBrush(colors.font);
-    DrawSymbol(p, center + QPointF(121.5f, -119 + (right_pressed ? 10 : 0)), Symbol::R, 1.7f);
+    DrawSymbol(p, center + QPointF(121.5f, -119 + (right_trigger.analog.value * 10.0f)), Symbol::R,
+               1.7f);
 }
 
 void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF center,
-                                                bool left_pressed, bool right_pressed) {
+                                                const Input::ButtonStatus& left_pressed,
+                                                const Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
     std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
 
@@ -2018,23 +2043,24 @@ void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF cente
         const float left_trigger_y = left_joycon_trigger[point * 2 + 1];
 
         qleft_trigger[point] =
-            center + QPointF(left_trigger_x, left_trigger_y + (left_pressed ? 0.5f : 0));
+            center + QPointF(left_trigger_x, left_trigger_y + (left_pressed.value ? 0.5f : 0));
         qright_trigger[point] =
-            center + QPointF(-left_trigger_x, left_trigger_y + (right_pressed ? 0.5f : 0));
+            center + QPointF(-left_trigger_x, left_trigger_y + (right_pressed.value ? 0.5f : 0));
     }
 
     // Left trigger
     p.setPen(colors.outline);
-    p.setBrush(left_pressed ? colors.highlight : colors.button);
+    p.setBrush(left_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qleft_trigger);
 
     // Right trigger
-    p.setBrush(right_pressed ? colors.highlight : colors.button);
+    p.setBrush(right_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qright_trigger);
 }
 
-void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center, bool left_pressed,
-                                            bool right_pressed) {
+void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center,
+                                            const Input::ButtonStatus& left_pressed,
+                                            const Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
     std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
     constexpr float size = 1.62f;
@@ -2043,25 +2069,27 @@ void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center, b
         const float left_trigger_x = left_joycon_trigger[point * 2 + 0];
         const float left_trigger_y = left_joycon_trigger[point * 2 + 1];
 
-        qleft_trigger[point] = center + QPointF(left_trigger_x * size + offset,
-                                                left_trigger_y * size + (left_pressed ? 0.5f : 0));
+        qleft_trigger[point] =
+            center + QPointF(left_trigger_x * size + offset,
+                             left_trigger_y * size + (left_pressed.value ? 0.5f : 0));
         qright_trigger[point] =
             center + QPointF(-left_trigger_x * size - offset,
-                             left_trigger_y * size + (right_pressed ? 0.5f : 0));
+                             left_trigger_y * size + (right_pressed.value ? 0.5f : 0));
     }
 
     // Left trigger
     p.setPen(colors.outline);
-    p.setBrush(left_pressed ? colors.highlight : colors.button);
+    p.setBrush(left_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qleft_trigger);
 
     // Right trigger
-    p.setBrush(right_pressed ? colors.highlight : colors.button);
+    p.setBrush(right_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qright_trigger);
 }
 
 void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF center,
-                                                   bool left_pressed, bool right_pressed) {
+                                                   const Input::ButtonStatus& left_pressed,
+                                                   const Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger;
     std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger;
     constexpr float size = 0.9f;
@@ -2080,9 +2108,9 @@ void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF ce
     }
 
     p.setPen(colors.outline);
-    p.setBrush(left_pressed ? colors.highlight : colors.button);
+    p.setBrush(left_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qleft_trigger);
-    p.setBrush(right_pressed ? colors.highlight : colors.button);
+    p.setBrush(right_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qright_trigger);
 
     // Draw L text
@@ -2097,7 +2125,8 @@ void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF ce
 }
 
 void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF center,
-                                                    bool left_pressed, bool right_pressed) {
+                                                    const Input::ButtonStatus& left_pressed,
+                                                    const Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger;
     std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger;
     constexpr float size = 0.9f;
@@ -2114,9 +2143,9 @@ void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF c
     }
 
     p.setPen(colors.outline);
-    p.setBrush(left_pressed ? colors.highlight : colors.button);
+    p.setBrush(left_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qleft_trigger);
-    p.setBrush(right_pressed ? colors.highlight : colors.button);
+    p.setBrush(right_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qright_trigger);
 
     // Draw ZL text
@@ -2130,7 +2159,8 @@ void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF c
     DrawSymbol(p, center + QPointF(180, -113), Symbol::ZR, 1.0f);
 }
 
-void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center, bool left_pressed) {
+void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center,
+                                            const Input::ButtonStatus& left_pressed) {
     std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
     constexpr float size = 1.78f;
     constexpr float offset = 311.5f;
@@ -2138,15 +2168,16 @@ void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center, b
     for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
         qleft_trigger[point] = center + QPointF(left_joycon_trigger[point * 2] * size + offset,
                                                 left_joycon_trigger[point * 2 + 1] * size -
-                                                    (left_pressed ? 0.5f : 1.0f));
+                                                    (left_pressed.value ? 0.5f : 1.0f));
     }
 
     p.setPen(colors.outline);
-    p.setBrush(left_pressed ? colors.highlight : colors.button);
+    p.setBrush(left_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qleft_trigger);
 }
 
-void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center, bool left_pressed) {
+void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center,
+                                             const Input::ButtonStatus& left_pressed) {
     std::array<QPointF, left_joycon_sideview_zl.size() / 2> qleft_trigger;
     constexpr float size = 1.1115f;
     constexpr float offset2 = 335;
@@ -2154,18 +2185,18 @@ void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center,
     for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) {
         qleft_trigger[point] = center + QPointF(left_joycon_sideview_zl[point * 2] * size + offset2,
                                                 left_joycon_sideview_zl[point * 2 + 1] * size +
-                                                    (left_pressed ? 1.5f : 1.0f));
+                                                    (left_pressed.value ? 1.5f : 1.0f));
     }
 
     p.setPen(colors.outline);
-    p.setBrush(left_pressed ? colors.highlight : colors.button);
+    p.setBrush(left_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qleft_trigger);
-    p.drawArc(center.x() + 158, center.y() + (left_pressed ? -203.5f : -204.0f), 77, 77, 225 * 16,
-              44 * 16);
+    p.drawArc(center.x() + 158, center.y() + (left_pressed.value ? -203.5f : -204.0f), 77, 77,
+              225 * 16, 44 * 16);
 }
 
 void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF center,
-                                                   bool left_pressed) {
+                                                   const Input::ButtonStatus& left_pressed) {
     std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger;
 
     for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
@@ -2174,7 +2205,7 @@ void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF ce
     }
 
     p.setPen(colors.outline);
-    p.setBrush(left_pressed ? colors.highlight : colors.button);
+    p.setBrush(left_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qleft_trigger);
 
     // Draw L text
@@ -2184,7 +2215,7 @@ void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF ce
 }
 
 void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF center,
-                                                    bool left_pressed) {
+                                                    const Input::ButtonStatus& left_pressed) {
     std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger;
 
     for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
@@ -2193,7 +2224,7 @@ void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF c
     }
 
     p.setPen(colors.outline);
-    p.setBrush(left_pressed ? colors.highlight : colors.button);
+    p.setBrush(left_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qleft_trigger);
 
     // Draw ZL text
@@ -2203,7 +2234,7 @@ void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF c
 }
 
 void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center,
-                                             bool right_pressed) {
+                                             const Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
     constexpr float size = 1.78f;
     constexpr float offset = 311.5f;
@@ -2211,36 +2242,36 @@ void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center,
     for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
         qright_trigger[point] = center + QPointF(-left_joycon_trigger[point * 2] * size - offset,
                                                  left_joycon_trigger[point * 2 + 1] * size -
-                                                     (right_pressed ? 0.5f : 1.0f));
+                                                     (right_pressed.value ? 0.5f : 1.0f));
     }
 
     p.setPen(colors.outline);
-    p.setBrush(right_pressed ? colors.highlight : colors.button);
+    p.setBrush(right_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qright_trigger);
 }
 
 void PlayerControlPreview::DrawRightZTriggers(QPainter& p, const QPointF center,
-                                              bool right_pressed) {
+                                              const Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joycon_sideview_zl.size() / 2> qright_trigger;
     constexpr float size = 1.1115f;
     constexpr float offset2 = 335;
 
     for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) {
         qright_trigger[point] =
-            center +
-            QPointF(-left_joycon_sideview_zl[point * 2] * size - offset2,
-                    left_joycon_sideview_zl[point * 2 + 1] * size + (right_pressed ? 0.5f : 0) + 1);
+            center + QPointF(-left_joycon_sideview_zl[point * 2] * size - offset2,
+                             left_joycon_sideview_zl[point * 2 + 1] * size +
+                                 (right_pressed.value ? 0.5f : 0) + 1);
     }
 
     p.setPen(colors.outline);
-    p.setBrush(right_pressed ? colors.highlight : colors.button);
+    p.setBrush(right_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qright_trigger);
-    p.drawArc(center.x() - 236, center.y() + (right_pressed ? -203.5f : -204.0f), 77, 77, 271 * 16,
-              44 * 16);
+    p.drawArc(center.x() - 236, center.y() + (right_pressed.value ? -203.5f : -204.0f), 77, 77,
+              271 * 16, 44 * 16);
 }
 
 void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF center,
-                                                    bool right_pressed) {
+                                                    const Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger;
 
     for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
@@ -2249,7 +2280,7 @@ void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF c
     }
 
     p.setPen(colors.outline);
-    p.setBrush(right_pressed ? colors.highlight : colors.button);
+    p.setBrush(right_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qright_trigger);
 
     // Draw R text
@@ -2259,7 +2290,7 @@ void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF c
 }
 
 void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF center,
-                                                     bool right_pressed) {
+                                                     const Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger;
 
     for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
@@ -2268,7 +2299,7 @@ void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF
     }
 
     p.setPen(colors.outline);
-    p.setBrush(right_pressed ? colors.highlight : colors.button);
+    p.setBrush(right_pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qright_trigger);
 
     // Draw ZR text
@@ -2278,13 +2309,13 @@ void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF
 }
 
 void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float size,
-                                        bool pressed) {
+                                        const Input::ButtonStatus& pressed) {
     const float radius1 = 13.0f * size;
     const float radius2 = 9.0f * size;
 
     // Outer circle
     p.setPen(colors.outline);
-    p.setBrush(pressed ? colors.highlight : colors.button);
+    p.setBrush(pressed.value ? colors.highlight : colors.button);
     DrawCircle(p, center, radius1);
 
     // Cross
@@ -2292,17 +2323,17 @@ void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float
     p.drawLine(center - QPoint(0, radius1), center + QPoint(0, radius1));
 
     // Inner circle
-    p.setBrush(pressed ? colors.highlight2 : colors.button2);
+    p.setBrush(pressed.value ? colors.highlight2 : colors.button2);
     DrawCircle(p, center, radius2);
 }
 
 void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF center, float angle,
-                                                float size, bool pressed) {
+                                                float size, const Input::ButtonStatus& pressed) {
     QVector<QPointF> joystick;
     joystick.reserve(static_cast<int>(left_joystick_sideview.size() / 2));
 
     for (std::size_t point = 0; point < left_joystick_sideview.size() / 2; ++point) {
-        joystick.append(QPointF(left_joystick_sideview[point * 2] * size + (pressed ? 1 : 0),
+        joystick.append(QPointF(left_joystick_sideview[point * 2] * size + (pressed.value ? 1 : 0),
                                 left_joystick_sideview[point * 2 + 1] * size - 1));
     }
 
@@ -2314,14 +2345,15 @@ void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF cente
 
     // Draw joystick
     p.setPen(colors.outline);
-    p.setBrush(pressed ? colors.highlight : colors.button);
+    p.setBrush(pressed.value ? colors.highlight : colors.button);
     p.drawPolygon(p2);
     p.drawLine(p2.at(1), p2.at(30));
     p.drawLine(p2.at(32), p2.at(71));
 }
 
 void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, const QPointF offset,
-                                           float offset_scalar, bool pressed) {
+                                           float offset_scalar,
+                                           const Input::ButtonStatus& pressed) {
     const float radius1 = 24.0f;
     const float radius2 = 17.0f;
 
@@ -2339,11 +2371,11 @@ void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, co
 
     // Outer circle
     p.setPen(colors.outline);
-    p.setBrush(pressed ? colors.highlight : colors.button);
+    p.setBrush(pressed.value ? colors.highlight : colors.button);
     p.drawEllipse(QPointF(0, 0), radius1 * amplitude, radius1);
 
     // Inner circle
-    p.setBrush(pressed ? colors.highlight2 : colors.button2);
+    p.setBrush(pressed.value ? colors.highlight2 : colors.button2);
 
     const float inner_offset =
         (radius1 - radius2) * 0.4f * ((offset.x() == 0 && offset.y() < 0) ? -1.0f : 1.0f);
@@ -2355,14 +2387,15 @@ void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, co
     p.restore();
 }
 
-void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, bool pressed) {
+void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center,
+                                          const Input::ButtonStatus& pressed) {
     // Outer circle
     p.setPen(colors.outline);
-    p.setBrush(pressed ? colors.highlight : colors.button);
+    p.setBrush(pressed.value ? colors.highlight : colors.button);
     DrawCircle(p, center, 26.0f);
 
     // Inner circle
-    p.setBrush(pressed ? colors.highlight2 : colors.button2);
+    p.setBrush(pressed.value ? colors.highlight2 : colors.button2);
     DrawCircle(p, center, 19.0f);
     p.setBrush(colors.transparent);
     DrawCircle(p, center, 13.5f);
@@ -2371,26 +2404,24 @@ void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, boo
 
 void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right) {
     using namespace Settings::NativeAnalog;
-    if (controller_type != Settings::ControllerType::LeftJoycon) {
-        DrawJoystickProperties(p, center_right, axis_values[RStick].properties);
+    if (controller_type != Core::HID::NpadType::JoyconLeft) {
+        DrawJoystickProperties(p, center_right, stick_values[RStick].x.properties);
         p.setPen(colors.indicator);
         p.setBrush(colors.indicator);
-        DrawJoystickDot(p, center_right, axis_values[RStick].raw_value,
-                        axis_values[RStick].properties);
+        DrawJoystickDot(p, center_right, stick_values[RStick], true);
         p.setPen(colors.indicator2);
         p.setBrush(colors.indicator2);
-        DrawJoystickDot(p, center_right, axis_values[RStick].value, axis_values[RStick].properties);
+        DrawJoystickDot(p, center_right, stick_values[RStick], false);
     }
 
-    if (controller_type != Settings::ControllerType::RightJoycon) {
-        DrawJoystickProperties(p, center_left, axis_values[LStick].properties);
+    if (controller_type != Core::HID::NpadType::JoyconRight) {
+        DrawJoystickProperties(p, center_left, stick_values[LStick].x.properties);
         p.setPen(colors.indicator);
         p.setBrush(colors.indicator);
-        DrawJoystickDot(p, center_left, axis_values[LStick].raw_value,
-                        axis_values[LStick].properties);
+        DrawJoystickDot(p, center_left, stick_values[LStick], true);
         p.setPen(colors.indicator2);
         p.setBrush(colors.indicator2);
-        DrawJoystickDot(p, center_left, axis_values[LStick].value, axis_values[LStick].properties);
+        DrawJoystickDot(p, center_left, stick_values[LStick], false);
     }
 }
 
@@ -2414,19 +2445,26 @@ void PlayerControlPreview::DrawJoystickProperties(QPainter& p, const QPointF cen
     DrawCircle(p, center, deadzone);
 }
 
-void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center, const QPointF value,
-                                           const Input::AnalogProperties& properties) {
+void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center,
+                                           const Input::StickStatus& stick, bool raw) {
     constexpr float size = 45.0f;
-    const float range = size * properties.range;
+    const float range = size * stick.x.properties.range;
 
-    // Dot pointer
-    DrawCircle(p, center + (value * range), 2);
+    if (raw) {
+        const QPointF value = QPointF(stick.x.raw_value, stick.y.raw_value) * size;
+        DrawCircle(p, center + value, 2);
+        return;
+    }
+
+    const QPointF value = QPointF(stick.x.value, stick.y.value) * range;
+    DrawCircle(p, center + value, 2);
 }
 
-void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width,
+void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center,
+                                           const Input::ButtonStatus& pressed, float width,
                                            float height, Direction direction, float radius) {
     p.setBrush(button_color);
-    if (pressed) {
+    if (pressed.value) {
         switch (direction) {
         case Direction::Left:
             center.setX(center.x() - 1);
@@ -2448,17 +2486,17 @@ void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, bool pre
     QRectF rect = {center.x() - width, center.y() - height, width * 2.0f, height * 2.0f};
     p.drawRoundedRect(rect, radius, radius);
 }
-void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center, bool pressed,
-                                           int button_size) {
+void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center,
+                                           const Input::ButtonStatus& pressed, int button_size) {
     p.setPen(colors.outline);
-    p.setBrush(pressed ? colors.highlight : colors.button);
+    p.setBrush(pressed.value ? colors.highlight : colors.button);
     DrawRectangle(p, center, button_size, button_size / 3.0f);
 }
-void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, bool pressed,
-                                          int button_size) {
+void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center,
+                                          const Input::ButtonStatus& pressed, int button_size) {
     // Draw outer line
     p.setPen(colors.outline);
-    p.setBrush(pressed ? colors.highlight : colors.button);
+    p.setBrush(pressed.value ? colors.highlight : colors.button);
     DrawRectangle(p, center, button_size, button_size / 3.0f);
     DrawRectangle(p, center, button_size / 3.0f, button_size);
 
@@ -2471,7 +2509,8 @@ void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, boo
     DrawRectangle(p, center, button_size / 3.0f, button_size);
 }
 
-void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, bool pressed) {
+void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center,
+                                         const Input::ButtonStatus& pressed) {
     std::array<QPointF, gc_button_x.size() / 2> button_x;
 
     for (std::size_t point = 0; point < gc_button_x.size() / 2; ++point) {
@@ -2479,11 +2518,12 @@ void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, bool
     }
 
     p.setPen(colors.outline);
-    p.setBrush(pressed ? colors.highlight : colors.button);
+    p.setBrush(pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, button_x);
 }
 
-void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, bool pressed) {
+void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center,
+                                         const Input::ButtonStatus& pressed) {
     std::array<QPointF, gc_button_y.size() / 2> button_x;
 
     for (std::size_t point = 0; point < gc_button_y.size() / 2; ++point) {
@@ -2491,27 +2531,28 @@ void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, bool
     }
 
     p.setPen(colors.outline);
-    p.setBrush(pressed ? colors.highlight : colors.button);
+    p.setBrush(pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, button_x);
 }
 
-void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center, bool pressed) {
+void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center,
+                                         const Input::ButtonStatus& pressed) {
     std::array<QPointF, gc_button_z.size() / 2> button_x;
 
     for (std::size_t point = 0; point < gc_button_z.size() / 2; ++point) {
         button_x[point] = center + QPointF(gc_button_z[point * 2],
-                                           gc_button_z[point * 2 + 1] + (pressed ? 1 : 0));
+                                           gc_button_z[point * 2 + 1] + (pressed.value ? 1 : 0));
     }
 
     p.setPen(colors.outline);
-    p.setBrush(pressed ? colors.highlight : colors.button2);
+    p.setBrush(pressed.value ? colors.highlight : colors.button2);
     DrawPolygon(p, button_x);
 }
 
-void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center, bool pressed,
-                                            float button_size) {
+void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center,
+                                            const Input::ButtonStatus& pressed, float button_size) {
     p.setBrush(button_color);
-    if (pressed) {
+    if (pressed.value) {
         p.setBrush(colors.highlight);
     }
     p.drawEllipse(center, button_size, button_size);
@@ -2540,7 +2581,8 @@ void PlayerControlPreview::DrawArrowButtonOutline(QPainter& p, const QPointF cen
 }
 
 void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
-                                           const Direction direction, bool pressed, float size) {
+                                           const Direction direction,
+                                           const Input::ButtonStatus& pressed, float size) {
     std::array<QPointF, up_arrow_button.size() / 2> arrow_button;
     QPoint offset;
 
@@ -2567,8 +2609,8 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
     }
 
     // Draw arrow button
-    p.setPen(pressed ? colors.highlight : colors.button);
-    p.setBrush(pressed ? colors.highlight : colors.button);
+    p.setPen(pressed.value ? colors.highlight : colors.button);
+    p.setBrush(pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, arrow_button);
 
     switch (direction) {
@@ -2596,7 +2638,8 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
 }
 
 void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center,
-                                             const Direction direction, bool pressed) {
+                                             const Direction direction,
+                                             const Input::ButtonStatus& pressed) {
     std::array<QPointF, trigger_button.size() / 2> qtrigger_button;
 
     for (std::size_t point = 0; point < trigger_button.size() / 2; ++point) {
@@ -2619,10 +2662,44 @@ void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center,
 
     // Draw arrow button
     p.setPen(colors.outline);
-    p.setBrush(pressed ? colors.highlight : colors.button);
+    p.setBrush(pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qtrigger_button);
 }
 
+void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::BatteryLevel battery) {
+    p.setPen(colors.outline);
+    p.setBrush(colors.transparent);
+    p.drawRect(center.x(), center.y(), 56, 20);
+    p.drawRect(center.x() + 56, center.y() + 6, 3, 8);
+    p.setBrush(colors.deadzone);
+    switch (battery) {
+    case Input::BatteryLevel::Charging:
+        p.setBrush(colors.indicator2);
+        p.drawText(center + QPoint(2, 14), tr("Charging"));
+        break;
+    case Input::BatteryLevel::Full:
+        p.drawRect(center.x() + 42, center.y(), 14, 20);
+        p.drawRect(center.x() + 28, center.y(), 14, 20);
+        p.drawRect(center.x() + 14, center.y(), 14, 20);
+        break;
+    case Input::BatteryLevel::Medium:
+        p.drawRect(center.x() + 28, center.y(), 14, 20);
+        p.drawRect(center.x() + 14, center.y(), 14, 20);
+        p.drawRect(center.x(), center.y(), 14, 20);
+        break;
+    case Input::BatteryLevel::Low:
+        p.drawRect(center.x() + 14, center.y(), 14, 20);
+        p.drawRect(center.x(), center.y(), 14, 20);
+        break;
+    case Input::BatteryLevel::Critical:
+        p.drawRect(center.x(), center.y(), 14, 20);
+        break;
+    case Input::BatteryLevel::Empty:
+        p.drawRect(center.x(), center.y(), 5, 20);
+        break;
+    }
+}
+
 void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol symbol,
                                       float icon_size) {
     std::array<QPointF, house.size() / 2> house_icon;
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index f4bbfa5281..b44a2e347d 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -7,9 +7,10 @@
 #include <array>
 #include <QFrame>
 #include <QPointer>
+#include "common/input.h"
 #include "common/settings.h"
-#include "core/frontend/input.h"
-#include "yuzu/debugger/controller.h"
+#include "core/hid/hid_core.h"
+#include "core/hid/hid_types.h"
 
 class QLabel;
 
@@ -24,17 +25,12 @@ public:
     explicit PlayerControlPreview(QWidget* parent);
     ~PlayerControlPreview() override;
 
-    void SetPlayerInput(std::size_t index, const ButtonParam& buttons_param,
-                        const AnalogParam& analogs_param);
-    void SetPlayerInputRaw(std::size_t index, const Settings::ButtonsRaw& buttons_,
-                           Settings::AnalogsRaw analogs_);
-    void SetConnectedStatus(bool checked);
-    void SetControllerType(Settings::ControllerType type);
+    void SetController(Core::HID::EmulatedController* controller);
     void BeginMappingButton(std::size_t button_id);
     void BeginMappingAnalog(std::size_t button_id);
     void EndMapping();
+    void ControllerUpdate(Core::HID::ControllerTriggerType type);
     void UpdateInput();
-    void SetCallBack(ControllerCallback callback_);
 
 protected:
     void paintEvent(QPaintEvent* event) override;
@@ -63,15 +59,6 @@ private:
         SR,
     };
 
-    struct AxisValue {
-        QPointF value{};
-        QPointF raw_value{};
-        Input::AnalogProperties properties{};
-        int size{};
-        QPoint offset{};
-        bool active{};
-    };
-
     struct LedPattern {
         bool position1;
         bool position2;
@@ -122,47 +109,66 @@ private:
     void DrawGCBody(QPainter& p, QPointF center);
 
     // Draw triggers functions
-    void DrawProTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
-    void DrawGCTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
-    void DrawHandheldTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
-    void DrawDualTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
-    void DrawDualTriggersTopView(QPainter& p, QPointF center, bool left_pressed,
-                                 bool right_pressed);
-    void DrawDualZTriggersTopView(QPainter& p, QPointF center, bool left_pressed,
-                                  bool right_pressed);
-    void DrawLeftTriggers(QPainter& p, QPointF center, bool left_pressed);
-    void DrawLeftZTriggers(QPainter& p, QPointF center, bool left_pressed);
-    void DrawLeftTriggersTopView(QPainter& p, QPointF center, bool left_pressed);
-    void DrawLeftZTriggersTopView(QPainter& p, QPointF center, bool left_pressed);
-    void DrawRightTriggers(QPainter& p, QPointF center, bool right_pressed);
-    void DrawRightZTriggers(QPainter& p, QPointF center, bool right_pressed);
-    void DrawRightTriggersTopView(QPainter& p, QPointF center, bool right_pressed);
-    void DrawRightZTriggersTopView(QPainter& p, QPointF center, bool right_pressed);
+    void DrawProTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed,
+                         const Input::ButtonStatus& right_pressed);
+    void DrawGCTriggers(QPainter& p, QPointF center, Input::TriggerStatus left_trigger,
+                        Input::TriggerStatus right_trigger);
+    void DrawHandheldTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed,
+                              const Input::ButtonStatus& right_pressed);
+    void DrawDualTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed,
+                          const Input::ButtonStatus& right_pressed);
+    void DrawDualTriggersTopView(QPainter& p, QPointF center,
+                                 const Input::ButtonStatus& left_pressed,
+                                 const Input::ButtonStatus& right_pressed);
+    void DrawDualZTriggersTopView(QPainter& p, QPointF center,
+                                  const Input::ButtonStatus& left_pressed,
+                                  const Input::ButtonStatus& right_pressed);
+    void DrawLeftTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed);
+    void DrawLeftZTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed);
+    void DrawLeftTriggersTopView(QPainter& p, QPointF center,
+                                 const Input::ButtonStatus& left_pressed);
+    void DrawLeftZTriggersTopView(QPainter& p, QPointF center,
+                                  const Input::ButtonStatus& left_pressed);
+    void DrawRightTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& right_pressed);
+    void DrawRightZTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& right_pressed);
+    void DrawRightTriggersTopView(QPainter& p, QPointF center,
+                                  const Input::ButtonStatus& right_pressed);
+    void DrawRightZTriggersTopView(QPainter& p, QPointF center,
+                                   const Input::ButtonStatus& right_pressed);
 
     // Draw joystick functions
-    void DrawJoystick(QPainter& p, QPointF center, float size, bool pressed);
-    void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size, bool pressed);
+    void DrawJoystick(QPainter& p, QPointF center, float size, const Input::ButtonStatus& pressed);
+    void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size,
+                              const Input::ButtonStatus& pressed);
     void DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right);
     void DrawJoystickProperties(QPainter& p, QPointF center,
                                 const Input::AnalogProperties& properties);
-    void DrawJoystickDot(QPainter& p, QPointF center, QPointF value,
-                         const Input::AnalogProperties& properties);
-    void DrawProJoystick(QPainter& p, QPointF center, QPointF offset, float scalar, bool pressed);
-    void DrawGCJoystick(QPainter& p, QPointF center, bool pressed);
+    void DrawJoystickDot(QPainter& p, QPointF center, const Input::StickStatus& stick, bool raw);
+    void DrawProJoystick(QPainter& p, QPointF center, QPointF offset, float scalar,
+                         const Input::ButtonStatus& pressed);
+    void DrawGCJoystick(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
 
     // Draw button functions
-    void DrawCircleButton(QPainter& p, QPointF center, bool pressed, float button_size);
-    void DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width, float height,
-                         Direction direction = Direction::None, float radius = 2);
-    void DrawMinusButton(QPainter& p, QPointF center, bool pressed, int button_size);
-    void DrawPlusButton(QPainter& p, QPointF center, bool pressed, int button_size);
-    void DrawGCButtonX(QPainter& p, QPointF center, bool pressed);
-    void DrawGCButtonY(QPainter& p, QPointF center, bool pressed);
-    void DrawGCButtonZ(QPainter& p, QPointF center, bool pressed);
+    void DrawCircleButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
+                          float button_size);
+    void DrawRoundButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
+                         float width, float height, Direction direction = Direction::None,
+                         float radius = 2);
+    void DrawMinusButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
+                         int button_size);
+    void DrawPlusButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
+                        int button_size);
+    void DrawGCButtonX(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
+    void DrawGCButtonY(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
+    void DrawGCButtonZ(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
     void DrawArrowButtonOutline(QPainter& p, const QPointF center, float size = 1.0f);
-    void DrawArrowButton(QPainter& p, QPointF center, Direction direction, bool pressed,
-                         float size = 1.0f);
-    void DrawTriggerButton(QPainter& p, QPointF center, Direction direction, bool pressed);
+    void DrawArrowButton(QPainter& p, QPointF center, Direction direction,
+                         const Input::ButtonStatus& pressed, float size = 1.0f);
+    void DrawTriggerButton(QPainter& p, QPointF center, Direction direction,
+                           const Input::ButtonStatus& pressed);
+
+    // Draw battery functions
+    void DrawBattery(QPainter& p, QPointF center, Input::BatteryLevel battery);
 
     // Draw icon functions
     void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size);
@@ -178,24 +184,23 @@ private:
     void SetTextFont(QPainter& p, float text_size,
                      const QString& font_family = QStringLiteral("sans-serif"));
 
-    using ButtonArray =
-        std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::BUTTON_NS_END>;
-    using StickArray =
-        std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>;
+    bool is_controller_set{};
+    bool is_connected{};
+    bool needs_redraw{};
+    Core::HID::NpadType controller_type;
 
-    ControllerCallback controller_callback;
-    bool is_enabled{};
     bool mapping_active{};
     int blink_counter{};
+    int callback_key;
     QColor button_color{};
     ColorMapping colors{};
     std::array<QColor, 4> led_color{};
-    ButtonArray buttons{};
-    StickArray sticks{};
     std::size_t player_index{};
-    std::size_t button_mapping_index{Settings::NativeButton::BUTTON_NS_END};
-    std::size_t analog_mapping_index{Settings::NativeAnalog::NUM_STICKS_HID};
-    std::array<AxisValue, Settings::NativeAnalog::NUM_STICKS_HID> axis_values{};
-    std::array<bool, Settings::NativeButton::NumButtons> button_values{};
-    Settings::ControllerType controller_type{Settings::ControllerType::ProController};
+    Core::HID::EmulatedController* controller;
+    std::size_t button_mapping_index{Settings::NativeButton::NumButtons};
+    std::size_t analog_mapping_index{Settings::NativeAnalog::NumAnalogs};
+    Core::HID::ButtonValues button_values{};
+    Core::HID::SticksValues stick_values{};
+    Core::HID::TriggerValues trigger_values{};
+    Core::HID::BatteryValues battery_values{};
 };
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp
index f8e08c4222..9fd1a919f2 100644
--- a/src/yuzu/configuration/configure_motion_touch.cpp
+++ b/src/yuzu/configuration/configure_motion_touch.cpp
@@ -15,9 +15,9 @@
 
 #include "common/logging/log.h"
 #include "common/settings.h"
+#include "input_common/drivers/udp_client.h"
+#include "input_common/helpers/udp_protocol.h"
 #include "input_common/main.h"
-#include "input_common/udp/client.h"
-#include "input_common/udp/udp.h"
 #include "ui_configure_motion_touch.h"
 #include "yuzu/configuration/configure_motion_touch.h"
 #include "yuzu/configuration/configure_touch_from_button.h"
diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp
index 2af3afda84..1e7a3751df 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.cpp
+++ b/src/yuzu/configuration/configure_mouse_advanced.cpp
@@ -11,8 +11,11 @@
 
 #include "common/assert.h"
 #include "common/param_package.h"
+#include "input_common/drivers/keyboard.h"
+#include "input_common/drivers/mouse.h"
 #include "input_common/main.h"
 #include "ui_configure_mouse_advanced.h"
+#include "yuzu/bootmanager.h"
 #include "yuzu/configuration/config.h"
 #include "yuzu/configuration/configure_mouse_advanced.h"
 
@@ -101,7 +104,7 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent,
                 [=, this](const Common::ParamPackage& params) {
                     buttons_param[button_id] = params;
                 },
-                InputCommon::Polling::DeviceType::Button);
+                InputCommon::Polling::InputType::Button);
         });
         connect(button, &QPushButton::customContextMenuRequested,
                 [=, this](const QPoint& menu_location) {
@@ -127,13 +130,10 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent,
     connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
 
     connect(poll_timer.get(), &QTimer::timeout, [this] {
-        Common::ParamPackage params;
-        for (auto& poller : device_pollers) {
-            params = poller->GetNextInput();
-            if (params.Has("engine")) {
-                SetPollingResult(params, false);
-                return;
-            }
+        const auto& params = input_subsystem->GetNextInput();
+        if (params.Has("engine")) {
+            SetPollingResult(params, false);
+            return;
         }
     });
 
@@ -196,26 +196,13 @@ void ConfigureMouseAdvanced::UpdateButtonLabels() {
 
 void ConfigureMouseAdvanced::HandleClick(
     QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
-    InputCommon::Polling::DeviceType type) {
+    InputCommon::Polling::InputType type) {
     button->setText(tr("[press key]"));
     button->setFocus();
 
-    // Keyboard keys or mouse buttons can only be used as button devices
-    want_keyboard_mouse = type == InputCommon::Polling::DeviceType::Button;
-    if (want_keyboard_mouse) {
-        const auto iter = std::find(button_map.begin(), button_map.end(), button);
-        ASSERT(iter != button_map.end());
-        const auto index = std::distance(button_map.begin(), iter);
-        ASSERT(index < Settings::NativeButton::NumButtons && index >= 0);
-    }
-
     input_setter = new_input_setter;
 
-    device_pollers = input_subsystem->GetPollers(type);
-
-    for (auto& poller : device_pollers) {
-        poller->Start();
-    }
+    input_subsystem->BeginMapping(type);
 
     QWidget::grabMouse();
     QWidget::grabKeyboard();
@@ -227,9 +214,7 @@ void ConfigureMouseAdvanced::HandleClick(
 void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) {
     timeout_timer->stop();
     poll_timer->stop();
-    for (auto& poller : device_pollers) {
-        poller->Stop();
-    }
+    input_subsystem->StopMapping();
 
     QWidget::releaseMouse();
     QWidget::releaseKeyboard();
@@ -247,15 +232,8 @@ void ConfigureMouseAdvanced::mousePressEvent(QMouseEvent* event) {
         return;
     }
 
-    if (want_keyboard_mouse) {
-        SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())},
-                         false);
-    } else {
-        // We don't want any mouse buttons, so don't stop polling
-        return;
-    }
-
-    SetPollingResult({}, true);
+    const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
+    input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button);
 }
 
 void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) {
@@ -264,13 +242,6 @@ void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) {
     }
 
     if (event->key() != Qt::Key_Escape) {
-        if (want_keyboard_mouse) {
-            SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())},
-                             false);
-        } else {
-            // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling
-            return;
-        }
+        input_subsystem->GetKeyboard()->PressKey(event->key());
     }
-    SetPollingResult({}, true);
 }
diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h
index 65b6fca9aa..5fa534eaf2 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.h
+++ b/src/yuzu/configuration/configure_mouse_advanced.h
@@ -46,7 +46,7 @@ private:
     /// Called when the button was pressed.
     void HandleClick(QPushButton* button,
                      std::function<void(const Common::ParamPackage&)> new_input_setter,
-                     InputCommon::Polling::DeviceType type);
+                     InputCommon::Polling::InputType type);
 
     /// Finish polling and configure input using the input_setter
     void SetPollingResult(const Common::ParamPackage& params, bool abort);
@@ -67,12 +67,6 @@ private:
     std::array<QPushButton*, Settings::NativeMouseButton::NumMouseButtons> button_map;
     std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons> buttons_param;
 
-    std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
-
     std::unique_ptr<QTimer> timeout_timer;
     std::unique_ptr<QTimer> poll_timer;
-
-    /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false,
-    /// keyboard events are ignored.
-    bool want_keyboard_mouse = false;
 };
diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp
index 40129f2289..bde0a08c4b 100644
--- a/src/yuzu/configuration/configure_touch_from_button.cpp
+++ b/src/yuzu/configuration/configure_touch_from_button.cpp
@@ -163,13 +163,10 @@ void ConfigureTouchFromButton::ConnectEvents() {
     connect(timeout_timer.get(), &QTimer::timeout, [this]() { SetPollingResult({}, true); });
 
     connect(poll_timer.get(), &QTimer::timeout, [this]() {
-        Common::ParamPackage params;
-        for (auto& poller : device_pollers) {
-            params = poller->GetNextInput();
-            if (params.Has("engine")) {
-                SetPollingResult(params, false);
-                return;
-            }
+        const auto& params = input_subsystem->GetNextInput();
+        if (params.Has("engine")) {
+            SetPollingResult(params, false);
+            return;
         }
     });
 }
@@ -248,11 +245,7 @@ void ConfigureTouchFromButton::GetButtonInput(const int row_index, const bool is
         }
     };
 
-    device_pollers = input_subsystem->GetPollers(InputCommon::Polling::DeviceType::Button);
-
-    for (auto& poller : device_pollers) {
-        poller->Start();
-    }
+    input_subsystem->BeginMapping(InputCommon::Polling::InputType::Button);
 
     grabKeyboard();
     grabMouse();
@@ -365,14 +358,14 @@ void ConfigureTouchFromButton::SetCoordinates(const int dot_id, const QPoint& po
 
 void ConfigureTouchFromButton::SetPollingResult(const Common::ParamPackage& params,
                                                 const bool cancel) {
+    timeout_timer->stop();
+    poll_timer->stop();
+    input_subsystem->StopMapping();
+
     releaseKeyboard();
     releaseMouse();
     qApp->restoreOverrideCursor();
-    timeout_timer->stop();
-    poll_timer->stop();
-    for (auto& poller : device_pollers) {
-        poller->Stop();
-    }
+
     if (input_setter) {
         (*input_setter)(params, cancel);
         input_setter.reset();
diff --git a/src/yuzu/configuration/configure_touch_from_button.h b/src/yuzu/configuration/configure_touch_from_button.h
index d9513e3bc6..e1400481a2 100644
--- a/src/yuzu/configuration/configure_touch_from_button.h
+++ b/src/yuzu/configuration/configure_touch_from_button.h
@@ -24,10 +24,6 @@ namespace InputCommon {
 class InputSubsystem;
 }
 
-namespace InputCommon::Polling {
-class DevicePoller;
-}
-
 namespace Settings {
 struct TouchFromButtonMap;
 }
@@ -85,7 +81,6 @@ private:
 
     std::unique_ptr<QTimer> timeout_timer;
     std::unique_ptr<QTimer> poll_timer;
-    std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
     std::optional<std::function<void(const Common::ParamPackage&, bool)>> input_setter;
 
     static constexpr int DataRoleDot = Qt::ItemDataRole::UserRole + 2;

From 173a6b1e57c71e8bfe7a1492d5fe9b6b3e81a6cb Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 19:50:30 -0500
Subject: [PATCH 21/88] core/emu_window: Remove touch input

---
 src/core/frontend/emu_window.cpp | 100 ++++---------------------------
 src/core/frontend/emu_window.h   |  30 ++--------
 2 files changed, 16 insertions(+), 114 deletions(-)

diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp
index e1f7e5886b..57c6ffc43b 100644
--- a/src/core/frontend/emu_window.cpp
+++ b/src/core/frontend/emu_window.cpp
@@ -3,66 +3,31 @@
 // Refer to the license.txt file included.
 
 #include <mutex>
-#include "common/settings.h"
 #include "core/frontend/emu_window.h"
-#include "core/frontend/input.h"
 
 namespace Core::Frontend {
 
 GraphicsContext::~GraphicsContext() = default;
 
-class EmuWindow::TouchState : public Input::Factory<Input::TouchDevice>,
-                              public std::enable_shared_from_this<TouchState> {
-public:
-    std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage&) override {
-        return std::make_unique<Device>(shared_from_this());
-    }
-
-    std::mutex mutex;
-
-    Input::TouchStatus status;
-
-private:
-    class Device : public Input::TouchDevice {
-    public:
-        explicit Device(std::weak_ptr<TouchState>&& touch_state_) : touch_state(touch_state_) {}
-        Input::TouchStatus GetStatus() const override {
-            if (auto state = touch_state.lock()) {
-                std::lock_guard guard{state->mutex};
-                return state->status;
-            }
-            return {};
-        }
-
-    private:
-        std::weak_ptr<TouchState> touch_state;
-    };
-};
-
 EmuWindow::EmuWindow() {
     // TODO: Find a better place to set this.
     config.min_client_area_size =
         std::make_pair(Layout::MinimumSize::Width, Layout::MinimumSize::Height);
     active_config = config;
-    touch_state = std::make_shared<TouchState>();
-    Input::RegisterFactory<Input::TouchDevice>("emu_window", touch_state);
 }
 
-EmuWindow::~EmuWindow() {
-    Input::UnregisterFactory<Input::TouchDevice>("emu_window");
-}
+EmuWindow::~EmuWindow() {}
 
-/**
- * Check if the given x/y coordinates are within the touchpad specified by the framebuffer layout
- * @param layout FramebufferLayout object describing the framebuffer size and screen positions
- * @param framebuffer_x Framebuffer x-coordinate to check
- * @param framebuffer_y Framebuffer y-coordinate to check
- * @return True if the coordinates are within the touchpad, otherwise false
- */
-static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, u32 framebuffer_x,
-                                u32 framebuffer_y) {
-    return (framebuffer_y >= layout.screen.top && framebuffer_y < layout.screen.bottom &&
-            framebuffer_x >= layout.screen.left && framebuffer_x < layout.screen.right);
+std::pair<f32, f32> EmuWindow::MapToTouchScreen(u32 framebuffer_x, u32 framebuffer_y) const {
+    std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y);
+    const float x =
+        static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) /
+        static_cast<float>(framebuffer_layout.screen.right - framebuffer_layout.screen.left);
+    const float y =
+        static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) /
+        static_cast<float>(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top);
+
+    return std::make_pair(x, y);
 }
 
 std::pair<u32, u32> EmuWindow::ClipToTouchScreen(u32 new_x, u32 new_y) const {
@@ -75,49 +40,6 @@ std::pair<u32, u32> EmuWindow::ClipToTouchScreen(u32 new_x, u32 new_y) const {
     return std::make_pair(new_x, new_y);
 }
 
-void EmuWindow::TouchPressed(u32 framebuffer_x, u32 framebuffer_y, size_t id) {
-    if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) {
-        return;
-    }
-    if (id >= touch_state->status.size()) {
-        return;
-    }
-
-    std::lock_guard guard{touch_state->mutex};
-    const float x =
-        static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) /
-        static_cast<float>(framebuffer_layout.screen.right - framebuffer_layout.screen.left);
-    const float y =
-        static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) /
-        static_cast<float>(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top);
-
-    touch_state->status[id] = std::make_tuple(x, y, true);
-}
-
-void EmuWindow::TouchReleased(size_t id) {
-    if (id >= touch_state->status.size()) {
-        return;
-    }
-    std::lock_guard guard{touch_state->mutex};
-    touch_state->status[id] = std::make_tuple(0.0f, 0.0f, false);
-}
-
-void EmuWindow::TouchMoved(u32 framebuffer_x, u32 framebuffer_y, size_t id) {
-    if (id >= touch_state->status.size()) {
-        return;
-    }
-
-    if (!std::get<2>(touch_state->status[id])) {
-        return;
-    }
-
-    if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) {
-        std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y);
-    }
-
-    TouchPressed(framebuffer_x, framebuffer_y, id);
-}
-
 void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height) {
     NotifyFramebufferLayoutChanged(Layout::DefaultFrameLayout(width, height));
 }
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h
index 8a86a1d276..e413a520ab 100644
--- a/src/core/frontend/emu_window.h
+++ b/src/core/frontend/emu_window.h
@@ -112,28 +112,6 @@ public:
     /// Returns if window is shown (not minimized)
     virtual bool IsShown() const = 0;
 
-    /**
-     * Signal that a touch pressed event has occurred (e.g. mouse click pressed)
-     * @param framebuffer_x Framebuffer x-coordinate that was pressed
-     * @param framebuffer_y Framebuffer y-coordinate that was pressed
-     * @param id Touch event ID
-     */
-    void TouchPressed(u32 framebuffer_x, u32 framebuffer_y, size_t id);
-
-    /**
-     * Signal that a touch released event has occurred (e.g. mouse click released)
-     * @param id Touch event ID
-     */
-    void TouchReleased(size_t id);
-
-    /**
-     * Signal that a touch movement event has occurred (e.g. mouse was moved over the emu window)
-     * @param framebuffer_x Framebuffer x-coordinate
-     * @param framebuffer_y Framebuffer y-coordinate
-     * @param id Touch event ID
-     */
-    void TouchMoved(u32 framebuffer_x, u32 framebuffer_y, size_t id);
-
     /**
      * Returns currently active configuration.
      * @note Accesses to the returned object need not be consistent because it may be modified in
@@ -212,6 +190,11 @@ protected:
         client_area_height = size.second;
     }
 
+    /**
+     * Converts a screen postion into the equivalent touchscreen position.
+     */
+    std::pair<f32, f32> MapToTouchScreen(u32 framebuffer_x, u32 framebuffer_y) const;
+
     WindowSystemInfo window_info;
 
 private:
@@ -237,9 +220,6 @@ private:
     WindowConfig config;        ///< Internal configuration (changes pending for being applied in
                                 /// ProcessConfigurationChanges)
     WindowConfig active_config; ///< Internal active configuration
-
-    class TouchState;
-    std::shared_ptr<TouchState> touch_state;
 };
 
 } // namespace Core::Frontend

From 456397ed39a6966e1a1e333090e778c0d3414858 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 19:59:09 -0500
Subject: [PATCH 22/88] debugger/controller: Remove TAS

---
 src/yuzu/debugger/controller.cpp | 32 ++++----------------------------
 src/yuzu/debugger/controller.h   | 19 +------------------
 2 files changed, 5 insertions(+), 46 deletions(-)

diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
index 0e190a3d58..d8e41f8b69 100644
--- a/src/yuzu/debugger/controller.cpp
+++ b/src/yuzu/debugger/controller.cpp
@@ -6,12 +6,11 @@
 #include <QLayout>
 #include <QString>
 #include "common/settings.h"
-#include "input_common/main.h"
+#include "core/core.h"
 #include "yuzu/configuration/configure_input_player_widget.h"
 #include "yuzu/debugger/controller.h"
 
-ControllerDialog::ControllerDialog(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_)
-    : QWidget(parent, Qt::Dialog), input_subsystem{input_subsystem_} {
+ControllerDialog::ControllerDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) {
     setObjectName(QStringLiteral("Controller"));
     setWindowTitle(tr("Controller P1"));
     resize(500, 350);
@@ -21,7 +20,8 @@ ControllerDialog::ControllerDialog(QWidget* parent, InputCommon::InputSubsystem*
                    Qt::WindowMaximizeButtonHint);
 
     widget = new PlayerControlPreview(this);
-    refreshConfiguration();
+    widget->SetController(Core::System::GetInstance().HIDCore().GetEmulatedController(
+        Core::HID::NpadIdType::Player1));
     QLayout* layout = new QVBoxLayout(this);
     layout->setContentsMargins(0, 0, 0, 0);
     layout->addWidget(widget);
@@ -30,22 +30,10 @@ ControllerDialog::ControllerDialog(QWidget* parent, InputCommon::InputSubsystem*
     // Configure focus so that widget is focusable and the dialog automatically forwards focus to
     // it.
     setFocusProxy(widget);
-    widget->SetConnectedStatus(false);
     widget->setFocusPolicy(Qt::StrongFocus);
     widget->setFocus();
 }
 
-void ControllerDialog::refreshConfiguration() {
-    const auto& players = Settings::values.players.GetValue();
-    constexpr std::size_t player = 0;
-    widget->SetPlayerInputRaw(player, players[player].buttons, players[player].analogs);
-    widget->SetControllerType(players[player].controller_type);
-    ControllerCallback callback{[this](ControllerInput input) { InputController(input); }};
-    widget->SetCallBack(callback);
-    widget->repaint();
-    widget->SetConnectedStatus(players[player].connected);
-}
-
 QAction* ControllerDialog::toggleViewAction() {
     if (toggle_view_action == nullptr) {
         toggle_view_action = new QAction(tr("&Controller P1"), this);
@@ -61,7 +49,6 @@ void ControllerDialog::showEvent(QShowEvent* ev) {
     if (toggle_view_action) {
         toggle_view_action->setChecked(isVisible());
     }
-    refreshConfiguration();
     QWidget::showEvent(ev);
 }
 
@@ -69,16 +56,5 @@ void ControllerDialog::hideEvent(QHideEvent* ev) {
     if (toggle_view_action) {
         toggle_view_action->setChecked(isVisible());
     }
-    widget->SetConnectedStatus(false);
     QWidget::hideEvent(ev);
 }
-
-void ControllerDialog::InputController(ControllerInput input) {
-    u32 buttons = 0;
-    int index = 0;
-    for (bool btn : input.button_values) {
-        buttons |= (btn ? 1U : 0U) << index;
-        index++;
-    }
-    //input_subsystem->GetTas()->RecordInput(buttons, input.axis_values);
-}
diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h
index 7742db58b6..697489cbbd 100644
--- a/src/yuzu/debugger/controller.h
+++ b/src/yuzu/debugger/controller.h
@@ -4,9 +4,7 @@
 
 #pragma once
 
-#include <QFileSystemWatcher>
 #include <QWidget>
-#include "common/settings.h"
 
 class QAction;
 class QHideEvent;
@@ -17,35 +15,20 @@ namespace InputCommon {
 class InputSubsystem;
 }
 
-struct ControllerInput {
-    std::array<std::pair<float, float>, Settings::NativeAnalog::NUM_STICKS_HID> axis_values{};
-    std::array<bool, Settings::NativeButton::NumButtons> button_values{};
-    bool changed{};
-};
-
-struct ControllerCallback {
-    std::function<void(ControllerInput)> input;
-};
-
 class ControllerDialog : public QWidget {
     Q_OBJECT
 
 public:
-    explicit ControllerDialog(QWidget* parent = nullptr,
-                              InputCommon::InputSubsystem* input_subsystem_ = nullptr);
+    explicit ControllerDialog(QWidget* parent = nullptr);
 
     /// Returns a QAction that can be used to toggle visibility of this dialog.
     QAction* toggleViewAction();
-    void refreshConfiguration();
 
 protected:
     void showEvent(QShowEvent* ev) override;
     void hideEvent(QHideEvent* ev) override;
 
 private:
-    void InputController(ControllerInput input);
     QAction* toggle_view_action = nullptr;
-    QFileSystemWatcher* watcher = nullptr;
     PlayerControlPreview* widget;
-    InputCommon::InputSubsystem* input_subsystem;
 };

From 6e2c84042d296272a2186feac67678c19fdb122b Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:18:26 -0500
Subject: [PATCH 23/88] settings: Cleanup settings

---
 src/common/settings.h                            |  3 ---
 src/common/settings_input.h                      | 13 ++++++++++++-
 src/core/hle/service/hid/controllers/debug_pad.h |  2 +-
 src/core/hle/service/hid/controllers/mouse.cpp   |  2 +-
 src/core/hle/service/hid/controllers/npad.h      |  2 +-
 src/core/hle/service/hid/hid.cpp                 |  3 +--
 6 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/src/common/settings.h b/src/common/settings.h
index fa4aa87476..4cf28617c6 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -572,7 +572,6 @@ struct Values {
     BasicSetting<bool> mouse_panning{false, "mouse_panning"};
     BasicRangedSetting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
     BasicSetting<bool> mouse_enabled{false, "mouse_enabled"};
-    std::string mouse_device;
     MouseButtonsRaw mouse_buttons;
 
     BasicSetting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};
@@ -592,8 +591,6 @@ struct Values {
     BasicSetting<int> touch_from_button_map_index{0, "touch_from_button_map"};
     std::vector<TouchFromButtonMap> touch_from_button_maps;
 
-    std::atomic_bool is_device_reload_pending{true};
-
     // Data Storage
     BasicSetting<bool> use_virtual_sd{true, "use_virtual_sd"};
     BasicSetting<bool> gamecard_inserted{false, "gamecard_inserted"};
diff --git a/src/common/settings_input.h b/src/common/settings_input.h
index 6096005822..2c0eb31d39 100644
--- a/src/common/settings_input.h
+++ b/src/common/settings_input.h
@@ -62,11 +62,22 @@ enum Values : int {
 
 constexpr int STICK_HID_BEGIN = LStick;
 constexpr int STICK_HID_END = NumAnalogs;
-constexpr int NUM_STICKS_HID = NumAnalogs;
 
 extern const std::array<const char*, NumAnalogs> mapping;
 } // namespace NativeAnalog
 
+namespace NativeTrigger {
+enum Values : int {
+    LTrigger,
+    RTrigger,
+
+    NumTriggers,
+};
+
+constexpr int TRIGGER_HID_BEGIN = LTrigger;
+constexpr int TRIGGER_HID_END = NumTriggers;
+} // namespace NativeTrigger
+
 namespace NativeVibration {
 enum Values : int {
     LeftVibrationDevice,
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 1b1645184d..e90ae8415c 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -87,7 +87,7 @@ private:
 
     std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
         buttons;
-    std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>
+    std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NumAnalogs>
         analogs;
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 544a719481..2211f11447 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -61,7 +61,7 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
 }
 
 void Controller_Mouse::OnLoadInputDevices() {
-    mouse_device = Input::CreateDevice<Input::MouseDevice>(Settings::values.mouse_device);
+    //mouse_device = Input::CreateDevice<Input::MouseDevice>(Settings::values.mouse_device);
     std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(),
                    mouse_button_devices.begin(), Input::CreateDevice<Input::ButtonDevice>);
 }
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 9ee146caf7..f3e868bdbb 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -563,7 +563,7 @@ private:
         std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>,
         10>;
     using StickArray = std::array<
-        std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>,
+        std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NumAnalogs>,
         10>;
     using VibrationArray = std::array<std::array<std::unique_ptr<Input::VibrationDevice>,
                                                  Settings::NativeVibration::NUM_VIBRATIONS_HID>,
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 10c64d41a3..9a5b60263d 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -117,7 +117,7 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
                                         std::chrono::nanoseconds ns_late) {
     auto& core_timing = system.CoreTiming();
 
-    const bool should_reload = Settings::values.is_device_reload_pending.exchange(false);
+    const bool should_reload = false;
     for (const auto& controller : controllers) {
         if (should_reload) {
             controller->OnLoadInputDevices();
@@ -2038,7 +2038,6 @@ public:
 };
 
 void ReloadInputDevices() {
-    Settings::values.is_device_reload_pending.store(true);
 }
 
 void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {

From 8fff6d6c67dbdaed8be639b0daeb9afdf8e53d59 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:19:28 -0500
Subject: [PATCH 24/88] Qt_applets: Use new input

---
 src/yuzu/applets/qt_controller.cpp        |  6 +-
 src/yuzu/applets/qt_controller.h          |  5 ++
 src/yuzu/applets/qt_software_keyboard.cpp | 89 ++++++++++++-----------
 src/yuzu/applets/qt_software_keyboard.h   | 12 +--
 src/yuzu/applets/qt_web_browser.cpp       |  3 +-
 5 files changed, 67 insertions(+), 48 deletions(-)

diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index bf8445a893..4dd577a181 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -6,8 +6,11 @@
 #include <thread>
 
 #include "common/assert.h"
+#include "common/param_package.h"
 #include "common/string_util.h"
 #include "core/core.h"
+#include "core/hid/emulated_controller.h
+#include "core/hid/hid_types.h
 #include "core/hle/lock.h"
 #include "core/hle/service/hid/controllers/npad.h"
 #include "core/hle/service/hid/hid.h"
@@ -48,7 +51,8 @@ void UpdateController(Settings::ControllerType controller_type, std::size_t npad
             ->GetAppletResource()
             ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
 
-    npad.UpdateControllerAt(npad.MapSettingsTypeToNPad(controller_type), npad_index, connected);
+    npad.UpdateControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(controller_type),
+                            npad_index, connected);
 }
 
 // Returns true if the given controller type is compatible with the given parameters.
diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h
index 037325f504..98060e6f81 100644
--- a/src/yuzu/applets/qt_controller.h
+++ b/src/yuzu/applets/qt_controller.h
@@ -31,6 +31,10 @@ namespace Ui {
 class QtControllerSelectorDialog;
 }
 
+namespace Core {
+class System;
+}
+
 class QtControllerSelectorDialog final : public QDialog {
     Q_OBJECT
 
@@ -102,6 +106,7 @@ private:
     Core::Frontend::ControllerParameters parameters;
 
     InputCommon::InputSubsystem* input_subsystem;
+    Core::System& system;
 
     std::unique_ptr<InputProfiles> input_profiles;
 
diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp
index a83a11a956..7e87312322 100644
--- a/src/yuzu/applets/qt_software_keyboard.cpp
+++ b/src/yuzu/applets/qt_software_keyboard.cpp
@@ -10,7 +10,8 @@
 #include "common/settings.h"
 #include "common/string_util.h"
 #include "core/core.h"
-#include "core/frontend/input_interpreter.h"
+#include "core/hid/hid_types.h"
+#include "core/hid/input_interpreter.h"
 #include "ui_qt_software_keyboard.h"
 #include "yuzu/applets/qt_software_keyboard.h"
 #include "yuzu/main.h"
@@ -484,7 +485,7 @@ void QtSoftwareKeyboardDialog::open() {
 void QtSoftwareKeyboardDialog::reject() {
     // Pressing the ESC key in a dialog calls QDialog::reject().
     // We will override this behavior to the "Cancel" action on the software keyboard.
-    TranslateButtonPress(HIDButton::X);
+    TranslateButtonPress(Core::HID::NpadButton::X);
 }
 
 void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) {
@@ -722,7 +723,7 @@ void QtSoftwareKeyboardDialog::SetTextDrawType() {
 
         connect(
             ui->line_edit_osk, &QLineEdit::returnPressed, this,
-            [this] { TranslateButtonPress(HIDButton::Plus); }, Qt::QueuedConnection);
+            [this] { TranslateButtonPress(Core::HID::NpadButton::Plus); }, Qt::QueuedConnection);
 
         ui->line_edit_osk->setPlaceholderText(
             QString::fromStdU16String(initialize_parameters.guide_text));
@@ -1208,9 +1209,9 @@ void QtSoftwareKeyboardDialog::SetupMouseHover() {
     }
 }
 
-template <HIDButton... T>
+template <Core::HID::NpadButton... T>
 void QtSoftwareKeyboardDialog::HandleButtonPressedOnce() {
-    const auto f = [this](HIDButton button) {
+    const auto f = [this](Core::HID::NpadButton button) {
         if (input_interpreter->IsButtonPressedOnce(button)) {
             TranslateButtonPress(button);
         }
@@ -1219,9 +1220,9 @@ void QtSoftwareKeyboardDialog::HandleButtonPressedOnce() {
     (f(T), ...);
 }
 
-template <HIDButton... T>
+template <Core::HID::NpadButton... T>
 void QtSoftwareKeyboardDialog::HandleButtonHold() {
-    const auto f = [this](HIDButton button) {
+    const auto f = [this](Core::HID::NpadButton button) {
         if (input_interpreter->IsButtonHeld(button)) {
             TranslateButtonPress(button);
         }
@@ -1230,9 +1231,9 @@ void QtSoftwareKeyboardDialog::HandleButtonHold() {
     (f(T), ...);
 }
 
-void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) {
+void QtSoftwareKeyboardDialog::TranslateButtonPress(Core::HID::NpadButton button) {
     switch (button) {
-    case HIDButton::A:
+    case Core::HID::NpadButton::A:
         switch (bottom_osk_index) {
         case BottomOSKIndex::LowerCase:
         case BottomOSKIndex::UpperCase:
@@ -1245,7 +1246,7 @@ void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) {
             break;
         }
         break;
-    case HIDButton::B:
+    case Core::HID::NpadButton::B:
         switch (bottom_osk_index) {
         case BottomOSKIndex::LowerCase:
             ui->button_backspace->click();
@@ -1260,7 +1261,7 @@ void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) {
             break;
         }
         break;
-    case HIDButton::X:
+    case Core::HID::NpadButton::X:
         if (is_inline) {
             emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position);
         } else {
@@ -1271,7 +1272,7 @@ void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) {
             emit SubmitNormalText(SwkbdResult::Cancel, std::move(text));
         }
         break;
-    case HIDButton::Y:
+    case Core::HID::NpadButton::Y:
         switch (bottom_osk_index) {
         case BottomOSKIndex::LowerCase:
             ui->button_space->click();
@@ -1284,8 +1285,8 @@ void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) {
             break;
         }
         break;
-    case HIDButton::LStick:
-    case HIDButton::RStick:
+    case Core::HID::NpadButton::StickL:
+    case Core::HID::NpadButton::StickR:
         switch (bottom_osk_index) {
         case BottomOSKIndex::LowerCase:
             ui->button_shift->click();
@@ -1298,13 +1299,13 @@ void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) {
             break;
         }
         break;
-    case HIDButton::L:
+    case Core::HID::NpadButton::L:
         MoveTextCursorDirection(Direction::Left);
         break;
-    case HIDButton::R:
+    case Core::HID::NpadButton::R:
         MoveTextCursorDirection(Direction::Right);
         break;
-    case HIDButton::Plus:
+    case Core::HID::NpadButton::Plus:
         switch (bottom_osk_index) {
         case BottomOSKIndex::LowerCase:
             ui->button_ok->click();
@@ -1319,24 +1320,24 @@ void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) {
             break;
         }
         break;
-    case HIDButton::DLeft:
-    case HIDButton::LStickLeft:
-    case HIDButton::RStickLeft:
+    case Core::HID::NpadButton::Left:
+    case Core::HID::NpadButton::StickLLeft:
+    case Core::HID::NpadButton::StickRLeft:
         MoveButtonDirection(Direction::Left);
         break;
-    case HIDButton::DUp:
-    case HIDButton::LStickUp:
-    case HIDButton::RStickUp:
+    case Core::HID::NpadButton::Up:
+    case Core::HID::NpadButton::StickLUp:
+    case Core::HID::NpadButton::StickRUp:
         MoveButtonDirection(Direction::Up);
         break;
-    case HIDButton::DRight:
-    case HIDButton::LStickRight:
-    case HIDButton::RStickRight:
+    case Core::HID::NpadButton::Right:
+    case Core::HID::NpadButton::StickLRight:
+    case Core::HID::NpadButton::StickRRight:
         MoveButtonDirection(Direction::Right);
         break;
-    case HIDButton::DDown:
-    case HIDButton::LStickDown:
-    case HIDButton::RStickDown:
+    case Core::HID::NpadButton::Down:
+    case Core::HID::NpadButton::StickLDown:
+    case Core::HID::NpadButton::StickRDown:
         MoveButtonDirection(Direction::Down);
         break;
     default:
@@ -1467,19 +1468,25 @@ void QtSoftwareKeyboardDialog::InputThread() {
     while (input_thread_running) {
         input_interpreter->PollInput();
 
-        HandleButtonPressedOnce<HIDButton::A, HIDButton::B, HIDButton::X, HIDButton::Y,
-                                HIDButton::LStick, HIDButton::RStick, HIDButton::L, HIDButton::R,
-                                HIDButton::Plus, HIDButton::DLeft, HIDButton::DUp,
-                                HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft,
-                                HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown,
-                                HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight,
-                                HIDButton::RStickDown>();
+        HandleButtonPressedOnce<
+            Core::HID::NpadButton::A, Core::HID::NpadButton::B, Core::HID::NpadButton::X,
+            Core::HID::NpadButton::Y, Core::HID::NpadButton::StickL, Core::HID::NpadButton::StickR,
+            Core::HID::NpadButton::L, Core::HID::NpadButton::R, Core::HID::NpadButton::Plus,
+            Core::HID::NpadButton::Left, Core::HID::NpadButton::Up, Core::HID::NpadButton::Right,
+            Core::HID::NpadButton::Down, Core::HID::NpadButton::StickLLeft,
+            Core::HID::NpadButton::StickLUp, Core::HID::NpadButton::StickLRight,
+            Core::HID::NpadButton::StickLDown, Core::HID::NpadButton::StickRLeft,
+            Core::HID::NpadButton::StickRUp, Core::HID::NpadButton::StickRRight,
+            Core::HID::NpadButton::StickRDown>();
 
-        HandleButtonHold<HIDButton::B, HIDButton::L, HIDButton::R, HIDButton::DLeft, HIDButton::DUp,
-                         HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft,
-                         HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown,
-                         HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight,
-                         HIDButton::RStickDown>();
+        HandleButtonHold<Core::HID::NpadButton::B, Core::HID::NpadButton::L,
+                         Core::HID::NpadButton::R, Core::HID::NpadButton::Left,
+                         Core::HID::NpadButton::Up, Core::HID::NpadButton::Right,
+                         Core::HID::NpadButton::Down, Core::HID::NpadButton::StickLLeft,
+                         Core::HID::NpadButton::StickLUp, Core::HID::NpadButton::StickLRight,
+                         Core::HID::NpadButton::StickLDown, Core::HID::NpadButton::StickRLeft,
+                         Core::HID::NpadButton::StickRUp, Core::HID::NpadButton::StickRRight,
+                         Core::HID::NpadButton::StickRDown>();
 
         std::this_thread::sleep_for(std::chrono::milliseconds(50));
     }
diff --git a/src/yuzu/applets/qt_software_keyboard.h b/src/yuzu/applets/qt_software_keyboard.h
index 592d9c085b..b030cdcf7c 100644
--- a/src/yuzu/applets/qt_software_keyboard.h
+++ b/src/yuzu/applets/qt_software_keyboard.h
@@ -14,14 +14,16 @@
 
 #include "core/frontend/applets/software_keyboard.h"
 
-enum class HIDButton : u8;
-
 class InputInterpreter;
 
 namespace Core {
 class System;
 }
 
+namespace Core::HID {
+enum class NpadButton : u64;
+}
+
 namespace Ui {
 class QtSoftwareKeyboardDialog;
 }
@@ -146,7 +148,7 @@ private:
      *
      * @tparam HIDButton The list of buttons that can be converted into keyboard input.
      */
-    template <HIDButton... T>
+    template <Core::HID::NpadButton... T>
     void HandleButtonPressedOnce();
 
     /**
@@ -154,7 +156,7 @@ private:
      *
      * @tparam HIDButton The list of buttons that can be converted into keyboard input.
      */
-    template <HIDButton... T>
+    template <Core::HID::NpadButton... T>
     void HandleButtonHold();
 
     /**
@@ -162,7 +164,7 @@ private:
      *
      * @param button The button press to process.
      */
-    void TranslateButtonPress(HIDButton button);
+    void TranslateButtonPress(Core::HID::NpadButton button);
 
     /**
      * Moves the focus of a button in a certain direction.
diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp
index 24d72a4960..8e190f9fef 100644
--- a/src/yuzu/applets/qt_web_browser.cpp
+++ b/src/yuzu/applets/qt_web_browser.cpp
@@ -14,9 +14,10 @@
 #endif
 
 #include "common/fs/path_util.h"
+#include "common/param_package.h"
 #include "core/core.h"
 #include "core/hid/input_interpreter.h"
-#include "input_common/keyboard.h"
+#include "input_common/drivers/keyboard.h"
 #include "input_common/main.h"
 #include "yuzu/applets/qt_web_browser.h"
 #include "yuzu/applets/qt_web_browser_scripts.h"

From db08721dccdec9330b883324e2a99d784c2405fd Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:25:22 -0500
Subject: [PATCH 25/88] service/hid: Create ring LIFO

---
 src/core/CMakeLists.txt              |  2 +-
 src/core/hle/service/hid/ring_lifo.h | 54 ++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 src/core/hle/service/hid/ring_lifo.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 09163fab97..582c15f7e7 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -132,7 +132,6 @@ add_library(core STATIC
     frontend/emu_window.h
     frontend/framebuffer_layout.cpp
     frontend/framebuffer_layout.h
-    frontend/input.h
     hardware_interrupt_manager.cpp
     hardware_interrupt_manager.h
     hid/emulated_console.cpp
@@ -415,6 +414,7 @@ add_library(core STATIC
     hle/service/hid/hid.h
     hle/service/hid/irs.cpp
     hle/service/hid/irs.h
+    hle/service/hid/ring_lifo.h
     hle/service/hid/xcd.cpp
     hle/service/hid/xcd.h
     hle/service/hid/errors.h
diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h
new file mode 100644
index 0000000000..1cc2a194f0
--- /dev/null
+++ b/src/core/hle/service/hid/ring_lifo.h
@@ -0,0 +1,54 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#pragma once
+
+#include "common/common_types.h"
+#include "common/swap.h"
+
+namespace Service::HID {
+constexpr std::size_t max_entry_size = 17;
+
+template <typename State>
+struct AtomicStorage {
+    s64_le sampling_number;
+    State state;
+};
+
+template <typename State>
+struct Lifo {
+    s64_le timestamp{};
+    s64_le total_entry_count = max_entry_size;
+    s64_le last_entry_index{};
+    s64_le entry_count{};
+    std::array<AtomicStorage<State>, max_entry_size> entries{};
+
+    const AtomicStorage<State>& ReadCurrentEntry() const {
+        return entries[last_entry_index];
+    }
+
+    const AtomicStorage<State>& ReadPreviousEntry() const {
+        return entries[GetPreviuousEntryIndex()];
+    }
+
+    std::size_t GetPreviuousEntryIndex() const {
+        return (last_entry_index + total_entry_count - 1) % total_entry_count;
+    }
+
+    std::size_t GetNextEntryIndex() const {
+        return (last_entry_index + 1) % total_entry_count;
+    }
+
+    void WriteNextEntry(const State& new_state) {
+        if (entry_count < total_entry_count - 1) {
+            entry_count++;
+        }
+        last_entry_index = GetNextEntryIndex();
+        const auto& previous_entry = ReadPreviousEntry();
+        entries[last_entry_index].sampling_number = previous_entry.sampling_number + 1;
+        entries[last_entry_index].state = new_state;
+    }
+};
+
+} // namespace Service::HID

From dbe030110256876438cf568314e3ffb60cd89952 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:29:00 -0500
Subject: [PATCH 26/88] service/hid: Use remove duplicated code, update names

---
 src/core/hle/service/hid/hid.cpp | 67 ++++++++++++++------------------
 src/core/hle/service/hid/hid.h   | 27 -------------
 2 files changed, 30 insertions(+), 64 deletions(-)

diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 9a5b60263d..18f29bb78d 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -9,6 +9,7 @@
 #include "core/core.h"
 #include "core/core_timing.h"
 #include "core/frontend/input.h"
+#include "core/hardware_properties.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_shared_memory.h"
@@ -34,10 +35,9 @@
 namespace Service::HID {
 
 // Updating period for each HID device.
-// HID is polled every 15ms, this value was derived from
-// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet
-constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000};         // (1ms, 1000Hz)
-constexpr auto motion_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.666Hz)
+// Period time is obtained by measuring the number of samples in a second
+constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000};    // (4ms, 250Hz)
+constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
 constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
 
 IAppletResource::IAppletResource(Core::System& system_,
@@ -89,7 +89,7 @@ IAppletResource::IAppletResource(Core::System& system_,
     system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
     system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event);
 
-    ReloadInputDevices();
+    system.HIDCore().ReloadInputDevices();
 }
 
 void IAppletResource::ActivateController(HidController controller) {
@@ -117,11 +117,7 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
                                         std::chrono::nanoseconds ns_late) {
     auto& core_timing = system.CoreTiming();
 
-    const bool should_reload = false;
     for (const auto& controller : controllers) {
-        if (should_reload) {
-            controller->OnLoadInputDevices();
-        }
         controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(),
                              SHARED_MEMORY_SIZE);
     }
@@ -891,7 +887,7 @@ void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) {
 void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     const auto applet_resource_user_id{rp.Pop<u64>()};
-    const auto hold_type{rp.PopEnum<Controller_NPad::NpadHoldType>()};
+    const auto hold_type{rp.PopEnum<Controller_NPad::NpadJoyHoldType>()};
 
     applet_resource->GetController<Controller_NPad>(HidController::NPad).SetHoldType(hold_type);
 
@@ -924,7 +920,7 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx
     const auto parameters{rp.PopRaw<Parameters>()};
 
     applet_resource->GetController<Controller_NPad>(HidController::NPad)
-        .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single);
+        .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single);
 
     LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
                 parameters.npad_id, parameters.applet_resource_user_id);
@@ -946,7 +942,7 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
     const auto parameters{rp.PopRaw<Parameters>()};
 
     applet_resource->GetController<Controller_NPad>(HidController::NPad)
-        .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single);
+        .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single);
 
     LOG_WARNING(Service_HID,
                 "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
@@ -968,7 +964,7 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
     const auto parameters{rp.PopRaw<Parameters>()};
 
     applet_resource->GetController<Controller_NPad>(HidController::NPad)
-        .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Dual);
+        .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Dual);
 
     LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
                 parameters.npad_id, parameters.applet_resource_user_id);
@@ -1134,36 +1130,36 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()};
 
-    VibrationDeviceInfo vibration_device_info;
+    Core::HID::VibrationDeviceInfo vibration_device_info;
 
     switch (vibration_device_handle.npad_type) {
-    case Controller_NPad::NpadType::ProController:
-    case Controller_NPad::NpadType::Handheld:
-    case Controller_NPad::NpadType::JoyconDual:
-    case Controller_NPad::NpadType::JoyconLeft:
-    case Controller_NPad::NpadType::JoyconRight:
+    case Core::HID::NpadType::ProController:
+    case Core::HID::NpadType::Handheld:
+    case Core::HID::NpadType::JoyconDual:
+    case Core::HID::NpadType::JoyconLeft:
+    case Core::HID::NpadType::JoyconRight:
     default:
-        vibration_device_info.type = VibrationDeviceType::LinearResonantActuator;
+        vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator;
         break;
-    case Controller_NPad::NpadType::GameCube:
-        vibration_device_info.type = VibrationDeviceType::GcErm;
+    case Core::HID::NpadType::GameCube:
+        vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm;
         break;
-    case Controller_NPad::NpadType::Pokeball:
-        vibration_device_info.type = VibrationDeviceType::Unknown;
+    case Core::HID::NpadType::Pokeball:
+        vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown;
         break;
     }
 
     switch (vibration_device_handle.device_index) {
     case Controller_NPad::DeviceIndex::Left:
-        vibration_device_info.position = VibrationDevicePosition::Left;
+        vibration_device_info.position = Core::HID::VibrationDevicePosition::Left;
         break;
     case Controller_NPad::DeviceIndex::Right:
-        vibration_device_info.position = VibrationDevicePosition::Right;
+        vibration_device_info.position = Core::HID::VibrationDevicePosition::Right;
         break;
     case Controller_NPad::DeviceIndex::None:
     default:
         UNREACHABLE_MSG("DeviceIndex should never be None!");
-        vibration_device_info.position = VibrationDevicePosition::None;
+        vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
         break;
     }
 
@@ -1278,7 +1274,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
     struct Parameters {
         Controller_NPad::DeviceHandle vibration_device_handle;
         u64 applet_resource_user_id;
-        VibrationGcErmCommand gc_erm_command;
+        Core::HID::VibrationGcErmCommand gc_erm_command;
     };
     static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
 
@@ -1292,21 +1288,21 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
      */
     const auto vibration_value = [parameters] {
         switch (parameters.gc_erm_command) {
-        case VibrationGcErmCommand::Stop:
+        case Core::HID::VibrationGcErmCommand::Stop:
             return Controller_NPad::VibrationValue{
                 .amp_low = 0.0f,
                 .freq_low = 160.0f,
                 .amp_high = 0.0f,
                 .freq_high = 320.0f,
             };
-        case VibrationGcErmCommand::Start:
+        case Core::HID::VibrationGcErmCommand::Start:
             return Controller_NPad::VibrationValue{
                 .amp_low = 1.0f,
                 .freq_low = 160.0f,
                 .amp_high = 1.0f,
                 .freq_high = 320.0f,
             };
-        case VibrationGcErmCommand::StopHard:
+        case Core::HID::VibrationGcErmCommand::StopHard:
             return Controller_NPad::VibrationValue{
                 .amp_low = 0.0f,
                 .freq_low = 0.0f,
@@ -1348,7 +1344,7 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
 
     const auto gc_erm_command = [last_vibration] {
         if (last_vibration.amp_low != 0.0f || last_vibration.amp_high != 0.0f) {
-            return VibrationGcErmCommand::Start;
+            return Core::HID::VibrationGcErmCommand::Start;
         }
 
         /**
@@ -1358,10 +1354,10 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
          * This is done to reuse the controller vibration functions made for regular controllers.
          */
         if (last_vibration.freq_low == 0.0f && last_vibration.freq_high == 0.0f) {
-            return VibrationGcErmCommand::StopHard;
+            return Core::HID::VibrationGcErmCommand::StopHard;
         }
 
-        return VibrationGcErmCommand::Stop;
+        return Core::HID::VibrationGcErmCommand::Stop;
     }();
 
     LOG_DEBUG(Service_HID,
@@ -2037,9 +2033,6 @@ public:
     }
 };
 
-void ReloadInputDevices() {
-}
-
 void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
     std::make_shared<Hid>(system)->InstallAsService(service_manager);
     std::make_shared<HidBus>(system)->InstallAsService(service_manager);
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index b1fe75e948..2e0c33c1cf 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -161,38 +161,11 @@ private:
     void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx);
     void SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx);
 
-    enum class VibrationDeviceType : u32 {
-        Unknown = 0,
-        LinearResonantActuator = 1,
-        GcErm = 2,
-    };
-
-    enum class VibrationDevicePosition : u32 {
-        None = 0,
-        Left = 1,
-        Right = 2,
-    };
-
-    enum class VibrationGcErmCommand : u64 {
-        Stop = 0,
-        Start = 1,
-        StopHard = 2,
-    };
-
-    struct VibrationDeviceInfo {
-        VibrationDeviceType type{};
-        VibrationDevicePosition position{};
-    };
-    static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size.");
-
     std::shared_ptr<IAppletResource> applet_resource;
 
     KernelHelpers::ServiceContext service_context;
 };
 
-/// Reload input devices. Used when input configuration changed
-void ReloadInputDevices();
-
 /// Registers all HID services with the specified service manager.
 void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
 

From 072559dede9e4ab098b84f43ee6db31d3987b2c3 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:31:06 -0500
Subject: [PATCH 27/88] service/hid: Update debug pad, xpad, stubbed and
 controller base to use ring lifo and the emulated controller

---
 .../service/hid/controllers/controller_base.h | 11 ---
 .../hle/service/hid/controllers/debug_pad.cpp | 68 +++++------------
 .../hle/service/hid/controllers/debug_pad.h   | 73 ++++++-------------
 .../hle/service/hid/controllers/stubbed.cpp   |  3 +-
 .../hle/service/hid/controllers/stubbed.h     | 11 ++-
 src/core/hle/service/hid/controllers/xpad.cpp | 29 +++-----
 src/core/hle/service/hid/controllers/xpad.h   | 51 +++++--------
 7 files changed, 80 insertions(+), 166 deletions(-)

diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h
index 1556fb08e4..4ba2eda1a9 100644
--- a/src/core/hle/service/hid/controllers/controller_base.h
+++ b/src/core/hle/service/hid/controllers/controller_base.h
@@ -35,9 +35,6 @@ public:
     virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                 std::size_t size) {}
 
-    // Called when input devices should be loaded
-    virtual void OnLoadInputDevices() = 0;
-
     void ActivateController();
 
     void DeactivateController();
@@ -47,14 +44,6 @@ public:
 protected:
     bool is_activated{false};
 
-    struct CommonHeader {
-        s64_le timestamp;
-        s64_le total_entry_count;
-        s64_le last_entry_index;
-        s64_le entry_count;
-    };
-    static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
-
     Core::System& system;
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index d439b8fb0e..b2b4edf51e 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -5,7 +5,10 @@
 #include <cstring>
 #include "common/common_types.h"
 #include "common/settings.h"
+#include "core/core.h"
 #include "core/core_timing.h"
+#include "core/hid/hid_core.h"
+#include "core/hid/hid_types.h"
 #include "core/hle/service/hid/controllers/debug_pad.h"
 
 namespace Service::HID {
@@ -14,7 +17,10 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
 [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
 enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right };
 
-Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} {}
+Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} {
+    controller = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Other);
+}
+
 Controller_DebugPad::~Controller_DebugPad() = default;
 
 void Controller_DebugPad::OnInit() {}
@@ -23,63 +29,29 @@ void Controller_DebugPad::OnRelease() {}
 
 void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                    std::size_t size) {
-    shared_memory.header.timestamp = core_timing.GetCPUTicks();
-    shared_memory.header.total_entry_count = 17;
-
     if (!IsControllerActivated()) {
-        shared_memory.header.entry_count = 0;
-        shared_memory.header.last_entry_index = 0;
+        debug_pad_lifo.entry_count = 0;
+        debug_pad_lifo.last_entry_index = 0;
+        std::memcpy(data, &debug_pad_lifo, sizeof(debug_pad_lifo));
         return;
     }
-    shared_memory.header.entry_count = 16;
 
-    const auto& last_entry = shared_memory.pad_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.pad_states[shared_memory.header.last_entry_index];
-
-    cur_entry.sampling_number = last_entry.sampling_number + 1;
-    cur_entry.sampling_number2 = cur_entry.sampling_number;
+    const auto& last_entry = debug_pad_lifo.ReadCurrentEntry().state;
+    next_state.sampling_number = last_entry.sampling_number + 1;
 
     if (Settings::values.debug_pad_enabled) {
-        cur_entry.attribute.connected.Assign(1);
-        auto& pad = cur_entry.pad_state;
+        next_state.attribute.connected.Assign(1);
 
-        using namespace Settings::NativeButton;
-        pad.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
-        pad.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
-        pad.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
-        pad.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
-        pad.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
-        pad.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
-        pad.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
-        pad.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
-        pad.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
-        pad.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
-        pad.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
-        pad.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
-        pad.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
-        pad.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
+        const auto& button_state = controller->GetDebugPadButtons();
+        const auto& stick_state = controller->GetSticks();
 
-        const auto [stick_l_x_f, stick_l_y_f] =
-            analogs[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
-        const auto [stick_r_x_f, stick_r_y_f] =
-            analogs[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
-        cur_entry.l_stick.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
-        cur_entry.l_stick.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
-        cur_entry.r_stick.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
-        cur_entry.r_stick.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
+        next_state.pad_state = button_state;
+        next_state.l_stick = stick_state.left;
+        next_state.r_stick = stick_state.right;
     }
 
-    std::memcpy(data, &shared_memory, sizeof(SharedMemory));
+    debug_pad_lifo.WriteNextEntry(next_state);
+    std::memcpy(data, &debug_pad_lifo, sizeof(debug_pad_lifo));
 }
 
-void Controller_DebugPad::OnLoadInputDevices() {
-    std::transform(Settings::values.debug_pad_buttons.begin(),
-                   Settings::values.debug_pad_buttons.begin() +
-                       Settings::NativeButton::NUM_BUTTONS_HID,
-                   buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
-    std::transform(Settings::values.debug_pad_analogs.begin(),
-                   Settings::values.debug_pad_analogs.end(), analogs.begin(),
-                   Input::CreateDevice<Input::AnalogDevice>);
-}
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index e90ae8415c..11b6c669b4 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -10,8 +10,14 @@
 #include "common/common_types.h"
 #include "common/settings.h"
 #include "common/swap.h"
-#include "core/frontend/input.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/hid/ring_lifo.h"
+
+namespace Core::HID {
+class EmulatedController;
+struct DebugPadButton;
+struct AnalogStickState;
+} // namespace Core::HID
 
 namespace Service::HID {
 class Controller_DebugPad final : public ControllerBase {
@@ -28,66 +34,31 @@ public:
     // 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;
 
-    // Called when input devices should be loaded
-    void OnLoadInputDevices() override;
-
 private:
-    struct AnalogStick {
-        s32_le x;
-        s32_le y;
-    };
-    static_assert(sizeof(AnalogStick) == 0x8);
-
-    struct PadState {
-        union {
-            u32_le raw{};
-            BitField<0, 1, u32> a;
-            BitField<1, 1, u32> b;
-            BitField<2, 1, u32> x;
-            BitField<3, 1, u32> y;
-            BitField<4, 1, u32> l;
-            BitField<5, 1, u32> r;
-            BitField<6, 1, u32> zl;
-            BitField<7, 1, u32> zr;
-            BitField<8, 1, u32> plus;
-            BitField<9, 1, u32> minus;
-            BitField<10, 1, u32> d_left;
-            BitField<11, 1, u32> d_up;
-            BitField<12, 1, u32> d_right;
-            BitField<13, 1, u32> d_down;
-        };
-    };
-    static_assert(sizeof(PadState) == 0x4, "PadState is an invalid size");
-
-    struct Attributes {
+    // This is nn::hid::DebugPadAttribute
+    struct DebugPadAttribute {
         union {
             u32_le raw{};
             BitField<0, 1, u32> connected;
         };
     };
-    static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size");
+    static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size");
 
-    struct PadStates {
+    // This is nn::hid::DebugPadState
+    struct DebugPadState {
         s64_le sampling_number;
-        s64_le sampling_number2;
-        Attributes attribute;
-        PadState pad_state;
-        AnalogStick r_stick;
-        AnalogStick l_stick;
+        DebugPadAttribute attribute;
+        Core::HID::DebugPadButton pad_state;
+        Core::HID::AnalogStickState r_stick;
+        Core::HID::AnalogStickState l_stick;
     };
-    static_assert(sizeof(PadStates) == 0x28, "PadStates is an invalid state");
+    static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
 
-    struct SharedMemory {
-        CommonHeader header;
-        std::array<PadStates, 17> pad_states;
-        INSERT_PADDING_BYTES(0x138);
-    };
-    static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size");
-    SharedMemory shared_memory{};
+    // This is nn::hid::detail::DebugPadLifo
+    Lifo<DebugPadState> debug_pad_lifo{};
+    static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
+    DebugPadState next_state{};
 
-    std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
-        buttons;
-    std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NumAnalogs>
-        analogs;
+    Core::HID::EmulatedController* controller;
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp
index 772c20453d..a8c93909dd 100644
--- a/src/core/hle/service/hid/controllers/stubbed.cpp
+++ b/src/core/hle/service/hid/controllers/stubbed.cpp
@@ -31,10 +31,9 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
     std::memcpy(data + common_offset, &header, sizeof(CommonHeader));
 }
 
-void Controller_Stubbed::OnLoadInputDevices() {}
-
 void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) {
     common_offset = off;
     smart_update = true;
 }
+
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h
index 21092af0d0..29f95a1006 100644
--- a/src/core/hle/service/hid/controllers/stubbed.h
+++ b/src/core/hle/service/hid/controllers/stubbed.h
@@ -22,12 +22,17 @@ public:
     // 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;
 
-    // Called when input devices should be loaded
-    void OnLoadInputDevices() override;
-
     void SetCommonHeaderOffset(std::size_t off);
 
 private:
+    struct CommonHeader {
+        s64_le timestamp;
+        s64_le total_entry_count;
+        s64_le last_entry_index;
+        s64_le entry_count;
+    };
+    static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
+
     bool smart_update{};
     std::size_t common_offset{};
 };
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp
index 41dc22cf96..29a412ff9e 100644
--- a/src/core/hle/service/hid/controllers/xpad.cpp
+++ b/src/core/hle/service/hid/controllers/xpad.cpp
@@ -19,28 +19,19 @@ void Controller_XPad::OnRelease() {}
 
 void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                std::size_t size) {
-    for (auto& xpad_entry : shared_memory.shared_memory_entries) {
-        xpad_entry.header.timestamp = core_timing.GetCPUTicks();
-        xpad_entry.header.total_entry_count = 17;
-
-        if (!IsControllerActivated()) {
-            xpad_entry.header.entry_count = 0;
-            xpad_entry.header.last_entry_index = 0;
-            return;
-        }
-        xpad_entry.header.entry_count = 16;
-
-        const auto& last_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index];
-        xpad_entry.header.last_entry_index = (xpad_entry.header.last_entry_index + 1) % 17;
-        auto& cur_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index];
-
-        cur_entry.sampling_number = last_entry.sampling_number + 1;
-        cur_entry.sampling_number2 = cur_entry.sampling_number;
+    if (!IsControllerActivated()) {
+        basic_xpad_lifo.entry_count = 0;
+        basic_xpad_lifo.last_entry_index = 0;
+        std::memcpy(data, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
+        return;
     }
+
+    const auto& last_entry = basic_xpad_lifo.ReadCurrentEntry().state;
+    next_state.sampling_number = last_entry.sampling_number + 1;
     // TODO(ogniK): Update xpad states
 
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
+    basic_xpad_lifo.WriteNextEntry(next_state);
+    std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
 }
 
-void Controller_XPad::OnLoadInputDevices() {}
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index f9ab5facf5..a5421f93b6 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -8,7 +8,9 @@
 #include "common/common_funcs.h"
 #include "common/common_types.h"
 #include "common/swap.h"
+#include "core/hid/hid_types.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/hid/ring_lifo.h"
 
 namespace Service::HID {
 class Controller_XPad final : public ControllerBase {
@@ -25,11 +27,9 @@ public:
     // 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;
 
-    // Called when input devices should be loaded
-    void OnLoadInputDevices() override;
-
 private:
-    struct Attributes {
+    // This is nn::hid::BasicXpadAttributeSet
+    struct BasicXpadAttributeSet {
         union {
             u32_le raw{};
             BitField<0, 1, u32> is_connected;
@@ -40,9 +40,10 @@ private:
             BitField<5, 1, u32> is_right_wired;
         };
     };
-    static_assert(sizeof(Attributes) == 4, "Attributes is an invalid size");
+    static_assert(sizeof(BasicXpadAttributeSet) == 4, "BasicXpadAttributeSet is an invalid size");
 
-    struct Buttons {
+    // This is nn::hid::BasicXpadButtonSet
+    struct BasicXpadButtonSet {
         union {
             u32_le raw{};
             // Button states
@@ -88,35 +89,21 @@ private:
             BitField<30, 1, u32> handheld_left_b;
         };
     };
-    static_assert(sizeof(Buttons) == 4, "Buttons is an invalid size");
+    static_assert(sizeof(BasicXpadButtonSet) == 4, "BasicXpadButtonSet is an invalid size");
 
-    struct AnalogStick {
-        s32_le x;
-        s32_le y;
-    };
-    static_assert(sizeof(AnalogStick) == 0x8, "AnalogStick is an invalid size");
-
-    struct XPadState {
+    // This is nn::hid::detail::BasicXpadState
+    struct BasicXpadState {
         s64_le sampling_number;
-        s64_le sampling_number2;
-        Attributes attributes;
-        Buttons pad_states;
-        AnalogStick l_stick;
-        AnalogStick r_stick;
+        BasicXpadAttributeSet attributes;
+        BasicXpadButtonSet pad_states;
+        Core::HID::AnalogStickState l_stick;
+        Core::HID::AnalogStickState r_stick;
     };
-    static_assert(sizeof(XPadState) == 0x28, "XPadState is an invalid size");
+    static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size");
 
-    struct XPadEntry {
-        CommonHeader header;
-        std::array<XPadState, 17> pad_states{};
-        INSERT_PADDING_BYTES(0x138);
-    };
-    static_assert(sizeof(XPadEntry) == 0x400, "XPadEntry is an invalid size");
-
-    struct SharedMemory {
-        std::array<XPadEntry, 4> shared_memory_entries{};
-    };
-    static_assert(sizeof(SharedMemory) == 0x1000, "SharedMemory is an invalid size");
-    SharedMemory shared_memory{};
+    // This is nn::hid::detail::BasicXpadLifo
+    Lifo<BasicXpadState> basic_xpad_lifo{};
+    static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size");
+    BasicXpadState next_state{};
 };
 } // namespace Service::HID

From afe2d667d95e74be8f401010fa31a9eeca77d93a Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:33:50 -0500
Subject: [PATCH 28/88] service/hid: Update touch and gestures to use ring lifo
 and the emulated console

---
 .../hle/service/hid/controllers/gesture.cpp   | 274 +++++++-----------
 .../hle/service/hid/controllers/gesture.h     |  80 ++---
 .../service/hid/controllers/touchscreen.cpp   | 136 +++------
 .../hle/service/hid/controllers/touchscreen.h |  71 ++---
 4 files changed, 191 insertions(+), 370 deletions(-)

diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 764abb5b62..2f98cc54b0 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -5,8 +5,10 @@
 #include "common/logging/log.h"
 #include "common/math_util.h"
 #include "common/settings.h"
+#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/frontend/emu_window.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/service/hid/controllers/gesture.h"
 
 namespace Service::HID {
@@ -23,16 +25,15 @@ constexpr f32 Square(s32 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;
 
 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;
 }
 
@@ -40,50 +41,43 @@ void Controller_Gesture::OnRelease() {}
 
 void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                   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()) {
-        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;
     }
 
     ReadTouchInput();
 
     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
     if (!ShouldUpdateGesture(gesture, time_difference)) {
         return;
     }
 
-    last_update_timestamp = shared_memory.header.timestamp;
+    last_update_timestamp = gesture_lifo.timestamp;
     UpdateGestureSharedMemory(data, size, gesture, time_difference);
 }
 
 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,
                                              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) {
         force_update = false;
         return true;
@@ -97,7 +91,7 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
     }
 
     // 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) {
         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,
                                                    GestureProperties& gesture,
                                                    f32 time_difference) {
-    TouchType type = TouchType::Idle;
-    Attribute attributes{};
+    GestureType type = GestureType::Idle;
+    GestureAttribute 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];
+    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
 
-    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;
-
-    // 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 (last_gesture.active_points == 0) {
@@ -141,46 +127,47 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
     }
 
     // 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;
 
-    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++;
-    type = TouchType::Touch;
+    type = GestureType::Touch;
 
     // 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);
         enable_press_and_tap = true;
     }
 }
 
-void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, TouchType& type,
+void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type,
                                                f32 time_difference) {
-    const auto& last_entry = GetLastGestureEntry();
+    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
 
     // Promote to pan type if touch moved
     for (size_t id = 0; id < MAX_POINTS; id++) {
         if (gesture.points[id] != last_gesture.points[id]) {
-            type = TouchType::Pan;
+            type = GestureType::Pan;
             break;
         }
     }
 
     // Number of fingers changed cancel the last event and clear data
     if (gesture.active_points != last_gesture.active_points) {
-        type = TouchType::Cancel;
+        type = GestureType::Cancel;
         enable_press_and_tap = false;
         gesture.active_points = 0;
         gesture.mid_point = {};
@@ -189,41 +176,41 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Touch
     }
 
     // Calculate extra parameters of panning
-    if (type == TouchType::Pan) {
+    if (type == GestureType::Pan) {
         UpdatePanEvent(gesture, last_gesture, type, time_difference);
         return;
     }
 
     // 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,
-                                    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) {
         switch (last_entry.type) {
-        case TouchType::Touch:
+        case GestureType::Touch:
             if (enable_press_and_tap) {
                 SetTapEvent(gesture, last_gesture_props, type, attributes);
                 return;
             }
-            type = TouchType::Cancel;
+            type = GestureType::Cancel;
             force_update = true;
             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;
             break;
-        case TouchType::Pan:
+        case GestureType::Pan:
             EndPanEvent(gesture, last_gesture_props, type, time_difference);
             break;
         default:
@@ -231,15 +218,15 @@ void Controller_Gesture::EndGesture(GestureProperties& gesture,
         }
         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++;
     }
 }
 
 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;
     force_update = true;
     f32 tap_time_difference =
@@ -251,44 +238,42 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
 }
 
 void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
-                                        GestureProperties& last_gesture_props, TouchType& type,
+                                        GestureProperties& last_gesture_props, GestureType& type,
                                         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;
 
     // Promote to pinch type
     if (std::abs(gesture.average_distance - last_gesture_props.average_distance) >
         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) /
                                                   (1 + (gesture.angle * last_gesture_props.angle)));
     // Promote to rotate type
     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,
-                                     GestureProperties& last_gesture_props, TouchType& type,
+                                     GestureProperties& last_gesture_props, GestureType& type,
                                      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);
-    cur_entry.vel_y =
+    next_state.vel_y =
         static_cast<f32>(last_entry.delta.y) / (last_pan_time_difference + time_difference);
     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
     if (curr_vel > swipe_threshold) {
@@ -297,93 +282,34 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
     }
 
     // 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;
 }
 
 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;
     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;
         }
-        cur_entry.direction = Direction::Left;
+        next_state.direction = GestureDirection::Left;
         return;
     }
-    if (cur_entry.delta.y > 0) {
-        cur_entry.direction = Direction::Down;
+    if (next_state.delta.y > 0) {
+        next_state.direction = GestureDirection::Down;
         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() {
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 7e7ae66259..8e6f315a41 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -8,8 +8,12 @@
 #include "common/bit_field.h"
 #include "common/common_types.h"
 #include "common/point.h"
-#include "core/frontend/input.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 {
 class Controller_Gesture final : public ControllerBase {
@@ -26,14 +30,12 @@ public:
     // 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;
 
-    // Called when input devices should be loaded
-    void OnLoadInputDevices() override;
-
 private:
     static constexpr size_t MAX_FINGERS = 16;
     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
         Complete, // Set at the end of a touch event
         Cancel,   // Set when the number of fingers change
@@ -46,7 +48,8 @@ private:
         Rotate,   // All points rotating from the midpoint
     };
 
-    enum class Direction : u32 {
+    // This is nn::hid::GestureDirection
+    enum class GestureDirection : u32 {
         None,
         Left,
         Up,
@@ -54,7 +57,8 @@ private:
         Down,
     };
 
-    struct Attribute {
+    // This is nn::hid::GestureAttribute
+    struct GestureAttribute {
         union {
             u32_le raw{};
 
@@ -62,31 +66,25 @@ private:
             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 {
         s64_le sampling_number;
-        s64_le sampling_number2;
         s64_le detection_count;
-        TouchType type;
-        Direction direction;
+        GestureType type;
+        GestureDirection direction;
         Common::Point<s32_le> pos;
         Common::Point<s32_le> delta;
         f32 vel_x;
         f32 vel_y;
-        Attribute attributes;
+        GestureAttribute attributes;
         f32 scale;
         f32 rotation_angle;
         s32_le point_count;
         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 {
         Common::Point<f32> pos{};
@@ -114,58 +112,42 @@ private:
                                    f32 time_difference);
 
     // Initializes new gesture
-    void NewGesture(GestureProperties& gesture, TouchType& type, Attribute& attributes);
+    void NewGesture(GestureProperties& gesture, GestureType& type, GestureAttribute& attributes);
 
     // 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
     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
     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
     void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
-                        TouchType& type, f32 time_difference);
+                        GestureType& type, f32 time_difference);
 
     // Terminates the pan event
     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
     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
     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{};
+    Core::HID::EmulatedConsole* console;
+
     GestureProperties last_gesture{};
     s64_le last_update_timestamp{};
     s64_le last_tap_timestamp{};
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index 6ef17acc51..e0a44d06b2 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -7,72 +7,79 @@
 #include "common/common_types.h"
 #include "common/logging/log.h"
 #include "common/settings.h"
+#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/frontend/emu_window.h"
-#include "core/frontend/input.h"
 #include "core/hle/service/hid/controllers/touchscreen.h"
 
 namespace Service::HID {
 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;
 
-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::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                       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()) {
-        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;
     }
-    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 (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.start_touch.Assign(1);
+            finger.pressed = true;
+            continue;
+        }
+
+        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& finger) { return finger.pressed; });
     const auto active_fingers_count =
         static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
 
     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) {
-        auto& touch_entry = cur_entry.states[id];
+        auto& touch_entry = next_state.states[id];
         if (id < active_fingers_count) {
             const auto& [active_x, active_y] = active_fingers[id].position;
             touch_entry.position = {
@@ -97,66 +104,9 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
             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
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index 8e9b40c0a3..bcf79237dd 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -9,18 +9,22 @@
 #include "common/common_types.h"
 #include "common/point.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/ring_lifo.h"
 
 namespace Service::HID {
 class Controller_Touchscreen final : public ControllerBase {
 public:
+    // This is nn::hid::TouchScreenModeForNx
     enum class TouchScreenModeForNx : u8 {
         UseSystemSetting,
         Finger,
         Heat2,
     };
 
+    // This is nn::hid::TouchScreenConfigurationForNx
     struct TouchScreenConfigurationForNx {
         TouchScreenModeForNx mode;
         INSERT_PADDING_BYTES_NOINIT(0x7);
@@ -41,73 +45,32 @@ public:
     // 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;
 
-    // Called when input devices should be loaded
-    void OnLoadInputDevices() override;
-
 private:
     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_number2;
         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 {
         u64_le last_touch{};
         Common::Point<float> position;
         u32_le id{};
         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;
+    Core::HID::EmulatedConsole* console;
 };
 } // namespace Service::HID

From 800a66d25a214363d1d06b68a59f315ed295f9e4 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:35:27 -0500
Subject: [PATCH 29/88] service/hid: Update mouse and keyboard to use ring lifo
 and the emulated device

---
 .../hle/service/hid/controllers/keyboard.cpp  | 56 ++++++-----------
 .../hle/service/hid/controllers/keyboard.h    | 53 +++++-----------
 .../hle/service/hid/controllers/mouse.cpp     | 60 ++++++++-----------
 src/core/hle/service/hid/controllers/mouse.h  | 58 ++++--------------
 4 files changed, 70 insertions(+), 157 deletions(-)

diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index c6c6200087..db0f56b927 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -5,14 +5,19 @@
 #include <cstring>
 #include "common/common_types.h"
 #include "common/settings.h"
+#include "core/core.h"
 #include "core/core_timing.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/service/hid/controllers/keyboard.h"
 
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
 constexpr u8 KEYS_PER_BYTE = 8;
 
-Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} {}
+Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} {
+    emulated_devices = system.HIDCore().GetEmulatedDevices();
+}
+
 Controller_Keyboard::~Controller_Keyboard() = default;
 
 void Controller_Keyboard::OnInit() {}
@@ -21,51 +26,26 @@ void Controller_Keyboard::OnRelease() {}
 
 void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                    std::size_t size) {
-    shared_memory.header.timestamp = core_timing.GetCPUTicks();
-    shared_memory.header.total_entry_count = 17;
-
     if (!IsControllerActivated()) {
-        shared_memory.header.entry_count = 0;
-        shared_memory.header.last_entry_index = 0;
+        keyboard_lifo.entry_count = 0;
+        keyboard_lifo.last_entry_index = 0;
+        std::memcpy(data, &keyboard_lifo, sizeof(keyboard_lifo));
         return;
     }
-    shared_memory.header.entry_count = 16;
 
-    const auto& last_entry = shared_memory.pad_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.pad_states[shared_memory.header.last_entry_index];
+    const auto& last_entry = keyboard_lifo.ReadCurrentEntry().state;
+    next_state.sampling_number = last_entry.sampling_number + 1;
 
-    cur_entry.sampling_number = last_entry.sampling_number + 1;
-    cur_entry.sampling_number2 = cur_entry.sampling_number;
-
-    cur_entry.key.fill(0);
     if (Settings::values.keyboard_enabled) {
-        for (std::size_t i = 0; i < keyboard_keys.size(); ++i) {
-            auto& entry = cur_entry.key[i / KEYS_PER_BYTE];
-            entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)));
-        }
+        const auto& keyboard_state = emulated_devices->GetKeyboard();
+        const auto& keyboard_modifier_state = emulated_devices->GetKeyboardModifier();
 
-        using namespace Settings::NativeKeyboard;
-
-        // TODO: Assign the correct key to all modifiers
-        cur_entry.modifier.control.Assign(keyboard_mods[LeftControl]->GetStatus());
-        cur_entry.modifier.shift.Assign(keyboard_mods[LeftShift]->GetStatus());
-        cur_entry.modifier.left_alt.Assign(keyboard_mods[LeftAlt]->GetStatus());
-        cur_entry.modifier.right_alt.Assign(keyboard_mods[RightAlt]->GetStatus());
-        cur_entry.modifier.gui.Assign(0);
-        cur_entry.modifier.caps_lock.Assign(keyboard_mods[CapsLock]->GetStatus());
-        cur_entry.modifier.scroll_lock.Assign(keyboard_mods[ScrollLock]->GetStatus());
-        cur_entry.modifier.num_lock.Assign(keyboard_mods[NumLock]->GetStatus());
-        cur_entry.modifier.katakana.Assign(0);
-        cur_entry.modifier.hiragana.Assign(0);
+        next_state.key = keyboard_state;
+        next_state.modifier = keyboard_modifier_state;
     }
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
+
+    keyboard_lifo.WriteNextEntry(next_state);
+    std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo));
 }
 
-void Controller_Keyboard::OnLoadInputDevices() {
-    std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(),
-                   keyboard_keys.begin(), Input::CreateDevice<Input::ButtonDevice>);
-    std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(),
-                   keyboard_mods.begin(), Input::CreateDevice<Input::ButtonDevice>);
-}
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index 172a80e9c2..6919e092a2 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -10,8 +10,14 @@
 #include "common/common_types.h"
 #include "common/settings.h"
 #include "common/swap.h"
-#include "core/frontend/input.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/hid/ring_lifo.h"
+
+namespace Core::HID {
+class EmulatedDevices;
+struct KeyboardModifier;
+struct KeyboardKey;
+} // namespace Core::HID
 
 namespace Service::HID {
 class Controller_Keyboard final : public ControllerBase {
@@ -28,47 +34,20 @@ public:
     // 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;
 
-    // Called when input devices should be loaded
-    void OnLoadInputDevices() override;
-
 private:
-    struct Modifiers {
-        union {
-            u32_le raw{};
-            BitField<0, 1, u32> control;
-            BitField<1, 1, u32> shift;
-            BitField<2, 1, u32> left_alt;
-            BitField<3, 1, u32> right_alt;
-            BitField<4, 1, u32> gui;
-            BitField<8, 1, u32> caps_lock;
-            BitField<9, 1, u32> scroll_lock;
-            BitField<10, 1, u32> num_lock;
-            BitField<11, 1, u32> katakana;
-            BitField<12, 1, u32> hiragana;
-        };
-    };
-    static_assert(sizeof(Modifiers) == 0x4, "Modifiers is an invalid size");
-
+    // This is nn::hid::detail::KeyboardState
     struct KeyboardState {
         s64_le sampling_number;
-        s64_le sampling_number2;
-
-        Modifiers modifier;
-        std::array<u8, 32> key;
+        Core::HID::KeyboardModifier modifier;
+        Core::HID::KeyboardKey key;
     };
-    static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size");
+    static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
 
-    struct SharedMemory {
-        CommonHeader header;
-        std::array<KeyboardState, 17> pad_states;
-        INSERT_PADDING_BYTES(0x28);
-    };
-    static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size");
-    SharedMemory shared_memory{};
+    // This is nn::hid::detail::KeyboardLifo
+    Lifo<KeyboardState> keyboard_lifo{};
+    static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
+    KeyboardState next_state{};
 
-    std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeKeyboard::NumKeyboardKeys>
-        keyboard_keys;
-    std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeKeyboard::NumKeyboardMods>
-        keyboard_mods;
+    Core::HID::EmulatedDevices* emulated_devices;
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 2211f11447..2f607bfe9d 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -4,14 +4,19 @@
 
 #include <cstring>
 #include "common/common_types.h"
+#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/frontend/emu_window.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/service/hid/controllers/mouse.h"
 
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
 
-Controller_Mouse::Controller_Mouse(Core::System& system_) : ControllerBase{system_} {}
+Controller_Mouse::Controller_Mouse(Core::System& system_) : ControllerBase{system_} {
+    emulated_devices = system.HIDCore().GetEmulatedDevices();
+}
+
 Controller_Mouse::~Controller_Mouse() = default;
 
 void Controller_Mouse::OnInit() {}
@@ -19,50 +24,35 @@ void Controller_Mouse::OnRelease() {}
 
 void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                 std::size_t size) {
-    shared_memory.header.timestamp = core_timing.GetCPUTicks();
-    shared_memory.header.total_entry_count = 17;
+    mouse_lifo.timestamp = core_timing.GetCPUTicks();
 
     if (!IsControllerActivated()) {
-        shared_memory.header.entry_count = 0;
-        shared_memory.header.last_entry_index = 0;
+        mouse_lifo.entry_count = 0;
+        mouse_lifo.last_entry_index = 0;
+        std::memcpy(data, &mouse_lifo, sizeof(mouse_lifo));
         return;
     }
-    shared_memory.header.entry_count = 16;
 
-    auto& last_entry = shared_memory.mouse_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.mouse_states[shared_memory.header.last_entry_index];
+    const auto& last_entry = mouse_lifo.ReadCurrentEntry().state;
+    next_state.sampling_number = last_entry.sampling_number + 1;
 
-    cur_entry.sampling_number = last_entry.sampling_number + 1;
-    cur_entry.sampling_number2 = cur_entry.sampling_number;
-
-    cur_entry.attribute.raw = 0;
+    next_state.attribute.raw = 0;
     if (Settings::values.mouse_enabled) {
-        const auto [px, py, sx, sy] = mouse_device->GetStatus();
-        const auto x = static_cast<s32>(px * Layout::ScreenUndocked::Width);
-        const auto y = static_cast<s32>(py * Layout::ScreenUndocked::Height);
-        cur_entry.x = x;
-        cur_entry.y = y;
-        cur_entry.delta_x = x - last_entry.x;
-        cur_entry.delta_y = y - last_entry.y;
-        cur_entry.mouse_wheel_x = sx;
-        cur_entry.mouse_wheel_y = sy;
-        cur_entry.attribute.is_connected.Assign(1);
+        const auto& mouse_button_state = emulated_devices->GetMouseButtons();
+        const auto& mouse_position_state = emulated_devices->GetMousePosition();
+        next_state.attribute.is_connected.Assign(1);
+        next_state.x = mouse_position_state.x;
+        next_state.y = mouse_position_state.y;
+        next_state.delta_x = next_state.x - last_entry.x;
+        next_state.delta_y = next_state.y - last_entry.y;
+        next_state.delta_wheel_x = mouse_position_state.delta_wheel_x;
+        next_state.delta_wheel_y = mouse_position_state.delta_wheel_y;
 
-        using namespace Settings::NativeMouseButton;
-        cur_entry.button.left.Assign(mouse_button_devices[Left]->GetStatus());
-        cur_entry.button.right.Assign(mouse_button_devices[Right]->GetStatus());
-        cur_entry.button.middle.Assign(mouse_button_devices[Middle]->GetStatus());
-        cur_entry.button.forward.Assign(mouse_button_devices[Forward]->GetStatus());
-        cur_entry.button.back.Assign(mouse_button_devices[Back]->GetStatus());
+        next_state.button = mouse_button_state;
     }
 
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
+    mouse_lifo.WriteNextEntry(next_state);
+    std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo));
 }
 
-void Controller_Mouse::OnLoadInputDevices() {
-    //mouse_device = Input::CreateDevice<Input::MouseDevice>(Settings::values.mouse_device);
-    std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(),
-                   mouse_button_devices.begin(), Input::CreateDevice<Input::ButtonDevice>);
-}
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 3d391a798b..ce868a2471 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -9,8 +9,13 @@
 #include "common/common_types.h"
 #include "common/settings.h"
 #include "common/swap.h"
-#include "core/frontend/input.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/hid/ring_lifo.h"
+
+namespace Core::HID {
+class EmulatedDevices;
+struct MouseState;
+} // namespace Core::HID
 
 namespace Service::HID {
 class Controller_Mouse final : public ControllerBase {
@@ -27,53 +32,12 @@ public:
     // 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;
 
-    // Called when input devices should be loaded
-    void OnLoadInputDevices() override;
-
 private:
-    struct Buttons {
-        union {
-            u32_le raw{};
-            BitField<0, 1, u32> left;
-            BitField<1, 1, u32> right;
-            BitField<2, 1, u32> middle;
-            BitField<3, 1, u32> forward;
-            BitField<4, 1, u32> back;
-        };
-    };
-    static_assert(sizeof(Buttons) == 0x4, "Buttons is an invalid size");
+    // This is nn::hid::detail::MouseLifo
+    Lifo<Core::HID::MouseState> mouse_lifo{};
+    static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
+    Core::HID::MouseState next_state{};
 
-    struct Attributes {
-        union {
-            u32_le raw{};
-            BitField<0, 1, u32> transferable;
-            BitField<1, 1, u32> is_connected;
-        };
-    };
-    static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size");
-
-    struct MouseState {
-        s64_le sampling_number;
-        s64_le sampling_number2;
-        s32_le x;
-        s32_le y;
-        s32_le delta_x;
-        s32_le delta_y;
-        s32_le mouse_wheel_x;
-        s32_le mouse_wheel_y;
-        Buttons button;
-        Attributes attribute;
-    };
-    static_assert(sizeof(MouseState) == 0x30, "MouseState is an invalid size");
-
-    struct SharedMemory {
-        CommonHeader header;
-        std::array<MouseState, 17> mouse_states;
-    };
-    SharedMemory shared_memory{};
-
-    std::unique_ptr<Input::MouseDevice> mouse_device;
-    std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeMouseButton::NumMouseButtons>
-        mouse_button_devices;
+    Core::HID::EmulatedDevices* emulated_devices;
 };
 } // namespace Service::HID

From a2ad5762e61f5d63d9a8c8a409f32c24409df67f Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:36:05 -0500
Subject: [PATCH 30/88] service/hid: Update console sixaxis to the emulated
 console

---
 .../hid/controllers/console_sixaxis.cpp       | 33 ++++++++-----------
 .../service/hid/controllers/console_sixaxis.h | 21 +++++++-----
 2 files changed, 26 insertions(+), 28 deletions(-)

diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
index bda6e2557a..1d351fde05 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
@@ -3,6 +3,7 @@
 // Refer to the license.txt file included.
 
 #include "common/settings.h"
+#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/hle/service/hid/controllers/console_sixaxis.h"
 
@@ -10,7 +11,10 @@ namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
 
 Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::System& system_)
-    : ControllerBase{system_} {}
+    : ControllerBase{system_} {
+    console = system.HIDCore().GetEmulatedConsole();
+}
+
 Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default;
 
 void Controller_ConsoleSixAxis::OnInit() {}
@@ -38,25 +42,21 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
     cur_entry.sampling_number2 = cur_entry.sampling_number;
 
     // Try to read sixaxis sensor states
-    MotionDevice motion_device{};
-    const auto& device = motions[0];
-    if (device) {
-        std::tie(motion_device.accel, motion_device.gyro, motion_device.rotation,
-                 motion_device.orientation, motion_device.quaternion) = device->GetStatus();
-        console_six_axis.is_seven_six_axis_sensor_at_rest = motion_device.gyro.Length2() < 0.0001f;
-    }
+    const auto motion_status = console->GetMotion();
 
-    cur_entry.accel = motion_device.accel;
+    console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
+
+    cur_entry.accel = motion_status.accel;
     // Zero gyro values as they just mess up with the camera
     // Note: Probably a correct sensivity setting must be set
     cur_entry.gyro = {};
     cur_entry.quaternion = {
         {
-            motion_device.quaternion.xyz.y,
-            motion_device.quaternion.xyz.x,
-            -motion_device.quaternion.w,
+            motion_status.quaternion.xyz.y,
+            motion_status.quaternion.xyz.x,
+            -motion_status.quaternion.w,
         },
-        -motion_device.quaternion.xyz.z,
+        -motion_status.quaternion.xyz.z,
     };
 
     console_six_axis.sampling_number++;
@@ -70,13 +70,6 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
     std::memcpy(transfer_memory, &seven_six_axis, sizeof(seven_six_axis));
 }
 
-void Controller_ConsoleSixAxis::OnLoadInputDevices() {
-    const auto player = Settings::values.players.GetValue()[0];
-    std::transform(player.motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
-                   player.motions.begin() + Settings::NativeMotion::MOTION_HID_END, motions.begin(),
-                   Input::CreateDevice<Input::MotionDevice>);
-}
-
 void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) {
     is_transfer_memory_set = true;
     transfer_memory = t_mem;
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h
index fd8a427afa..6d18d2ce07 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.h
@@ -5,10 +5,10 @@
 #pragma once
 
 #include <array>
-#include "common/bit_field.h"
 #include "common/common_types.h"
 #include "common/quaternion.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"
 
 namespace Service::HID {
@@ -26,9 +26,6 @@ public:
     // 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;
 
-    // Called when input devices should be loaded
-    void OnLoadInputDevices() override;
-
     // Called on InitializeSevenSixAxisSensor
     void SetTransferMemoryPointer(u8* t_mem);
 
@@ -47,12 +44,22 @@ private:
     };
     static_assert(sizeof(SevenSixAxisState) == 0x50, "SevenSixAxisState is an invalid size");
 
+    struct CommonHeader {
+        s64_le timestamp;
+        s64_le total_entry_count;
+        s64_le last_entry_index;
+        s64_le entry_count;
+    };
+    static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
+
+    // TODO(german77): SevenSixAxisMemory doesn't follow the standard lifo. Investigate
     struct SevenSixAxisMemory {
         CommonHeader header{};
         std::array<SevenSixAxisState, 0x21> sevensixaxis_states{};
     };
     static_assert(sizeof(SevenSixAxisMemory) == 0xA70, "SevenSixAxisMemory is an invalid size");
 
+    // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
     struct ConsoleSharedMemory {
         u64_le sampling_number{};
         bool is_seven_six_axis_sensor_at_rest{};
@@ -69,9 +76,7 @@ private:
         Common::Quaternion<f32> quaternion;
     };
 
-    using MotionArray =
-        std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>;
-    MotionArray motions;
+    Core::HID::EmulatedConsole* console;
     u8* transfer_memory = nullptr;
     bool is_transfer_memory_set = false;
     ConsoleSharedMemory console_six_axis{};

From c87ad2d0d635d8786c48fed856e1bcf1ecc154bf Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:37:50 -0500
Subject: [PATCH 31/88] service/hid: Rewrite npad to use ring lifo and the
 emulated controller

---
 src/core/hle/service/hid/controllers/npad.cpp | 1116 +++++++----------
 src/core/hle/service/hid/controllers/npad.h   |  393 ++----
 2 files changed, 612 insertions(+), 897 deletions(-)

diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 196876810a..03cbd42f4d 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -12,7 +12,6 @@
 #include "common/settings.h"
 #include "core/core.h"
 #include "core/core_timing.h"
-#include "core/frontend/input.h"
 #include "core/hle/kernel/k_event.h"
 #include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_writable_event.h"
@@ -20,64 +19,13 @@
 #include "core/hle/service/kernel_helpers.h"
 
 namespace Service::HID {
-constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
-constexpr s32 HID_TRIGGER_MAX = 0x7fff;
-[[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
 constexpr std::size_t NPAD_OFFSET = 0x9A00;
-constexpr u32 BATTERY_FULL = 2;
 constexpr u32 MAX_NPAD_ID = 7;
 constexpr std::size_t HANDHELD_INDEX = 8;
 constexpr std::array<u32, 10> npad_id_list{
     0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN,
 };
 
-enum class JoystickId : std::size_t {
-    Joystick_Left,
-    Joystick_Right,
-};
-
-Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad(
-    Settings::ControllerType type) {
-    switch (type) {
-    case Settings::ControllerType::ProController:
-        return NPadControllerType::ProController;
-    case Settings::ControllerType::DualJoyconDetached:
-        return NPadControllerType::JoyDual;
-    case Settings::ControllerType::LeftJoycon:
-        return NPadControllerType::JoyLeft;
-    case Settings::ControllerType::RightJoycon:
-        return NPadControllerType::JoyRight;
-    case Settings::ControllerType::Handheld:
-        return NPadControllerType::Handheld;
-    case Settings::ControllerType::GameCube:
-        return NPadControllerType::GameCube;
-    default:
-        UNREACHABLE();
-        return NPadControllerType::ProController;
-    }
-}
-
-Settings::ControllerType Controller_NPad::MapNPadToSettingsType(
-    Controller_NPad::NPadControllerType type) {
-    switch (type) {
-    case NPadControllerType::ProController:
-        return Settings::ControllerType::ProController;
-    case NPadControllerType::JoyDual:
-        return Settings::ControllerType::DualJoyconDetached;
-    case NPadControllerType::JoyLeft:
-        return Settings::ControllerType::LeftJoycon;
-    case NPadControllerType::JoyRight:
-        return Settings::ControllerType::RightJoycon;
-    case NPadControllerType::Handheld:
-        return Settings::ControllerType::Handheld;
-    case NPadControllerType::GameCube:
-        return Settings::ControllerType::GameCube;
-    default:
-        UNREACHABLE();
-        return Settings::ControllerType::ProController;
-    }
-}
-
 std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) {
     switch (npad_id) {
     case 0:
@@ -143,118 +91,157 @@ bool Controller_NPad::IsNpadIdValid(u32 npad_id) {
 
 bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) {
     return IsNpadIdValid(device_handle.npad_id) &&
-           device_handle.npad_type < NpadType::MaxNpadType &&
+           device_handle.npad_type < Core::HID::NpadType::MaxNpadType &&
            device_handle.device_index < DeviceIndex::MaxDeviceIndex;
 }
 
 Controller_NPad::Controller_NPad(Core::System& system_,
                                  KernelHelpers::ServiceContext& service_context_)
     : ControllerBase{system_}, service_context{service_context_} {
-    latest_vibration_values.fill({DEFAULT_VIBRATION_VALUE, DEFAULT_VIBRATION_VALUE});
+    for (std::size_t i = 0; i < controller_data.size(); ++i) {
+        auto& controller = controller_data[i];
+        controller.device = system.HIDCore().GetEmulatedControllerByIndex(i);
+        controller.vibration[0].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
+        controller.vibration[1].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
+        Core::HID::ControllerUpdateCallback engine_callback{
+            [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }};
+        controller.callback_key = controller.device->SetCallback(engine_callback);
+    }
 }
 
 Controller_NPad::~Controller_NPad() {
+    for (std::size_t i = 0; i < controller_data.size(); ++i) {
+        auto& controller = controller_data[i];
+        controller.device->DeleteCallback(controller.callback_key);
+    }
     OnRelease();
 }
 
-void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
-    const auto controller_type = connected_controllers[controller_idx].type;
-    auto& controller = shared_memory_entries[controller_idx];
-    if (controller_type == NPadControllerType::None) {
-        styleset_changed_events[controller_idx]->GetWritableEvent().Signal();
+void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
+                                       std::size_t controller_idx) {
+    if (type == Core::HID::ControllerTriggerType::All) {
+        ControllerUpdate(Core::HID::ControllerTriggerType::Type, controller_idx);
+        ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
         return;
     }
-    controller.style_set.raw = 0; // Zero out
-    controller.device_type.raw = 0;
-    controller.system_properties.raw = 0;
+
+    switch (type) {
+    case Core::HID::ControllerTriggerType::Connected:
+        InitNewlyAddedController(controller_idx);
+        break;
+    case Core::HID::ControllerTriggerType::Disconnected:
+        DisconnectNpadAtIndex(controller_idx);
+        break;
+    case Core::HID::ControllerTriggerType::Type: {
+        auto& controller = controller_data[controller_idx];
+        if (controller.device->IsConnected()) {
+            LOG_ERROR(Service_HID, "Controller type changed without turning off the controller");
+        }
+        break;
+    }
+    default:
+        break;
+    }
+}
+
+void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
+    auto& controller = controller_data[controller_idx];
+    const auto controller_type = controller.device->GetNpadType();
+    auto& shared_memory = controller.shared_memory_entry;
+    if (controller_type == Core::HID::NpadType::None) {
+        controller.styleset_changed_event->GetWritableEvent().Signal();
+        return;
+    }
+    shared_memory.style_set.raw = 0; // Zero out
+    shared_memory.device_type.raw = 0;
+    shared_memory.system_properties.raw = 0;
     switch (controller_type) {
-    case NPadControllerType::None:
+    case Core::HID::NpadType::None:
         UNREACHABLE();
         break;
-    case NPadControllerType::ProController:
-        controller.style_set.fullkey.Assign(1);
-        controller.device_type.fullkey.Assign(1);
-        controller.system_properties.is_vertical.Assign(1);
-        controller.system_properties.use_plus.Assign(1);
-        controller.system_properties.use_minus.Assign(1);
-        controller.assignment_mode = NpadAssignments::Single;
-        controller.footer_type = AppletFooterUiType::SwitchProController;
+    case Core::HID::NpadType::ProController:
+        shared_memory.style_set.fullkey.Assign(1);
+        shared_memory.device_type.fullkey.Assign(1);
+        shared_memory.system_properties.is_vertical.Assign(1);
+        shared_memory.system_properties.use_plus.Assign(1);
+        shared_memory.system_properties.use_minus.Assign(1);
+        shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
+        shared_memory.footer_type = AppletFooterUiType::SwitchProController;
         break;
-    case NPadControllerType::Handheld:
-        controller.style_set.handheld.Assign(1);
-        controller.device_type.handheld_left.Assign(1);
-        controller.device_type.handheld_right.Assign(1);
-        controller.system_properties.is_vertical.Assign(1);
-        controller.system_properties.use_plus.Assign(1);
-        controller.system_properties.use_minus.Assign(1);
-        controller.assignment_mode = NpadAssignments::Dual;
-        controller.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
+    case Core::HID::NpadType::Handheld:
+        shared_memory.style_set.handheld.Assign(1);
+        shared_memory.device_type.handheld_left.Assign(1);
+        shared_memory.device_type.handheld_right.Assign(1);
+        shared_memory.system_properties.is_vertical.Assign(1);
+        shared_memory.system_properties.use_plus.Assign(1);
+        shared_memory.system_properties.use_minus.Assign(1);
+        shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
+        shared_memory.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
         break;
-    case NPadControllerType::JoyDual:
-        controller.style_set.joycon_dual.Assign(1);
-        controller.device_type.joycon_left.Assign(1);
-        controller.device_type.joycon_right.Assign(1);
-        controller.system_properties.is_vertical.Assign(1);
-        controller.system_properties.use_plus.Assign(1);
-        controller.system_properties.use_minus.Assign(1);
-        controller.assignment_mode = NpadAssignments::Dual;
-        controller.footer_type = AppletFooterUiType::JoyDual;
+    case Core::HID::NpadType::JoyconDual:
+        shared_memory.style_set.joycon_dual.Assign(1);
+        shared_memory.device_type.joycon_left.Assign(1);
+        shared_memory.device_type.joycon_right.Assign(1);
+        shared_memory.system_properties.is_vertical.Assign(1);
+        shared_memory.system_properties.use_plus.Assign(1);
+        shared_memory.system_properties.use_minus.Assign(1);
+        shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
+        shared_memory.footer_type = AppletFooterUiType::JoyDual;
         break;
-    case NPadControllerType::JoyLeft:
-        controller.style_set.joycon_left.Assign(1);
-        controller.device_type.joycon_left.Assign(1);
-        controller.system_properties.is_horizontal.Assign(1);
-        controller.system_properties.use_minus.Assign(1);
-        controller.assignment_mode = NpadAssignments::Single;
-        controller.footer_type = AppletFooterUiType::JoyLeftHorizontal;
+    case Core::HID::NpadType::JoyconLeft:
+        shared_memory.style_set.joycon_left.Assign(1);
+        shared_memory.device_type.joycon_left.Assign(1);
+        shared_memory.system_properties.is_horizontal.Assign(1);
+        shared_memory.system_properties.use_minus.Assign(1);
+        shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
+        shared_memory.footer_type = AppletFooterUiType::JoyLeftHorizontal;
         break;
-    case NPadControllerType::JoyRight:
-        controller.style_set.joycon_right.Assign(1);
-        controller.device_type.joycon_right.Assign(1);
-        controller.system_properties.is_horizontal.Assign(1);
-        controller.system_properties.use_plus.Assign(1);
-        controller.assignment_mode = NpadAssignments::Single;
-        controller.footer_type = AppletFooterUiType::JoyRightHorizontal;
+    case Core::HID::NpadType::JoyconRight:
+        shared_memory.style_set.joycon_right.Assign(1);
+        shared_memory.device_type.joycon_right.Assign(1);
+        shared_memory.system_properties.is_horizontal.Assign(1);
+        shared_memory.system_properties.use_plus.Assign(1);
+        shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
+        shared_memory.footer_type = AppletFooterUiType::JoyRightHorizontal;
         break;
-    case NPadControllerType::GameCube:
-        controller.style_set.gamecube.Assign(1);
+    case Core::HID::NpadType::GameCube:
+        shared_memory.style_set.gamecube.Assign(1);
         // The GC Controller behaves like a wired Pro Controller
-        controller.device_type.fullkey.Assign(1);
-        controller.system_properties.is_vertical.Assign(1);
-        controller.system_properties.use_plus.Assign(1);
+        shared_memory.device_type.fullkey.Assign(1);
+        shared_memory.system_properties.is_vertical.Assign(1);
+        shared_memory.system_properties.use_plus.Assign(1);
         break;
-    case NPadControllerType::Pokeball:
-        controller.style_set.palma.Assign(1);
-        controller.device_type.palma.Assign(1);
-        controller.assignment_mode = NpadAssignments::Single;
+    case Core::HID::NpadType::Pokeball:
+        shared_memory.style_set.palma.Assign(1);
+        shared_memory.device_type.palma.Assign(1);
+        shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
+        break;
+    default:
         break;
     }
 
-    controller.fullkey_color.attribute = ColorAttributes::Ok;
-    controller.fullkey_color.fullkey.body = 0;
-    controller.fullkey_color.fullkey.button = 0;
+    const auto& body_colors = controller.device->GetColors();
 
-    controller.joycon_color.attribute = ColorAttributes::Ok;
-    controller.joycon_color.left.body =
-        Settings::values.players.GetValue()[controller_idx].body_color_left;
-    controller.joycon_color.left.button =
-        Settings::values.players.GetValue()[controller_idx].button_color_left;
-    controller.joycon_color.right.body =
-        Settings::values.players.GetValue()[controller_idx].body_color_right;
-    controller.joycon_color.right.button =
-        Settings::values.players.GetValue()[controller_idx].button_color_right;
+    shared_memory.fullkey_color.attribute = ColorAttribute::Ok;
+    shared_memory.fullkey_color.fullkey = body_colors.fullkey;
+
+    shared_memory.joycon_color.attribute = ColorAttribute::Ok;
+    shared_memory.joycon_color.left = body_colors.left;
+    shared_memory.joycon_color.right = body_colors.right;
 
     // TODO: Investigate when we should report all batery types
-    controller.battery_level_dual = BATTERY_FULL;
-    controller.battery_level_left = BATTERY_FULL;
-    controller.battery_level_right = BATTERY_FULL;
+    const auto& battery_level = controller.device->GetBattery();
+    shared_memory.battery_level_dual = battery_level.dual.battery_level;
+    shared_memory.battery_level_left = battery_level.left.battery_level;
+    shared_memory.battery_level_right = battery_level.right.battery_level;
 
     SignalStyleSetChangedEvent(IndexToNPad(controller_idx));
 }
 
 void Controller_NPad::OnInit() {
-    for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
-        styleset_changed_events[i] =
+    for (std::size_t i = 0; i < controller_data.size(); ++i) {
+        auto& controller = controller_data[i];
+        controller.styleset_changed_event =
             service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
     }
 
@@ -262,10 +249,9 @@ void Controller_NPad::OnInit() {
         return;
     }
 
-    OnLoadInputDevices();
-
-    if (style.raw == 0) {
+    if (system.HIDCore().GetSupportedStyleTag().raw == 0) {
         // We want to support all controllers
+        Core::HID::NpadStyleTag style{};
         style.handheld.Assign(1);
         style.joycon_left.Assign(1);
         style.joycon_right.Assign(1);
@@ -273,173 +259,98 @@ void Controller_NPad::OnInit() {
         style.fullkey.Assign(1);
         style.gamecube.Assign(1);
         style.palma.Assign(1);
-    }
-
-    std::transform(Settings::values.players.GetValue().begin(),
-                   Settings::values.players.GetValue().end(), connected_controllers.begin(),
-                   [](const Settings::PlayerInput& player) {
-                       return ControllerHolder{MapSettingsTypeToNPad(player.controller_type),
-                                               player.connected};
-                   });
-
-    // Connect the Player 1 or Handheld controller if none are connected.
-    if (std::none_of(connected_controllers.begin(), connected_controllers.end(),
-                     [](const ControllerHolder& controller) { return controller.is_connected; })) {
-        const auto controller =
-            MapSettingsTypeToNPad(Settings::values.players.GetValue()[0].controller_type);
-        if (controller == NPadControllerType::Handheld) {
-            Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true;
-            connected_controllers[HANDHELD_INDEX] = {controller, true};
-        } else {
-            Settings::values.players.GetValue()[0].connected = true;
-            connected_controllers[0] = {controller, true};
-        }
-    }
-
-    // Account for handheld
-    if (connected_controllers[HANDHELD_INDEX].is_connected) {
-        connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld;
+        system.HIDCore().SetSupportedStyleTag(style);
     }
 
     supported_npad_id_types.resize(npad_id_list.size());
     std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
                 npad_id_list.size() * sizeof(u32));
 
-    for (std::size_t i = 0; i < connected_controllers.size(); ++i) {
-        const auto& controller = connected_controllers[i];
-        if (controller.is_connected) {
-            AddNewControllerAt(controller.type, i);
+    for (std::size_t i = 0; i < controller_data.size(); ++i) {
+        auto& controller = controller_data[i].device;
+        if (controller->IsConnected()) {
+            AddNewControllerAt(controller->GetNpadType(), i);
         }
     }
-}
 
-void Controller_NPad::OnLoadInputDevices() {
-    const auto& players = Settings::values.players.GetValue();
-
-    std::lock_guard lock{mutex};
-    for (std::size_t i = 0; i < players.size(); ++i) {
-        std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
-                       players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
-                       buttons[i].begin(), Input::CreateDevice<Input::ButtonDevice>);
-        std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
-                       players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
-                       sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>);
-        std::transform(players[i].vibrations.begin() +
-                           Settings::NativeVibration::VIBRATION_HID_BEGIN,
-                       players[i].vibrations.begin() + Settings::NativeVibration::VIBRATION_HID_END,
-                       vibrations[i].begin(), Input::CreateDevice<Input::VibrationDevice>);
-        std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
-                       players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END,
-                       motions[i].begin(), Input::CreateDevice<Input::MotionDevice>);
-        for (std::size_t device_idx = 0; device_idx < vibrations[i].size(); ++device_idx) {
-            InitializeVibrationDeviceAtIndex(i, device_idx);
+    // Prefill controller buffers
+    for (auto& controller : controller_data) {
+        NPadGenericState dummy_pad_state{};
+        auto& npad = controller.shared_memory_entry;
+        for (std::size_t i = 0; i < 17; ++i) {
+            dummy_pad_state.sampling_number =
+                npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
+            npad.fullkey_lifo.WriteNextEntry(dummy_pad_state);
+            npad.handheld_lifo.WriteNextEntry(dummy_pad_state);
+            npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state);
+            npad.joy_left_lifo.WriteNextEntry(dummy_pad_state);
+            npad.joy_right_lifo.WriteNextEntry(dummy_pad_state);
+            npad.joy_right_lifo.WriteNextEntry(dummy_pad_state);
+            npad.palma_lifo.WriteNextEntry(dummy_pad_state);
         }
     }
 }
 
 void Controller_NPad::OnRelease() {
-    for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) {
-        for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) {
-            VibrateControllerAtIndex(npad_idx, device_idx, {});
+    for (std::size_t i = 0; i < controller_data.size(); ++i) {
+        auto& controller = controller_data[i];
+        service_context.CloseEvent(controller.styleset_changed_event);
+        for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
+            VibrateControllerAtIndex(i, device_idx, {});
         }
     }
-
-    for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
-        service_context.CloseEvent(styleset_changed_events[i]);
-    }
 }
 
 void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
     std::lock_guard lock{mutex};
-
     const auto controller_idx = NPadIdToIndex(npad_id);
-    const auto controller_type = connected_controllers[controller_idx].type;
-    if (!connected_controllers[controller_idx].is_connected) {
+    auto& controller = controller_data[controller_idx];
+    const auto controller_type = controller.device->GetNpadType();
+    if (!controller.device->IsConnected()) {
         return;
     }
-    auto& pad_state = npad_pad_states[controller_idx].pad_states;
-    auto& lstick_entry = npad_pad_states[controller_idx].l_stick;
-    auto& rstick_entry = npad_pad_states[controller_idx].r_stick;
-    auto& trigger_entry = npad_trigger_states[controller_idx];
-    const auto& button_state = buttons[controller_idx];
-    const auto& analog_state = sticks[controller_idx];
-    const auto [stick_l_x_f, stick_l_y_f] =
-        analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
-    const auto [stick_r_x_f, stick_r_y_f] =
-        analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
 
-    using namespace Settings::NativeButton;
-    if (controller_type != NPadControllerType::JoyLeft) {
-        pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus());
+    auto& pad_entry = controller.npad_pad_state;
+    auto& trigger_entry = controller.npad_trigger_state;
+    const auto button_state = controller.device->GetNpadButtons();
+    const auto stick_state = controller.device->GetSticks();
 
-        pad_state.r_stick_right.Assign(
-            analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
-                ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
-        pad_state.r_stick_left.Assign(
-            analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
-                ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
-        pad_state.r_stick_up.Assign(
-            analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
-                ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
-        pad_state.r_stick_down.Assign(
-            analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
-                ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
-        rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
-        rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
+    using btn = Core::HID::NpadButton;
+    pad_entry.npad_buttons.raw = btn::None;
+    if (controller_type != Core::HID::NpadType::JoyconLeft) {
+        constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R |
+                                          btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp |
+                                          btn::StickRRight | btn::StickRDown;
+        pad_entry.npad_buttons.raw |= button_state.raw & right_button_mask;
+        pad_entry.r_stick = stick_state.right;
     }
 
-    if (controller_type != NPadControllerType::JoyRight) {
-        pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus());
-
-        pad_state.l_stick_right.Assign(
-            analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
-                ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
-        pad_state.l_stick_left.Assign(
-            analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
-                ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
-        pad_state.l_stick_up.Assign(
-            analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
-                ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
-        pad_state.l_stick_down.Assign(
-            analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
-                ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
-        lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
-        lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
+    if (controller_type != Core::HID::NpadType::JoyconRight) {
+        constexpr btn left_button_mask =
+            btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL |
+            btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown;
+        pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask;
+        pad_entry.l_stick = stick_state.left;
     }
 
-    if (controller_type == NPadControllerType::JoyLeft) {
-        pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
+    if (controller_type == Core::HID::NpadType::JoyconLeft) {
+        pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
+        pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
     }
 
-    if (controller_type == NPadControllerType::JoyRight) {
-        pad_state.right_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.right_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
+    if (controller_type == Core::HID::NpadType::JoyconRight) {
+        pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
+        pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
     }
 
-    if (controller_type == NPadControllerType::GameCube) {
-        trigger_entry.l_analog = static_cast<s32>(
-            button_state[ZL - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0);
-        trigger_entry.r_analog = static_cast<s32>(
-            button_state[ZR - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0);
-        pad_state.zl.Assign(false);
-        pad_state.zr.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.l.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
-        pad_state.r.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
+    if (controller_type == Core::HID::NpadType::GameCube) {
+        const auto& trigger_state = controller.device->GetTriggers();
+        trigger_entry.l_analog = trigger_state.left;
+        trigger_entry.r_analog = trigger_state.right;
+        pad_entry.npad_buttons.zl.Assign(false);
+        pad_entry.npad_buttons.zr.Assign(button_state.r);
+        pad_entry.npad_buttons.l.Assign(button_state.zl);
+        pad_entry.npad_buttons.r.Assign(button_state.zr);
     }
 }
 
@@ -448,173 +359,124 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
     if (!IsControllerActivated()) {
         return;
     }
-    for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
-        auto& npad = shared_memory_entries[i];
-        const std::array<NPadGeneric*, 7> controller_npads{
-            &npad.fullkey_states,   &npad.handheld_states,  &npad.joy_dual_states,
-            &npad.joy_left_states,  &npad.joy_right_states, &npad.palma_states,
-            &npad.system_ext_states};
+    for (std::size_t i = 0; i < controller_data.size(); ++i) {
+        auto& controller = controller_data[i];
+        auto& npad = controller.shared_memory_entry;
 
-        // There is the posibility to have more controllers with analog triggers
-        const std::array<TriggerGeneric*, 1> controller_triggers{
-            &npad.gc_trigger_states,
-        };
+        const auto& controller_type = controller.device->GetNpadType();
 
-        for (auto* main_controller : controller_npads) {
-            main_controller->common.entry_count = 16;
-            main_controller->common.total_entry_count = 17;
-
-            const auto& last_entry =
-                main_controller->npad[main_controller->common.last_entry_index];
-
-            main_controller->common.timestamp = core_timing.GetCPUTicks();
-            main_controller->common.last_entry_index =
-                (main_controller->common.last_entry_index + 1) % 17;
-
-            auto& cur_entry = main_controller->npad[main_controller->common.last_entry_index];
-
-            cur_entry.timestamp = last_entry.timestamp + 1;
-            cur_entry.timestamp2 = cur_entry.timestamp;
-        }
-
-        for (auto* analog_trigger : controller_triggers) {
-            analog_trigger->entry_count = 16;
-            analog_trigger->total_entry_count = 17;
-
-            const auto& last_entry = analog_trigger->trigger[analog_trigger->last_entry_index];
-
-            analog_trigger->timestamp = core_timing.GetCPUTicks();
-            analog_trigger->last_entry_index = (analog_trigger->last_entry_index + 1) % 17;
-
-            auto& cur_entry = analog_trigger->trigger[analog_trigger->last_entry_index];
-
-            cur_entry.timestamp = last_entry.timestamp + 1;
-            cur_entry.timestamp2 = cur_entry.timestamp;
-        }
-
-        const auto& controller_type = connected_controllers[i].type;
-
-        if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
+        if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) {
             continue;
         }
         const u32 npad_index = static_cast<u32>(i);
 
         RequestPadStateUpdate(npad_index);
-        auto& pad_state = npad_pad_states[npad_index];
-        auto& trigger_state = npad_trigger_states[npad_index];
-
-        auto& main_controller =
-            npad.fullkey_states.npad[npad.fullkey_states.common.last_entry_index];
-        auto& handheld_entry =
-            npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
-        auto& dual_entry = npad.joy_dual_states.npad[npad.joy_dual_states.common.last_entry_index];
-        auto& left_entry = npad.joy_left_states.npad[npad.joy_left_states.common.last_entry_index];
-        auto& right_entry =
-            npad.joy_right_states.npad[npad.joy_right_states.common.last_entry_index];
-        auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index];
-        auto& libnx_entry =
-            npad.system_ext_states.npad[npad.system_ext_states.common.last_entry_index];
-        auto& trigger_entry =
-            npad.gc_trigger_states.trigger[npad.gc_trigger_states.last_entry_index];
-
-        libnx_entry.connection_status.raw = 0;
-        libnx_entry.connection_status.is_connected.Assign(1);
-
-        switch (controller_type) {
-        case NPadControllerType::None:
-            UNREACHABLE();
-            break;
-        case NPadControllerType::ProController:
-            main_controller.connection_status.raw = 0;
-            main_controller.connection_status.is_connected.Assign(1);
-            main_controller.connection_status.is_wired.Assign(1);
-            main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
-            main_controller.pad.l_stick = pad_state.l_stick;
-            main_controller.pad.r_stick = pad_state.r_stick;
-
-            libnx_entry.connection_status.is_wired.Assign(1);
-            break;
-        case NPadControllerType::Handheld:
-            handheld_entry.connection_status.raw = 0;
-            handheld_entry.connection_status.is_connected.Assign(1);
-            handheld_entry.connection_status.is_wired.Assign(1);
-            handheld_entry.connection_status.is_left_connected.Assign(1);
-            handheld_entry.connection_status.is_right_connected.Assign(1);
-            handheld_entry.connection_status.is_left_wired.Assign(1);
-            handheld_entry.connection_status.is_right_wired.Assign(1);
-            handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-            handheld_entry.pad.l_stick = pad_state.l_stick;
-            handheld_entry.pad.r_stick = pad_state.r_stick;
-
-            libnx_entry.connection_status.is_wired.Assign(1);
-            libnx_entry.connection_status.is_left_connected.Assign(1);
-            libnx_entry.connection_status.is_right_connected.Assign(1);
-            libnx_entry.connection_status.is_left_wired.Assign(1);
-            libnx_entry.connection_status.is_right_wired.Assign(1);
-            break;
-        case NPadControllerType::JoyDual:
-            dual_entry.connection_status.raw = 0;
-            dual_entry.connection_status.is_connected.Assign(1);
-            dual_entry.connection_status.is_left_connected.Assign(1);
-            dual_entry.connection_status.is_right_connected.Assign(1);
-            dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-            dual_entry.pad.l_stick = pad_state.l_stick;
-            dual_entry.pad.r_stick = pad_state.r_stick;
-
-            libnx_entry.connection_status.is_left_connected.Assign(1);
-            libnx_entry.connection_status.is_right_connected.Assign(1);
-            break;
-        case NPadControllerType::JoyLeft:
-            left_entry.connection_status.raw = 0;
-            left_entry.connection_status.is_connected.Assign(1);
-            left_entry.connection_status.is_left_connected.Assign(1);
-            left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-            left_entry.pad.l_stick = pad_state.l_stick;
-            left_entry.pad.r_stick = pad_state.r_stick;
-
-            libnx_entry.connection_status.is_left_connected.Assign(1);
-            break;
-        case NPadControllerType::JoyRight:
-            right_entry.connection_status.raw = 0;
-            right_entry.connection_status.is_connected.Assign(1);
-            right_entry.connection_status.is_right_connected.Assign(1);
-            right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-            right_entry.pad.l_stick = pad_state.l_stick;
-            right_entry.pad.r_stick = pad_state.r_stick;
-
-            libnx_entry.connection_status.is_right_connected.Assign(1);
-            break;
-        case NPadControllerType::GameCube:
-            main_controller.connection_status.raw = 0;
-            main_controller.connection_status.is_connected.Assign(1);
-            main_controller.connection_status.is_wired.Assign(1);
-            main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
-            main_controller.pad.l_stick = pad_state.l_stick;
-            main_controller.pad.r_stick = pad_state.r_stick;
-            trigger_entry.l_analog = trigger_state.l_analog;
-            trigger_entry.r_analog = trigger_state.r_analog;
-
-            libnx_entry.connection_status.is_wired.Assign(1);
-            break;
-        case NPadControllerType::Pokeball:
-            pokeball_entry.connection_status.raw = 0;
-            pokeball_entry.connection_status.is_connected.Assign(1);
-            pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-            pokeball_entry.pad.l_stick = pad_state.l_stick;
-            pokeball_entry.pad.r_stick = pad_state.r_stick;
-            break;
-        }
+        auto& pad_state = controller.npad_pad_state;
+        auto& libnx_state = controller.npad_libnx_state;
+        auto& trigger_state = controller.npad_trigger_state;
 
         // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
         // any controllers.
-        libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-        libnx_entry.pad.l_stick = pad_state.l_stick;
-        libnx_entry.pad.r_stick = pad_state.r_stick;
+        libnx_state.connection_status.raw = 0;
+        libnx_state.connection_status.is_connected.Assign(1);
+        switch (controller_type) {
+        case Core::HID::NpadType::None:
+            UNREACHABLE();
+            break;
+        case Core::HID::NpadType::ProController:
+            pad_state.connection_status.raw = 0;
+            pad_state.connection_status.is_connected.Assign(1);
+            pad_state.connection_status.is_wired.Assign(1);
 
-        press_state |= static_cast<u32>(pad_state.pad_states.raw);
+            libnx_state.connection_status.is_wired.Assign(1);
+            pad_state.sampling_number =
+                npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.fullkey_lifo.WriteNextEntry(pad_state);
+            break;
+        case Core::HID::NpadType::Handheld:
+            pad_state.connection_status.raw = 0;
+            pad_state.connection_status.is_connected.Assign(1);
+            pad_state.connection_status.is_wired.Assign(1);
+            pad_state.connection_status.is_left_connected.Assign(1);
+            pad_state.connection_status.is_right_connected.Assign(1);
+            pad_state.connection_status.is_left_wired.Assign(1);
+            pad_state.connection_status.is_right_wired.Assign(1);
+
+            libnx_state.connection_status.is_wired.Assign(1);
+            libnx_state.connection_status.is_left_connected.Assign(1);
+            libnx_state.connection_status.is_right_connected.Assign(1);
+            libnx_state.connection_status.is_left_wired.Assign(1);
+            libnx_state.connection_status.is_right_wired.Assign(1);
+            pad_state.sampling_number =
+                npad.handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.handheld_lifo.WriteNextEntry(pad_state);
+            break;
+        case Core::HID::NpadType::JoyconDual:
+            pad_state.connection_status.raw = 0;
+            pad_state.connection_status.is_connected.Assign(1);
+            pad_state.connection_status.is_left_connected.Assign(1);
+            pad_state.connection_status.is_right_connected.Assign(1);
+
+            libnx_state.connection_status.is_left_connected.Assign(1);
+            libnx_state.connection_status.is_right_connected.Assign(1);
+            pad_state.sampling_number =
+                npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.joy_dual_lifo.WriteNextEntry(pad_state);
+            break;
+        case Core::HID::NpadType::JoyconLeft:
+            pad_state.connection_status.raw = 0;
+            pad_state.connection_status.is_connected.Assign(1);
+            pad_state.connection_status.is_left_connected.Assign(1);
+
+            libnx_state.connection_status.is_left_connected.Assign(1);
+            pad_state.sampling_number =
+                npad.joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.joy_left_lifo.WriteNextEntry(pad_state);
+            break;
+        case Core::HID::NpadType::JoyconRight:
+            pad_state.connection_status.raw = 0;
+            pad_state.connection_status.is_connected.Assign(1);
+            pad_state.connection_status.is_right_connected.Assign(1);
+
+            libnx_state.connection_status.is_right_connected.Assign(1);
+            pad_state.sampling_number =
+                npad.joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.joy_right_lifo.WriteNextEntry(pad_state);
+            break;
+        case Core::HID::NpadType::GameCube:
+            pad_state.connection_status.raw = 0;
+            pad_state.connection_status.is_connected.Assign(1);
+            pad_state.connection_status.is_wired.Assign(1);
+
+            libnx_state.connection_status.is_wired.Assign(1);
+            pad_state.sampling_number =
+                npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            trigger_state.sampling_number =
+                npad.gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.fullkey_lifo.WriteNextEntry(pad_state);
+            npad.gc_trigger_lifo.WriteNextEntry(trigger_state);
+            break;
+        case Core::HID::NpadType::Pokeball:
+            pad_state.connection_status.raw = 0;
+            pad_state.connection_status.is_connected.Assign(1);
+            pad_state.sampling_number =
+                npad.palma_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.palma_lifo.WriteNextEntry(pad_state);
+            break;
+        default:
+            break;
+        }
+
+        libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw;
+        libnx_state.l_stick = pad_state.l_stick;
+        libnx_state.r_stick = pad_state.r_stick;
+        npad.system_ext_lifo.WriteNextEntry(pad_state);
+
+        press_state |= static_cast<u32>(pad_state.npad_buttons.raw);
+
+        std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
+                    &controller.shared_memory_entry, sizeof(NpadInternalState));
     }
-    std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
-                shared_memory_entries.size() * sizeof(NPadEntry));
 }
 
 void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
@@ -622,145 +484,130 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
     if (!IsControllerActivated()) {
         return;
     }
-    for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
-        auto& npad = shared_memory_entries[i];
 
-        const auto& controller_type = connected_controllers[i].type;
+    for (std::size_t i = 0; i < controller_data.size(); ++i) {
+        auto& controller = controller_data[i];
 
-        if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
+        const auto& controller_type = controller.device->GetNpadType();
+
+        if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) {
             continue;
         }
 
-        const std::array<SixAxisGeneric*, 6> controller_sixaxes{
-            &npad.sixaxis_fullkey,    &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
-            &npad.sixaxis_dual_right, &npad.sixaxis_left,     &npad.sixaxis_right,
-        };
-
-        for (auto* sixaxis_sensor : controller_sixaxes) {
-            sixaxis_sensor->common.entry_count = 16;
-            sixaxis_sensor->common.total_entry_count = 17;
-
-            const auto& last_entry =
-                sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
-
-            sixaxis_sensor->common.timestamp = core_timing.GetCPUTicks();
-            sixaxis_sensor->common.last_entry_index =
-                (sixaxis_sensor->common.last_entry_index + 1) % 17;
-
-            auto& cur_entry = sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
-
-            cur_entry.timestamp = last_entry.timestamp + 1;
-            cur_entry.timestamp2 = cur_entry.timestamp;
-        }
-
-        // Try to read sixaxis sensor states
-        std::array<MotionDevice, 2> motion_devices;
+        auto& npad = controller.shared_memory_entry;
+        const auto& motion_state = controller.device->GetMotions();
+        auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
+        auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
+        auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
+        auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
+        auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
+        auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
 
         if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) {
             sixaxis_at_rest = true;
-            for (std::size_t e = 0; e < motion_devices.size(); ++e) {
-                const auto& device = motions[i][e];
-                if (device) {
-                    std::tie(motion_devices[e].accel, motion_devices[e].gyro,
-                             motion_devices[e].rotation, motion_devices[e].orientation,
-                             motion_devices[e].quaternion) = device->GetStatus();
-                    sixaxis_at_rest = sixaxis_at_rest && motion_devices[e].gyro.Length2() < 0.0001f;
-                }
+            for (std::size_t e = 0; e < motion_state.size(); ++e) {
+                sixaxis_at_rest = sixaxis_at_rest && motion_state[e].is_at_rest;
             }
         }
 
-        auto& full_sixaxis_entry =
-            npad.sixaxis_fullkey.sixaxis[npad.sixaxis_fullkey.common.last_entry_index];
-        auto& handheld_sixaxis_entry =
-            npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
-        auto& dual_left_sixaxis_entry =
-            npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index];
-        auto& dual_right_sixaxis_entry =
-            npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index];
-        auto& left_sixaxis_entry =
-            npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index];
-        auto& right_sixaxis_entry =
-            npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index];
-
         switch (controller_type) {
-        case NPadControllerType::None:
+        case Core::HID::NpadType::None:
             UNREACHABLE();
             break;
-        case NPadControllerType::ProController:
-            full_sixaxis_entry.attribute.raw = 0;
-            if (sixaxis_sensors_enabled && motions[i][0]) {
-                full_sixaxis_entry.attribute.is_connected.Assign(1);
-                full_sixaxis_entry.accel = motion_devices[0].accel;
-                full_sixaxis_entry.gyro = motion_devices[0].gyro;
-                full_sixaxis_entry.rotation = motion_devices[0].rotation;
-                full_sixaxis_entry.orientation = motion_devices[0].orientation;
+        case Core::HID::NpadType::ProController:
+            sixaxis_fullkey_state.attribute.raw = 0;
+            if (sixaxis_sensors_enabled) {
+                sixaxis_fullkey_state.attribute.is_connected.Assign(1);
+                sixaxis_fullkey_state.accel = motion_state[0].accel;
+                sixaxis_fullkey_state.gyro = motion_state[0].gyro;
+                sixaxis_fullkey_state.rotation = motion_state[0].rotation;
+                sixaxis_fullkey_state.orientation = motion_state[0].orientation;
             }
             break;
-        case NPadControllerType::Handheld:
-            handheld_sixaxis_entry.attribute.raw = 0;
-            if (sixaxis_sensors_enabled && motions[i][0]) {
-                handheld_sixaxis_entry.attribute.is_connected.Assign(1);
-                handheld_sixaxis_entry.accel = motion_devices[0].accel;
-                handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
-                handheld_sixaxis_entry.rotation = motion_devices[0].rotation;
-                handheld_sixaxis_entry.orientation = motion_devices[0].orientation;
+        case Core::HID::NpadType::Handheld:
+            sixaxis_handheld_state.attribute.raw = 0;
+            if (sixaxis_sensors_enabled) {
+                sixaxis_handheld_state.attribute.is_connected.Assign(1);
+                sixaxis_handheld_state.accel = motion_state[0].accel;
+                sixaxis_handheld_state.gyro = motion_state[0].gyro;
+                sixaxis_handheld_state.rotation = motion_state[0].rotation;
+                sixaxis_handheld_state.orientation = motion_state[0].orientation;
             }
             break;
-        case NPadControllerType::JoyDual:
-            dual_left_sixaxis_entry.attribute.raw = 0;
-            dual_right_sixaxis_entry.attribute.raw = 0;
-            if (sixaxis_sensors_enabled && motions[i][0]) {
+        case Core::HID::NpadType::JoyconDual:
+            sixaxis_dual_left_state.attribute.raw = 0;
+            sixaxis_dual_right_state.attribute.raw = 0;
+            if (sixaxis_sensors_enabled) {
                 // Set motion for the left joycon
-                dual_left_sixaxis_entry.attribute.is_connected.Assign(1);
-                dual_left_sixaxis_entry.accel = motion_devices[0].accel;
-                dual_left_sixaxis_entry.gyro = motion_devices[0].gyro;
-                dual_left_sixaxis_entry.rotation = motion_devices[0].rotation;
-                dual_left_sixaxis_entry.orientation = motion_devices[0].orientation;
+                sixaxis_dual_left_state.attribute.is_connected.Assign(1);
+                sixaxis_dual_left_state.accel = motion_state[0].accel;
+                sixaxis_dual_left_state.gyro = motion_state[0].gyro;
+                sixaxis_dual_left_state.rotation = motion_state[0].rotation;
+                sixaxis_dual_left_state.orientation = motion_state[0].orientation;
             }
-            if (sixaxis_sensors_enabled && motions[i][1]) {
+            if (sixaxis_sensors_enabled) {
                 // Set motion for the right joycon
-                dual_right_sixaxis_entry.attribute.is_connected.Assign(1);
-                dual_right_sixaxis_entry.accel = motion_devices[1].accel;
-                dual_right_sixaxis_entry.gyro = motion_devices[1].gyro;
-                dual_right_sixaxis_entry.rotation = motion_devices[1].rotation;
-                dual_right_sixaxis_entry.orientation = motion_devices[1].orientation;
+                sixaxis_dual_right_state.attribute.is_connected.Assign(1);
+                sixaxis_dual_right_state.accel = motion_state[1].accel;
+                sixaxis_dual_right_state.gyro = motion_state[1].gyro;
+                sixaxis_dual_right_state.rotation = motion_state[1].rotation;
+                sixaxis_dual_right_state.orientation = motion_state[1].orientation;
             }
             break;
-        case NPadControllerType::JoyLeft:
-            left_sixaxis_entry.attribute.raw = 0;
-            if (sixaxis_sensors_enabled && motions[i][0]) {
-                left_sixaxis_entry.attribute.is_connected.Assign(1);
-                left_sixaxis_entry.accel = motion_devices[0].accel;
-                left_sixaxis_entry.gyro = motion_devices[0].gyro;
-                left_sixaxis_entry.rotation = motion_devices[0].rotation;
-                left_sixaxis_entry.orientation = motion_devices[0].orientation;
+        case Core::HID::NpadType::JoyconLeft:
+            sixaxis_left_lifo_state.attribute.raw = 0;
+            if (sixaxis_sensors_enabled) {
+                sixaxis_left_lifo_state.attribute.is_connected.Assign(1);
+                sixaxis_left_lifo_state.accel = motion_state[0].accel;
+                sixaxis_left_lifo_state.gyro = motion_state[0].gyro;
+                sixaxis_left_lifo_state.rotation = motion_state[0].rotation;
+                sixaxis_left_lifo_state.orientation = motion_state[0].orientation;
             }
             break;
-        case NPadControllerType::JoyRight:
-            right_sixaxis_entry.attribute.raw = 0;
-            if (sixaxis_sensors_enabled && motions[i][1]) {
-                right_sixaxis_entry.attribute.is_connected.Assign(1);
-                right_sixaxis_entry.accel = motion_devices[1].accel;
-                right_sixaxis_entry.gyro = motion_devices[1].gyro;
-                right_sixaxis_entry.rotation = motion_devices[1].rotation;
-                right_sixaxis_entry.orientation = motion_devices[1].orientation;
+        case Core::HID::NpadType::JoyconRight:
+            sixaxis_right_lifo_state.attribute.raw = 0;
+            if (sixaxis_sensors_enabled) {
+                sixaxis_right_lifo_state.attribute.is_connected.Assign(1);
+                sixaxis_right_lifo_state.accel = motion_state[1].accel;
+                sixaxis_right_lifo_state.gyro = motion_state[1].gyro;
+                sixaxis_right_lifo_state.rotation = motion_state[1].rotation;
+                sixaxis_right_lifo_state.orientation = motion_state[1].orientation;
             }
             break;
-        case NPadControllerType::GameCube:
-        case NPadControllerType::Pokeball:
+        default:
             break;
         }
+
+        sixaxis_fullkey_state.sampling_number =
+            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+        sixaxis_handheld_state.sampling_number =
+            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+        sixaxis_dual_left_state.sampling_number =
+            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+        sixaxis_dual_right_state.sampling_number =
+            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+        sixaxis_left_lifo_state.sampling_number =
+            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+        sixaxis_right_lifo_state.sampling_number =
+            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+
+        npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
+        npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
+        npad.sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
+        npad.sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
+        npad.sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
+        npad.sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
+        std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
+                    &controller.shared_memory_entry, sizeof(NpadInternalState));
     }
-    std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
-                shared_memory_entries.size() * sizeof(NPadEntry));
 }
 
-void Controller_NPad::SetSupportedStyleSet(NpadStyleSet style_set) {
-    style.raw = style_set.raw;
+void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
+    system.HIDCore().SetSupportedStyleTag(style_set);
 }
 
-Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const {
-    return style;
+Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
+    return system.HIDCore().GetSupportedStyleTag();
 }
 
 void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) {
@@ -779,11 +626,11 @@ std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
     return supported_npad_id_types.size();
 }
 
-void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) {
+void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
     hold_type = joy_hold_type;
 }
 
-Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const {
+Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const {
     return hold_type;
 }
 
@@ -803,29 +650,31 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
     return communication_mode;
 }
 
-void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) {
+void Controller_NPad::SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode) {
     const std::size_t npad_index = NPadIdToIndex(npad_id);
-    ASSERT(npad_index < shared_memory_entries.size());
-    if (shared_memory_entries[npad_index].assignment_mode != assignment_mode) {
-        shared_memory_entries[npad_index].assignment_mode = assignment_mode;
+    ASSERT(npad_index < controller_data.size());
+    auto& controller = controller_data[npad_index];
+    if (controller.shared_memory_entry.assignment_mode != assignment_mode) {
+        controller.shared_memory_entry.assignment_mode = assignment_mode;
     }
 }
 
 bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index,
                                                const VibrationValue& vibration_value) {
-    if (!connected_controllers[npad_index].is_connected || !vibrations[npad_index][device_index]) {
+    auto& controller = controller_data[npad_index];
+
+    if (!controller.device->IsConnected()) {
         return false;
     }
 
-    const auto& player = Settings::values.players.GetValue()[npad_index];
-
-    if (!player.vibration_enabled) {
-        if (latest_vibration_values[npad_index][device_index].amp_low != 0.0f ||
-            latest_vibration_values[npad_index][device_index].amp_high != 0.0f) {
+    if (!controller.device->IsVibrationEnabled()) {
+        if (controller.vibration[device_index].latest_vibration_value.amp_low != 0.0f ||
+            controller.vibration[device_index].latest_vibration_value.amp_high != 0.0f) {
             // Send an empty vibration to stop any vibrations.
-            vibrations[npad_index][device_index]->SetRumblePlay(0.0f, 160.0f, 0.0f, 320.0f);
+            Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
+            controller.device->SetVibration(device_index, vibration);
             // Then reset the vibration value to its default value.
-            latest_vibration_values[npad_index][device_index] = DEFAULT_VIBRATION_VALUE;
+            controller.vibration[device_index].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
         }
 
         return false;
@@ -840,22 +689,18 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size
 
         // Filter out non-zero vibrations that are within 10ms of each other.
         if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) &&
-            duration_cast<milliseconds>(now - last_vibration_timepoints[npad_index][device_index]) <
+            duration_cast<milliseconds>(
+                now - controller.vibration[device_index].last_vibration_timepoint) <
                 milliseconds(10)) {
             return false;
         }
 
-        last_vibration_timepoints[npad_index][device_index] = now;
+        controller.vibration[device_index].last_vibration_timepoint = now;
     }
 
-    auto& vibration = vibrations[npad_index][device_index];
-    const auto player_vibration_strength = static_cast<f32>(player.vibration_strength);
-    const auto amp_low =
-        std::min(vibration_value.amp_low * player_vibration_strength / 100.0f, 1.0f);
-    const auto amp_high =
-        std::min(vibration_value.amp_high * player_vibration_strength / 100.0f, 1.0f);
-    return vibration->SetRumblePlay(amp_low, vibration_value.freq_low, amp_high,
-                                    vibration_value.freq_high);
+    Core::HID::VibrationValue vibration{vibration_value.amp_low, vibration_value.freq_low,
+                                        vibration_value.amp_high, vibration_value.freq_high};
+    return controller.device->SetVibration(device_index, vibration);
 }
 
 void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle,
@@ -869,10 +714,10 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han
     }
 
     const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
+    auto& controller = controller_data[npad_index];
     const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
 
-    if (!vibration_devices_mounted[npad_index][device_index] ||
-        !connected_controllers[npad_index].is_connected) {
+    if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) {
         return;
     }
 
@@ -882,23 +727,25 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han
     }
 
     // Some games try to send mismatched parameters in the device handle, block these.
-    if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft &&
-         (vibration_device_handle.npad_type == NpadType::JoyconRight ||
+    if ((controller.device->GetNpadType() == Core::HID::NpadType::JoyconLeft &&
+         (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconRight ||
           vibration_device_handle.device_index == DeviceIndex::Right)) ||
-        (connected_controllers[npad_index].type == NPadControllerType::JoyRight &&
-         (vibration_device_handle.npad_type == NpadType::JoyconLeft ||
+        (controller.device->GetNpadType() == Core::HID::NpadType::JoyconRight &&
+         (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconLeft ||
           vibration_device_handle.device_index == DeviceIndex::Left))) {
         return;
     }
 
     // Filter out vibrations with equivalent values to reduce unnecessary state changes.
-    if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low &&
-        vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) {
+    if (vibration_value.amp_low ==
+            controller.vibration[device_index].latest_vibration_value.amp_low &&
+        vibration_value.amp_high ==
+            controller.vibration[device_index].latest_vibration_value.amp_high) {
         return;
     }
 
     if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) {
-        latest_vibration_values[npad_index][device_index] = vibration_value;
+        controller.vibration[device_index].latest_vibration_value = vibration_value;
     }
 }
 
@@ -925,8 +772,9 @@ Controller_NPad::VibrationValue Controller_NPad::GetLastVibration(
     }
 
     const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
+    const auto& controller = controller_data[npad_index];
     const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
-    return latest_vibration_values[npad_index][device_index];
+    return controller.vibration[device_index].latest_vibration_value;
 }
 
 void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) {
@@ -941,17 +789,14 @@ void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_de
 
 void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index,
                                                        std::size_t device_index) {
+    auto& controller = controller_data[npad_index];
     if (!Settings::values.vibration_enabled.GetValue()) {
-        vibration_devices_mounted[npad_index][device_index] = false;
+        controller.vibration[device_index].device_mounted = false;
         return;
     }
 
-    if (vibrations[npad_index][device_index]) {
-        vibration_devices_mounted[npad_index][device_index] =
-            vibrations[npad_index][device_index]->GetStatus() == 1;
-    } else {
-        vibration_devices_mounted[npad_index][device_index] = false;
-    }
+    controller.vibration[device_index].device_mounted =
+        controller.device->TestVibration(device_index) == 1;
 }
 
 void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
@@ -964,42 +809,35 @@ bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_dev
     }
 
     const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
+    const auto& controller = controller_data[npad_index];
     const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
-    return vibration_devices_mounted[npad_index][device_index];
+    return controller.vibration[device_index].device_mounted;
 }
 
 Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) {
-    return styleset_changed_events[NPadIdToIndex(npad_id)]->GetReadableEvent();
+    const auto& controller = controller_data[NPadIdToIndex(npad_id)];
+    return controller.styleset_changed_event->GetReadableEvent();
 }
 
 void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const {
-    styleset_changed_events[NPadIdToIndex(npad_id)]->GetWritableEvent().Signal();
+    const auto& controller = controller_data[NPadIdToIndex(npad_id)];
+    controller.styleset_changed_event->GetWritableEvent().Signal();
 }
 
-void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) {
+void Controller_NPad::AddNewControllerAt(Core::HID::NpadType controller, std::size_t npad_index) {
     UpdateControllerAt(controller, npad_index, true);
 }
 
-void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index,
+void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t npad_index,
                                          bool connected) {
+    auto& controller = controller_data[npad_index].device;
     if (!connected) {
         DisconnectNpadAtIndex(npad_index);
         return;
     }
 
-    if (controller == NPadControllerType::Handheld && npad_index == HANDHELD_INDEX) {
-        Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type =
-            MapNPadToSettingsType(controller);
-        Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true;
-        connected_controllers[HANDHELD_INDEX] = {controller, true};
-        InitNewlyAddedController(HANDHELD_INDEX);
-        return;
-    }
-
-    Settings::values.players.GetValue()[npad_index].controller_type =
-        MapNPadToSettingsType(controller);
-    Settings::values.players.GetValue()[npad_index].connected = true;
-    connected_controllers[npad_index] = {controller, true};
+    controller->SetNpadType(type);
+    controller->Connect();
     InitNewlyAddedController(npad_index);
 }
 
@@ -1008,27 +846,27 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) {
 }
 
 void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
-    for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) {
+    auto& controller = controller_data[npad_index];
+    for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
         // Send an empty vibration to stop any vibrations.
         VibrateControllerAtIndex(npad_index, device_idx, {});
-        vibration_devices_mounted[npad_index][device_idx] = false;
+        controller.vibration[device_idx].device_mounted = false;
     }
 
-    Settings::values.players.GetValue()[npad_index].connected = false;
-    connected_controllers[npad_index].is_connected = false;
+    controller.device->Disconnect();
 
-    auto& controller = shared_memory_entries[npad_index];
-    controller.style_set.raw = 0; // Zero out
-    controller.device_type.raw = 0;
-    controller.system_properties.raw = 0;
-    controller.button_properties.raw = 0;
-    controller.battery_level_dual = 0;
-    controller.battery_level_left = 0;
-    controller.battery_level_right = 0;
-    controller.fullkey_color = {};
-    controller.joycon_color = {};
-    controller.assignment_mode = NpadAssignments::Dual;
-    controller.footer_type = AppletFooterUiType::None;
+    auto& shared_memory_entry = controller.shared_memory_entry;
+    shared_memory_entry.style_set.raw = 0; // Zero out
+    shared_memory_entry.device_type.raw = 0;
+    shared_memory_entry.system_properties.raw = 0;
+    shared_memory_entry.button_properties.raw = 0;
+    shared_memory_entry.battery_level_dual = 0;
+    shared_memory_entry.battery_level_left = 0;
+    shared_memory_entry.battery_level_right = 0;
+    shared_memory_entry.fullkey_color = {};
+    shared_memory_entry.joycon_color = {};
+    shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual;
+    shared_memory_entry.footer_type = AppletFooterUiType::None;
 
     SignalStyleSetChangedEvent(IndexToNPad(npad_index));
 }
@@ -1069,16 +907,18 @@ void Controller_NPad::ResetSixAxisFusionParameters() {
 void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
     const auto npad_index_1 = NPadIdToIndex(npad_id_1);
     const auto npad_index_2 = NPadIdToIndex(npad_id_2);
+    const auto& controller_1 = controller_data[npad_index_1].device;
+    const auto& controller_2 = controller_data[npad_index_2].device;
 
     // If the controllers at both npad indices form a pair of left and right joycons, merge them.
     // Otherwise, do nothing.
-    if ((connected_controllers[npad_index_1].type == NPadControllerType::JoyLeft &&
-         connected_controllers[npad_index_2].type == NPadControllerType::JoyRight) ||
-        (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft &&
-         connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) {
+    if ((controller_1->GetNpadType() == Core::HID::NpadType::JoyconLeft &&
+         controller_2->GetNpadType() == Core::HID::NpadType::JoyconRight) ||
+        (controller_2->GetNpadType() == Core::HID::NpadType::JoyconLeft &&
+         controller_1->GetNpadType() == Core::HID::NpadType::JoyconRight)) {
         // Disconnect the joycon at the second id and connect the dual joycon at the first index.
         DisconnectNpad(npad_id_2);
-        AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1);
+        AddNewControllerAt(Core::HID::NpadType::JoyconDual, npad_index_1);
     }
 }
 
@@ -1099,16 +939,17 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
     }
     const auto npad_index_1 = NPadIdToIndex(npad_id_1);
     const auto npad_index_2 = NPadIdToIndex(npad_id_2);
+    const auto& controller_1 = controller_data[npad_index_1].device;
+    const auto& controller_2 = controller_data[npad_index_2].device;
+    const auto type_index_1 = controller_1->GetNpadType();
+    const auto type_index_2 = controller_2->GetNpadType();
 
-    if (!IsControllerSupported(connected_controllers[npad_index_1].type) ||
-        !IsControllerSupported(connected_controllers[npad_index_2].type)) {
+    if (!IsControllerSupported(type_index_1) || !IsControllerSupported(type_index_2)) {
         return false;
     }
 
-    std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type);
-
-    AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1);
-    AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2);
+    AddNewControllerAt(type_index_2, npad_index_1);
+    AddNewControllerAt(type_index_1, npad_index_2);
 
     return true;
 }
@@ -1141,12 +982,14 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
 }
 
 bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const {
-    return unintended_home_button_input_protection[NPadIdToIndex(npad_id)];
+    auto& controller = controller_data[NPadIdToIndex(npad_id)];
+    return controller.unintended_home_button_input_protection;
 }
 
 void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
                                                                     u32 npad_id) {
-    unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled;
+    auto& controller = controller_data[NPadIdToIndex(npad_id)];
+    controller.unintended_home_button_input_protection = is_protection_enabled;
 }
 
 void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
@@ -1154,32 +997,34 @@ void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
 }
 
 void Controller_NPad::ClearAllConnectedControllers() {
-    for (auto& controller : connected_controllers) {
-        if (controller.is_connected && controller.type != NPadControllerType::None) {
-            controller.type = NPadControllerType::None;
-            controller.is_connected = false;
+    for (auto& controller : controller_data) {
+        if (controller.device->IsConnected() &&
+            controller.device->GetNpadType() != Core::HID::NpadType::None) {
+            controller.device->SetNpadType(Core::HID::NpadType::None);
+            controller.device->Disconnect();
         }
     }
 }
 
 void Controller_NPad::DisconnectAllConnectedControllers() {
-    for (auto& controller : connected_controllers) {
-        controller.is_connected = false;
+    for (auto& controller : controller_data) {
+        controller.device->Disconnect();
     }
 }
 
 void Controller_NPad::ConnectAllDisconnectedControllers() {
-    for (auto& controller : connected_controllers) {
-        if (controller.type != NPadControllerType::None && !controller.is_connected) {
-            controller.is_connected = true;
+    for (auto& controller : controller_data) {
+        if (controller.device->GetNpadType() != Core::HID::NpadType::None &&
+            !controller.device->IsConnected()) {
+            controller.device->Connect();
         }
     }
 }
 
 void Controller_NPad::ClearAllControllers() {
-    for (auto& controller : connected_controllers) {
-        controller.type = NPadControllerType::None;
-        controller.is_connected = false;
+    for (auto& controller : controller_data) {
+        controller.device->SetNpadType(Core::HID::NpadType::None);
+        controller.device->Disconnect();
     }
 }
 
@@ -1187,8 +1032,8 @@ u32 Controller_NPad::GetAndResetPressState() {
     return press_state.exchange(0);
 }
 
-bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const {
-    if (controller == NPadControllerType::Handheld) {
+bool Controller_NPad::IsControllerSupported(Core::HID::NpadType controller) const {
+    if (controller == Core::HID::NpadType::Handheld) {
         const bool support_handheld =
             std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
                       NPAD_HANDHELD) != supported_npad_id_types.end();
@@ -1196,7 +1041,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
         if (!support_handheld) {
             return false;
         }
-        // Handheld should not be supported in docked mode
+        // Handheld shouldn't be supported in docked mode
         if (Settings::values.use_docked_mode.GetValue()) {
             return false;
         }
@@ -1206,18 +1051,19 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
 
     if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
                     [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
+        Core::HID::NpadStyleTag style = GetSupportedStyleSet();
         switch (controller) {
-        case NPadControllerType::ProController:
+        case Core::HID::NpadType::ProController:
             return style.fullkey;
-        case NPadControllerType::JoyDual:
+        case Core::HID::NpadType::JoyconDual:
             return style.joycon_dual;
-        case NPadControllerType::JoyLeft:
+        case Core::HID::NpadType::JoyconLeft:
             return style.joycon_left;
-        case NPadControllerType::JoyRight:
+        case Core::HID::NpadType::JoyconRight:
             return style.joycon_right;
-        case NPadControllerType::GameCube:
+        case Core::HID::NpadType::GameCube:
             return style.gamecube;
-        case NPadControllerType::Pokeball:
+        case Core::HID::NpadType::Pokeball:
             return style.palma;
         default:
             return false;
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index f3e868bdbb..483cae5b68 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -12,8 +12,10 @@
 #include "common/common_types.h"
 #include "common/quaternion.h"
 #include "common/settings.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/ring_lifo.h"
 
 namespace Kernel {
 class KEvent;
@@ -48,31 +50,6 @@ public:
     void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                         std::size_t size) override;
 
-    // Called when input devices should be loaded
-    void OnLoadInputDevices() override;
-
-    enum class NPadControllerType {
-        None,
-        ProController,
-        Handheld,
-        JoyDual,
-        JoyLeft,
-        JoyRight,
-        GameCube,
-        Pokeball,
-    };
-
-    enum class NpadType : u8 {
-        ProController = 3,
-        Handheld = 4,
-        JoyconDual = 5,
-        JoyconLeft = 6,
-        JoyconRight = 7,
-        GameCube = 8,
-        Pokeball = 9,
-        MaxNpadType = 10,
-    };
-
     enum class DeviceIndex : u8 {
         Left = 0,
         Right = 1,
@@ -80,28 +57,33 @@ public:
         MaxDeviceIndex = 3,
     };
 
+    // This is nn::hid::GyroscopeZeroDriftMode
     enum class GyroscopeZeroDriftMode : u32 {
         Loose = 0,
         Standard = 1,
         Tight = 2,
     };
 
-    enum class NpadHoldType : u64 {
+    // This is nn::hid::NpadJoyHoldType
+    enum class NpadJoyHoldType : u64 {
         Vertical = 0,
         Horizontal = 1,
     };
 
-    enum class NpadAssignments : u32 {
+    // This is nn::hid::NpadJoyAssignmentMode
+    enum class NpadJoyAssignmentMode : u32 {
         Dual = 0,
         Single = 1,
     };
 
+    // This is nn::hid::NpadHandheldActivationMode
     enum class NpadHandheldActivationMode : u64 {
         Dual = 0,
         Single = 1,
         None = 2,
     };
 
+    // This is nn::hid::NpadCommunicationMode
     enum class NpadCommunicationMode : u64 {
         Mode_5ms = 0,
         Mode_10ms = 1,
@@ -110,33 +92,14 @@ public:
     };
 
     struct DeviceHandle {
-        NpadType npad_type;
+        Core::HID::NpadType npad_type;
         u8 npad_id;
         DeviceIndex device_index;
         INSERT_PADDING_BYTES_NOINIT(1);
     };
     static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size");
 
-    struct NpadStyleSet {
-        union {
-            u32_le raw{};
-
-            BitField<0, 1, u32> fullkey;
-            BitField<1, 1, u32> handheld;
-            BitField<2, 1, u32> joycon_dual;
-            BitField<3, 1, u32> joycon_left;
-            BitField<4, 1, u32> joycon_right;
-            BitField<5, 1, u32> gamecube;
-            BitField<6, 1, u32> palma;
-            BitField<7, 1, u32> lark;
-            BitField<8, 1, u32> handheld_lark;
-            BitField<9, 1, u32> lucia;
-            BitField<29, 1, u32> system_ext;
-            BitField<30, 1, u32> system;
-        };
-    };
-    static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
-
+    // This is nn::hid::VibrationValue
     struct VibrationValue {
         f32 amp_low;
         f32 freq_low;
@@ -168,15 +131,15 @@ public:
         };
     };
 
-    void SetSupportedStyleSet(NpadStyleSet style_set);
-    NpadStyleSet GetSupportedStyleSet() const;
+    void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
+    Core::HID::NpadStyleTag GetSupportedStyleSet() const;
 
     void SetSupportedNpadIdTypes(u8* data, std::size_t length);
     void GetSupportedNpadIdTypes(u32* data, std::size_t max_length);
     std::size_t GetSupportedNpadIdTypesSize() const;
 
-    void SetHoldType(NpadHoldType joy_hold_type);
-    NpadHoldType GetHoldType() const;
+    void SetHoldType(NpadJoyHoldType joy_hold_type);
+    NpadJoyHoldType GetHoldType() const;
 
     void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode);
     NpadHandheldActivationMode GetNpadHandheldActivationMode() const;
@@ -184,7 +147,7 @@ public:
     void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_);
     NpadCommunicationMode GetNpadCommunicationMode() const;
 
-    void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode);
+    void SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode);
 
     bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index,
                                   const VibrationValue& vibration_value);
@@ -209,9 +172,9 @@ public:
     void SignalStyleSetChangedEvent(u32 npad_id) const;
 
     // Adds a new controller at an index.
-    void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index);
+    void AddNewControllerAt(Core::HID::NpadType controller, std::size_t npad_index);
     // Adds a new controller at an index with connection status.
-    void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected);
+    void UpdateControllerAt(Core::HID::NpadType controller, std::size_t npad_index, bool connected);
 
     void DisconnectNpad(u32 npad_id);
     void DisconnectNpadAtIndex(std::size_t index);
@@ -241,103 +204,37 @@ public:
     // Specifically for cheat engine and other features.
     u32 GetAndResetPressState();
 
-    static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type);
-    static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type);
     static std::size_t NPadIdToIndex(u32 npad_id);
     static u32 IndexToNPad(std::size_t index);
     static bool IsNpadIdValid(u32 npad_id);
     static bool IsDeviceHandleValid(const DeviceHandle& device_handle);
 
 private:
-    struct CommonHeader {
-        s64_le timestamp;
-        s64_le total_entry_count;
-        s64_le last_entry_index;
-        s64_le entry_count;
-    };
-    static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
-
-    enum class ColorAttributes : u32_le {
+    // This is nn::hid::detail::ColorAttribute
+    enum class ColorAttribute : u32_le {
         Ok = 0,
         ReadError = 1,
         NoController = 2,
     };
-    static_assert(sizeof(ColorAttributes) == 4, "ColorAttributes is an invalid size");
+    static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size");
 
-    struct ControllerColor {
-        u32_le body;
-        u32_le button;
+    // This is nn::hid::detail::NpadFullKeyColorState
+    struct NpadFullKeyColorState {
+        ColorAttribute attribute;
+        Core::HID::NpadControllerColor fullkey;
     };
-    static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size");
+    static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size");
 
-    struct FullKeyColor {
-        ColorAttributes attribute;
-        ControllerColor fullkey;
+    // This is nn::hid::detail::NpadJoyColorState
+    struct NpadJoyColorState {
+        ColorAttribute attribute;
+        Core::HID::NpadControllerColor left;
+        Core::HID::NpadControllerColor right;
     };
-    static_assert(sizeof(FullKeyColor) == 0xC, "FullKeyColor is an invalid size");
+    static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size");
 
-    struct JoyconColor {
-        ColorAttributes attribute;
-        ControllerColor left;
-        ControllerColor right;
-    };
-    static_assert(sizeof(JoyconColor) == 0x14, "JoyconColor is an invalid size");
-
-    struct ControllerPadState {
-        union {
-            u64_le raw{};
-            // Button states
-            BitField<0, 1, u64> a;
-            BitField<1, 1, u64> b;
-            BitField<2, 1, u64> x;
-            BitField<3, 1, u64> y;
-            BitField<4, 1, u64> l_stick;
-            BitField<5, 1, u64> r_stick;
-            BitField<6, 1, u64> l;
-            BitField<7, 1, u64> r;
-            BitField<8, 1, u64> zl;
-            BitField<9, 1, u64> zr;
-            BitField<10, 1, u64> plus;
-            BitField<11, 1, u64> minus;
-
-            // D-Pad
-            BitField<12, 1, u64> d_left;
-            BitField<13, 1, u64> d_up;
-            BitField<14, 1, u64> d_right;
-            BitField<15, 1, u64> d_down;
-
-            // Left JoyStick
-            BitField<16, 1, u64> l_stick_left;
-            BitField<17, 1, u64> l_stick_up;
-            BitField<18, 1, u64> l_stick_right;
-            BitField<19, 1, u64> l_stick_down;
-
-            // Right JoyStick
-            BitField<20, 1, u64> r_stick_left;
-            BitField<21, 1, u64> r_stick_up;
-            BitField<22, 1, u64> r_stick_right;
-            BitField<23, 1, u64> r_stick_down;
-
-            // Not always active?
-            BitField<24, 1, u64> left_sl;
-            BitField<25, 1, u64> left_sr;
-
-            BitField<26, 1, u64> right_sl;
-            BitField<27, 1, u64> right_sr;
-
-            BitField<28, 1, u64> palma;
-            BitField<30, 1, u64> handheld_left_b;
-        };
-    };
-    static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size");
-
-    struct AnalogPosition {
-        s32_le x;
-        s32_le y;
-    };
-    static_assert(sizeof(AnalogPosition) == 8, "AnalogPosition is an invalid size");
-
-    struct ConnectionState {
+    // This is nn::hid::NpadAttribute
+    struct NpadAttribute {
         union {
             u32_le raw{};
             BitField<0, 1, u32> is_connected;
@@ -348,76 +245,57 @@ private:
             BitField<5, 1, u32> is_right_wired;
         };
     };
-    static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size");
+    static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size");
 
-    struct ControllerPad {
-        ControllerPadState pad_states;
-        AnalogPosition l_stick;
-        AnalogPosition r_stick;
+    // This is nn::hid::NpadFullKeyState
+    // This is nn::hid::NpadHandheldState
+    // This is nn::hid::NpadJoyDualState
+    // This is nn::hid::NpadJoyLeftState
+    // This is nn::hid::NpadJoyRightState
+    // This is nn::hid::NpadPalmaState
+    // This is nn::hid::NpadSystemExtState
+    struct NPadGenericState {
+        s64_le sampling_number;
+        Core::HID::NpadButtonState npad_buttons;
+        Core::HID::AnalogStickState l_stick;
+        Core::HID::AnalogStickState r_stick;
+        NpadAttribute connection_status;
+        INSERT_PADDING_BYTES(4); // Reserved
     };
-    static_assert(sizeof(ControllerPad) == 0x18, "ControllerPad is an invalid size");
+    static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
 
-    struct GenericStates {
-        s64_le timestamp;
-        s64_le timestamp2;
-        ControllerPad pad;
-        ConnectionState connection_status;
-    };
-    static_assert(sizeof(GenericStates) == 0x30, "NPadGenericStates is an invalid size");
-
-    struct NPadGeneric {
-        CommonHeader common;
-        std::array<GenericStates, 17> npad;
-    };
-    static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size");
-
-    struct SixAxisAttributes {
+    // This is nn::hid::SixAxisSensorAttribute
+    struct SixAxisSensorAttribute {
         union {
             u32_le raw{};
             BitField<0, 1, u32> is_connected;
             BitField<1, 1, u32> is_interpolated;
         };
     };
-    static_assert(sizeof(SixAxisAttributes) == 4, "SixAxisAttributes is an invalid size");
+    static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size");
 
-    struct SixAxisStates {
-        s64_le timestamp{};
-        INSERT_PADDING_WORDS(2);
-        s64_le timestamp2{};
+    // This is nn::hid::SixAxisSensorState
+    struct SixAxisSensorState {
+        s64_le delta_time{};
+        s64_le sampling_number{};
         Common::Vec3f accel{};
         Common::Vec3f gyro{};
         Common::Vec3f rotation{};
         std::array<Common::Vec3f, 3> orientation{};
-        SixAxisAttributes attribute;
+        SixAxisSensorAttribute attribute;
         INSERT_PADDING_BYTES(4); // Reserved
     };
-    static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size");
+    static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size");
 
-    struct SixAxisGeneric {
-        CommonHeader common{};
-        std::array<SixAxisStates, 17> sixaxis{};
-    };
-    static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size");
-
-    struct TriggerState {
-        s64_le timestamp{};
-        s64_le timestamp2{};
+    // This is nn::hid::server::NpadGcTriggerState
+    struct NpadGcTriggerState {
+        s64_le sampling_number{};
         s32_le l_analog{};
         s32_le r_analog{};
     };
-    static_assert(sizeof(TriggerState) == 0x18, "TriggerState is an invalid size");
-
-    struct TriggerGeneric {
-        INSERT_PADDING_BYTES(0x4);
-        s64_le timestamp;
-        INSERT_PADDING_BYTES(0x4);
-        s64_le total_entry_count;
-        s64_le last_entry_index;
-        s64_le entry_count;
-        std::array<TriggerState, 17> trigger{};
-    };
-    static_assert(sizeof(TriggerGeneric) == 0x1C8, "TriggerGeneric is an invalid size");
+    static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
 
+    // This is nn::hid::NpadSystemProperties
     struct NPadSystemProperties {
         union {
             s64_le raw{};
@@ -438,15 +316,18 @@ private:
     };
     static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
 
-    struct NPadButtonProperties {
+    // This is nn::hid::NpadSystemButtonProperties
+    struct NpadSystemButtonProperties {
         union {
             s32_le raw{};
             BitField<0, 1, s32> is_home_button_protection_enabled;
         };
     };
-    static_assert(sizeof(NPadButtonProperties) == 0x4, "NPadButtonProperties is an invalid size");
+    static_assert(sizeof(NpadSystemButtonProperties) == 0x4,
+                  "NPadButtonProperties is an invalid size");
 
-    struct NPadDevice {
+    // This is nn::hid::system::DeviceType
+    struct DeviceType {
         union {
             u32_le raw{};
             BitField<0, 1, s32> fullkey;
@@ -469,14 +350,6 @@ private:
         };
     };
 
-    struct MotionDevice {
-        Common::Vec3f accel;
-        Common::Vec3f gyro;
-        Common::Vec3f rotation;
-        std::array<Common::Vec3f, 3> orientation;
-        Common::Quaternion<f32> quaternion;
-    };
-
     struct NfcXcdHandle {
         INSERT_PADDING_BYTES(0x60);
     };
@@ -485,6 +358,7 @@ private:
         INSERT_PADDING_BYTES(0x4);
     };
 
+    // This is nn::hid::server::NpadGcTriggerState
     enum class AppletFooterUiType : u8 {
         None = 0,
         HandheldNone = 1,
@@ -510,95 +384,90 @@ private:
         Lagon = 21,
     };
 
-    struct NPadEntry {
-        NpadStyleSet style_set;
-        NpadAssignments assignment_mode;
-        FullKeyColor fullkey_color;
-        JoyconColor joycon_color;
-
-        NPadGeneric fullkey_states;
-        NPadGeneric handheld_states;
-        NPadGeneric joy_dual_states;
-        NPadGeneric joy_left_states;
-        NPadGeneric joy_right_states;
-        NPadGeneric palma_states;
-        NPadGeneric system_ext_states;
-        SixAxisGeneric sixaxis_fullkey;
-        SixAxisGeneric sixaxis_handheld;
-        SixAxisGeneric sixaxis_dual_left;
-        SixAxisGeneric sixaxis_dual_right;
-        SixAxisGeneric sixaxis_left;
-        SixAxisGeneric sixaxis_right;
-        NPadDevice device_type;
-        INSERT_PADDING_BYTES(0x4); // reserved
+    // This is nn::hid::detail::NpadInternalState
+    struct NpadInternalState {
+        Core::HID::NpadStyleTag style_set;
+        NpadJoyAssignmentMode assignment_mode;
+        NpadFullKeyColorState fullkey_color;
+        NpadJoyColorState joycon_color;
+        Lifo<NPadGenericState> fullkey_lifo;
+        Lifo<NPadGenericState> handheld_lifo;
+        Lifo<NPadGenericState> joy_dual_lifo;
+        Lifo<NPadGenericState> joy_left_lifo;
+        Lifo<NPadGenericState> joy_right_lifo;
+        Lifo<NPadGenericState> palma_lifo;
+        Lifo<NPadGenericState> system_ext_lifo;
+        Lifo<SixAxisSensorState> sixaxis_fullkey_lifo;
+        Lifo<SixAxisSensorState> sixaxis_handheld_lifo;
+        Lifo<SixAxisSensorState> sixaxis_dual_left_lifo;
+        Lifo<SixAxisSensorState> sixaxis_dual_right_lifo;
+        Lifo<SixAxisSensorState> sixaxis_left_lifo;
+        Lifo<SixAxisSensorState> sixaxis_right_lifo;
+        DeviceType device_type;
+        INSERT_PADDING_BYTES(0x4); // Reserved
         NPadSystemProperties system_properties;
-        NPadButtonProperties button_properties;
-        u32 battery_level_dual;
-        u32 battery_level_left;
-        u32 battery_level_right;
+        NpadSystemButtonProperties button_properties;
+        Core::HID::BatteryLevel battery_level_dual;
+        Core::HID::BatteryLevel battery_level_left;
+        Core::HID::BatteryLevel battery_level_right;
         AppletFooterUiAttributes footer_attributes;
         AppletFooterUiType footer_type;
-        // nfc_states needs to be checked switchbrew does not match with HW
+        // nfc_states needs to be checked switchbrew doesn't match with HW
         NfcXcdHandle nfc_states;
-        INSERT_PADDING_BYTES(0x8); // Mutex
-        TriggerGeneric gc_trigger_states;
-        INSERT_PADDING_BYTES(0xc1f);
+        INSERT_PADDING_BYTES(0x18); // Unknown
+        Lifo<NpadGcTriggerState> gc_trigger_lifo;
+        INSERT_PADDING_BYTES(0xc1f); // Unknown
     };
-    static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size");
+    static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
 
-    struct ControllerHolder {
-        NPadControllerType type;
-        bool is_connected;
+    struct VibrationData {
+        bool device_mounted{};
+        VibrationValue latest_vibration_value{};
+        std::chrono::steady_clock::time_point last_vibration_timepoint{};
     };
 
+    struct ControllerData {
+        Core::HID::EmulatedController* device;
+        Kernel::KEvent* styleset_changed_event{};
+        NpadInternalState shared_memory_entry{};
+
+        std::array<VibrationData, 2> vibration{};
+        bool unintended_home_button_input_protection{};
+
+        // Current pad state
+        NPadGenericState npad_pad_state{};
+        NPadGenericState npad_libnx_state{};
+        NpadGcTriggerState npad_trigger_state{};
+        SixAxisSensorState sixaxis_fullkey_state{};
+        SixAxisSensorState sixaxis_handheld_state{};
+        SixAxisSensorState sixaxis_dual_left_state{};
+        SixAxisSensorState sixaxis_dual_right_state{};
+        SixAxisSensorState sixaxis_left_lifo_state{};
+        SixAxisSensorState sixaxis_right_lifo_state{};
+        int callback_key;
+    };
+
+    void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx);
     void InitNewlyAddedController(std::size_t controller_idx);
-    bool IsControllerSupported(NPadControllerType controller) const;
+    bool IsControllerSupported(Core::HID::NpadType controller) const;
     void RequestPadStateUpdate(u32 npad_id);
 
     std::atomic<u32> press_state{};
 
-    NpadStyleSet style{};
-    std::array<NPadEntry, 10> shared_memory_entries{};
-    using ButtonArray = std::array<
-        std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>,
-        10>;
-    using StickArray = std::array<
-        std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NumAnalogs>,
-        10>;
-    using VibrationArray = std::array<std::array<std::unique_ptr<Input::VibrationDevice>,
-                                                 Settings::NativeVibration::NUM_VIBRATIONS_HID>,
-                                      10>;
-    using MotionArray = std::array<
-        std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>,
-        10>;
-
+    std::array<ControllerData, 10> controller_data{};
     KernelHelpers::ServiceContext& service_context;
     std::mutex mutex;
-    ButtonArray buttons;
-    StickArray sticks;
-    VibrationArray vibrations;
-    MotionArray motions;
     std::vector<u32> supported_npad_id_types{};
-    NpadHoldType hold_type{NpadHoldType::Vertical};
+    NpadJoyHoldType hold_type{NpadJoyHoldType::Vertical};
     NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
     NpadCommunicationMode communication_mode{NpadCommunicationMode::Default};
-    // Each controller should have their own styleset changed event
-    std::array<Kernel::KEvent*, 10> styleset_changed_events{};
-    std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10>
-        last_vibration_timepoints{};
-    std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{};
     bool permit_vibration_session_enabled{false};
-    std::array<std::array<bool, 2>, 10> vibration_devices_mounted{};
-    std::array<ControllerHolder, 10> connected_controllers{};
-    std::array<bool, 10> unintended_home_button_input_protection{};
     bool analog_stick_use_center_clamp{};
     GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
     bool sixaxis_sensors_enabled{true};
     f32 sixaxis_fusion_parameter1{};
     f32 sixaxis_fusion_parameter2{};
     bool sixaxis_at_rest{true};
-    std::array<ControllerPad, 10> npad_pad_states{};
-    std::array<TriggerState, 10> npad_trigger_states{};
     bool is_in_lr_assignment_mode{false};
 };
 } // namespace Service::HID

From dd62a0187d2f8208e288528a7cbf01810bfed20a Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:39:43 -0500
Subject: [PATCH 32/88] core: Remove frontend/input

---
 src/core/frontend/input.h | 217 --------------------------------------
 1 file changed, 217 deletions(-)
 delete mode 100644 src/core/frontend/input.h

diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h
deleted file mode 100644
index f1747c5b23..0000000000
--- a/src/core/frontend/input.h
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <functional>
-#include <memory>
-#include <string>
-#include <tuple>
-#include <unordered_map>
-#include <utility>
-#include "common/logging/log.h"
-#include "common/param_package.h"
-#include "common/quaternion.h"
-#include "common/vector_math.h"
-
-namespace Input {
-
-enum class AnalogDirection : u8 {
-    RIGHT,
-    LEFT,
-    UP,
-    DOWN,
-};
-struct AnalogProperties {
-    float deadzone;
-    float range;
-    float threshold;
-};
-template <typename StatusType>
-struct InputCallback {
-    std::function<void(StatusType)> on_change;
-};
-
-/// An abstract class template for an input device (a button, an analog input, etc.).
-template <typename StatusType>
-class InputDevice {
-public:
-    virtual ~InputDevice() = default;
-    virtual StatusType GetStatus() const {
-        return {};
-    }
-    virtual StatusType GetRawStatus() const {
-        return GetStatus();
-    }
-    virtual AnalogProperties GetAnalogProperties() const {
-        return {};
-    }
-    virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const {
-        return {};
-    }
-    virtual bool SetRumblePlay([[maybe_unused]] f32 amp_low, [[maybe_unused]] f32 freq_low,
-                               [[maybe_unused]] f32 amp_high,
-                               [[maybe_unused]] f32 freq_high) const {
-        return {};
-    }
-    void SetCallback(InputCallback<StatusType> callback_) {
-        callback = std::move(callback_);
-    }
-    void TriggerOnChange() {
-        if (callback.on_change) {
-            callback.on_change(GetStatus());
-        }
-    }
-
-private:
-    InputCallback<StatusType> callback;
-};
-
-/// An abstract class template for a factory that can create input devices.
-template <typename InputDeviceType>
-class Factory {
-public:
-    virtual ~Factory() = default;
-    virtual std::unique_ptr<InputDeviceType> Create(const Common::ParamPackage&) = 0;
-};
-
-namespace Impl {
-
-template <typename InputDeviceType>
-using FactoryListType = std::unordered_map<std::string, std::shared_ptr<Factory<InputDeviceType>>>;
-
-template <typename InputDeviceType>
-struct FactoryList {
-    static FactoryListType<InputDeviceType> list;
-};
-
-template <typename InputDeviceType>
-FactoryListType<InputDeviceType> FactoryList<InputDeviceType>::list;
-
-} // namespace Impl
-
-/**
- * Registers an input device factory.
- * @tparam InputDeviceType the type of input devices the factory can create
- * @param name the name of the factory. Will be used to match the "engine" parameter when creating
- *     a device
- * @param factory the factory object to register
- */
-template <typename InputDeviceType>
-void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDeviceType>> factory) {
-    auto pair = std::make_pair(name, std::move(factory));
-    if (!Impl::FactoryList<InputDeviceType>::list.insert(std::move(pair)).second) {
-        LOG_ERROR(Input, "Factory '{}' already registered", name);
-    }
-}
-
-/**
- * Unregisters an input device factory.
- * @tparam InputDeviceType the type of input devices the factory can create
- * @param name the name of the factory to unregister
- */
-template <typename InputDeviceType>
-void UnregisterFactory(const std::string& name) {
-    if (Impl::FactoryList<InputDeviceType>::list.erase(name) == 0) {
-        LOG_ERROR(Input, "Factory '{}' not registered", name);
-    }
-}
-
-/**
- * Create an input device from given paramters.
- * @tparam InputDeviceType the type of input devices to create
- * @param params a serialized ParamPackage string contains all parameters for creating the device
- */
-template <typename InputDeviceType>
-std::unique_ptr<InputDeviceType> CreateDevice(const std::string& params) {
-    const Common::ParamPackage package(params);
-    const std::string engine = package.Get("engine", "null");
-    const auto& factory_list = Impl::FactoryList<InputDeviceType>::list;
-    const auto pair = factory_list.find(engine);
-    if (pair == factory_list.end()) {
-        if (engine != "null") {
-            LOG_ERROR(Input, "Unknown engine name: {}", engine);
-        }
-        return std::make_unique<InputDeviceType>();
-    }
-    return pair->second->Create(package);
-}
-
-/**
- * A button device is an input device that returns bool as status.
- * true for pressed; false for released.
- */
-using ButtonDevice = InputDevice<bool>;
-
-/**
- * An analog device is an input device that returns a tuple of x and y coordinates as status. The
- * coordinates are within the unit circle. x+ is defined as right direction, and y+ is defined as up
- * direction
- */
-using AnalogDevice = InputDevice<std::tuple<float, float>>;
-
-/**
- * A vibration device is an input device that returns an unsigned byte as status.
- * It represents whether the vibration device supports vibration or not.
- * If the status returns 1, it supports vibration. Otherwise, it does not support vibration.
- */
-using VibrationDevice = InputDevice<u8>;
-
-/**
- * A motion status is an object that returns a tuple of accelerometer state vector,
- * gyroscope state vector, rotation state vector, orientation state matrix and quaterion state
- * vector.
- *
- * For both 3D vectors:
- *   x+ is the same direction as RIGHT on D-pad.
- *   y+ is normal to the touch screen, pointing outward.
- *   z+ is the same direction as UP on D-pad.
- *
- * For accelerometer state vector
- *   Units: g (gravitational acceleration)
- *
- * For gyroscope state vector:
- *   Orientation is determined by right-hand rule.
- *   Units: deg/sec
- *
- * For rotation state vector
- *   Units: rotations
- *
- * For orientation state matrix
- *   x vector
- *   y vector
- *   z vector
- *
- * For quaternion state vector
- *   xyz vector
- *   w float
- */
-using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common::Vec3<float>,
-                                std::array<Common::Vec3f, 3>, Common::Quaternion<f32>>;
-
-/**
- * A motion device is an input device that returns a motion status object
- */
-using MotionDevice = InputDevice<MotionStatus>;
-
-/**
- * A touch status is an object that returns an array of 16 tuple elements of two floats and a bool.
- * The floats are x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is
- * pressed.
- */
-using TouchStatus = std::array<std::tuple<float, float, bool>, 16>;
-
-/**
- * A touch device is an input device that returns a touch status object
- */
-using TouchDevice = InputDevice<TouchStatus>;
-
-/**
- * A mouse device is an input device that returns a tuple of two floats and four ints.
- * The first two floats are X and Y device coordinates of the mouse (from 0-1).
- * The s32s are the mouse wheel.
- */
-using MouseDevice = InputDevice<std::tuple<float, float, s32, s32>>;
-
-} // namespace Input

From 510c7d29537f4d17ec5751b981729e1bf66fe44c Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:46:17 -0500
Subject: [PATCH 33/88] core/frontend: Update applets

---
 src/core/frontend/applets/controller.cpp      | 23 +++++++++++--------
 .../service/am/applets/applet_controller.cpp  |  2 +-
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp
index 03bbedf8b8..ca1edce15f 100644
--- a/src/core/frontend/applets/controller.cpp
+++ b/src/core/frontend/applets/controller.cpp
@@ -49,26 +49,31 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
         // Connect controllers based on the following priority list from highest to lowest priority:
         // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
         if (parameters.allow_pro_controller) {
-            npad.AddNewControllerAt(
-                npad.MapSettingsTypeToNPad(Settings::ControllerType::ProController), index);
+            npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(
+                                        Settings::ControllerType::ProController),
+                                    index);
         } else if (parameters.allow_dual_joycons) {
-            npad.AddNewControllerAt(
-                npad.MapSettingsTypeToNPad(Settings::ControllerType::DualJoyconDetached), index);
+            npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(
+                                        Settings::ControllerType::DualJoyconDetached),
+                                    index);
         } else if (parameters.allow_left_joycon && parameters.allow_right_joycon) {
             // Assign left joycons to even player indices and right joycons to odd player indices.
             // We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and
             // a right Joycon for Player 2 in 2 Player Assist mode.
             if (index % 2 == 0) {
-                npad.AddNewControllerAt(
-                    npad.MapSettingsTypeToNPad(Settings::ControllerType::LeftJoycon), index);
+                npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(
+                                            Settings::ControllerType::LeftJoycon),
+                                        index);
             } else {
-                npad.AddNewControllerAt(
-                    npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index);
+                npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(
+                                            Settings::ControllerType::RightJoycon),
+                                        index);
             }
         } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
                    !Settings::values.use_docked_mode.GetValue()) {
             // We should *never* reach here under any normal circumstances.
-            npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld),
+            npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(
+                                        Settings::ControllerType::Handheld),
                                     index);
         } else {
             UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!");
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index 2721679c10..c1b6cd1266 100644
--- a/src/core/hle/service/am/applets/applet_controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -25,7 +25,7 @@ namespace Service::AM::Applets {
 static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
     ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text,
     std::vector<IdentificationColor> identification_colors, std::vector<ExplainText> text) {
-    HID::Controller_NPad::NpadStyleSet npad_style_set;
+    Core::HID::NpadStyleTag npad_style_set;
     npad_style_set.raw = private_arg.style_set;
 
     return {

From 1b82d5bb4f9440603e7af0af6abed7968aef37e4 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:50:32 -0500
Subject: [PATCH 34/88] yuzu: Update overlay applet

---
 src/yuzu/util/overlay_dialog.cpp | 27 +++++++++++++++------------
 src/yuzu/util/overlay_dialog.h   | 10 ++++++----
 2 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/src/yuzu/util/overlay_dialog.cpp b/src/yuzu/util/overlay_dialog.cpp
index 95b1485450..c66dfbdff0 100644
--- a/src/yuzu/util/overlay_dialog.cpp
+++ b/src/yuzu/util/overlay_dialog.cpp
@@ -6,7 +6,8 @@
 #include <QScreen>
 
 #include "core/core.h"
-#include "core/frontend/input_interpreter.h"
+#include "core/hid/hid_types.h"
+#include "core/hid/input_interpreter.h"
 #include "ui_overlay_dialog.h"
 #include "yuzu/util/overlay_dialog.h"
 
@@ -179,9 +180,9 @@ void OverlayDialog::MoveAndResizeWindow() {
     QDialog::resize(width, height);
 }
 
-template <HIDButton... T>
+template <Core::HID::NpadButton... T>
 void OverlayDialog::HandleButtonPressedOnce() {
-    const auto f = [this](HIDButton button) {
+    const auto f = [this](Core::HID::NpadButton button) {
         if (input_interpreter->IsButtonPressedOnce(button)) {
             TranslateButtonPress(button);
         }
@@ -190,7 +191,7 @@ void OverlayDialog::HandleButtonPressedOnce() {
     (f(T), ...);
 }
 
-void OverlayDialog::TranslateButtonPress(HIDButton button) {
+void OverlayDialog::TranslateButtonPress(Core::HID::NpadButton button) {
     QPushButton* left_button = use_rich_text ? ui->button_cancel_rich : ui->button_cancel;
     QPushButton* right_button = use_rich_text ? ui->button_ok_rich : ui->button_ok_label;
 
@@ -198,20 +199,20 @@ void OverlayDialog::TranslateButtonPress(HIDButton button) {
     // TODO (Morph): focusPrevious/NextChild() doesn't work well with the rich text dialog, fix it
 
     switch (button) {
-    case HIDButton::A:
-    case HIDButton::B:
+    case Core::HID::NpadButton::A:
+    case Core::HID::NpadButton::B:
         if (left_button->hasFocus()) {
             left_button->click();
         } else if (right_button->hasFocus()) {
             right_button->click();
         }
         break;
-    case HIDButton::DLeft:
-    case HIDButton::LStickLeft:
+    case Core::HID::NpadButton::Left:
+    case Core::HID::NpadButton::StickLLeft:
         focusPreviousChild();
         break;
-    case HIDButton::DRight:
-    case HIDButton::LStickRight:
+    case Core::HID::NpadButton::Right:
+    case Core::HID::NpadButton::StickLRight:
         focusNextChild();
         break;
     default:
@@ -241,8 +242,10 @@ void OverlayDialog::InputThread() {
     while (input_thread_running) {
         input_interpreter->PollInput();
 
-        HandleButtonPressedOnce<HIDButton::A, HIDButton::B, HIDButton::DLeft, HIDButton::DRight,
-                                HIDButton::LStickLeft, HIDButton::LStickRight>();
+        HandleButtonPressedOnce<Core::HID::NpadButton::A, Core::HID::NpadButton::B,
+                                Core::HID::NpadButton::Left, Core::HID::NpadButton::Right,
+                                Core::HID::NpadButton::StickLLeft,
+                                Core::HID::NpadButton::StickLRight>();
 
         std::this_thread::sleep_for(std::chrono::milliseconds(50));
     }
diff --git a/src/yuzu/util/overlay_dialog.h b/src/yuzu/util/overlay_dialog.h
index e8c388bd01..d8a140ff3f 100644
--- a/src/yuzu/util/overlay_dialog.h
+++ b/src/yuzu/util/overlay_dialog.h
@@ -13,14 +13,16 @@
 
 #include "common/common_types.h"
 
-enum class HIDButton : u8;
-
 class InputInterpreter;
 
 namespace Core {
 class System;
 }
 
+namespace Core::HID {
+enum class NpadButton : u64;
+}
+
 namespace Ui {
 class OverlayDialog;
 }
@@ -79,7 +81,7 @@ private:
      *
      * @tparam HIDButton The list of buttons that can be converted into keyboard input.
      */
-    template <HIDButton... T>
+    template <Core::HID::NpadButton... T>
     void HandleButtonPressedOnce();
 
     /**
@@ -87,7 +89,7 @@ private:
      *
      * @param button The button press to process.
      */
-    void TranslateButtonPress(HIDButton button);
+    void TranslateButtonPress(Core::HID::NpadButton button);
 
     void StartInputThread();
     void StopInputThread();

From e14ae06391ac724e4be4557df0568846687a3662 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 20 Sep 2021 20:53:04 -0500
Subject: [PATCH 35/88] core: Update input interpreter

---
 src/core/hid/input_interpreter.cpp | 17 +++++-----
 src/core/hid/input_interpreter.h   | 52 ++++++------------------------
 src/yuzu/applets/qt_controller.cpp |  2 --
 src/yuzu_cmd/config.cpp            |  1 -
 4 files changed, 18 insertions(+), 54 deletions(-)

diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp
index c33d8a11ad..7e7c1816fd 100644
--- a/src/core/hid/input_interpreter.cpp
+++ b/src/core/hid/input_interpreter.cpp
@@ -3,6 +3,7 @@
 // Refer to the license.txt file included.
 
 #include "core/core.h"
+#include "core/hid/hid_types.h"
 #include "core/hid/input_interpreter.h"
 #include "core/hle/service/hid/controllers/npad.h"
 #include "core/hle/service/hid/hid.h"
@@ -38,25 +39,23 @@ void InputInterpreter::ResetButtonStates() {
     }
 }
 
-bool InputInterpreter::IsButtonPressed(HIDButton button) const {
-    return (button_states[current_index] & (1U << static_cast<u8>(button))) != 0;
+bool InputInterpreter::IsButtonPressed(Core::HID::NpadButton button) const {
+    return (button_states[current_index] & static_cast<u32>(button)) != 0;
 }
 
-bool InputInterpreter::IsButtonPressedOnce(HIDButton button) const {
-    const bool current_press =
-        (button_states[current_index] & (1U << static_cast<u8>(button))) != 0;
-    const bool previous_press =
-        (button_states[previous_index] & (1U << static_cast<u8>(button))) != 0;
+bool InputInterpreter::IsButtonPressedOnce(Core::HID::NpadButton button) const {
+    const bool current_press = (button_states[current_index] & static_cast<u32>(button)) != 0;
+    const bool previous_press = (button_states[previous_index] & static_cast<u32>(button)) != 0;
 
     return current_press && !previous_press;
 }
 
-bool InputInterpreter::IsButtonHeld(HIDButton button) const {
+bool InputInterpreter::IsButtonHeld(Core::HID::NpadButton button) const {
     u32 held_buttons{button_states[0]};
 
     for (std::size_t i = 1; i < button_states.size(); ++i) {
         held_buttons &= button_states[i];
     }
 
-    return (held_buttons & (1U << static_cast<u8>(button))) != 0;
+    return (held_buttons & static_cast<u32>(button)) != 0;
 }
diff --git a/src/core/hid/input_interpreter.h b/src/core/hid/input_interpreter.h
index 9495e3daf0..1791cf9b72 100644
--- a/src/core/hid/input_interpreter.h
+++ b/src/core/hid/input_interpreter.h
@@ -12,46 +12,14 @@ namespace Core {
 class System;
 }
 
+namespace Core::HID {
+enum class NpadButton : u64;
+}
+
 namespace Service::HID {
 class Controller_NPad;
 }
 
-enum class HIDButton : u8 {
-    A,
-    B,
-    X,
-    Y,
-    LStick,
-    RStick,
-    L,
-    R,
-    ZL,
-    ZR,
-    Plus,
-    Minus,
-
-    DLeft,
-    DUp,
-    DRight,
-    DDown,
-
-    LStickLeft,
-    LStickUp,
-    LStickRight,
-    LStickDown,
-
-    RStickLeft,
-    RStickUp,
-    RStickRight,
-    RStickDown,
-
-    LeftSL,
-    LeftSR,
-
-    RightSL,
-    RightSR,
-};
-
 /**
  * The InputInterpreter class interfaces with HID to retrieve button press states.
  * Input is intended to be polled every 50ms so that a button is considered to be
@@ -76,7 +44,7 @@ public:
      *
      * @returns True when the button is pressed.
      */
-    [[nodiscard]] bool IsButtonPressed(HIDButton button) const;
+    [[nodiscard]] bool IsButtonPressed(Core::HID::NpadButton button) const;
 
     /**
      * Checks whether any of the buttons in the parameter list is pressed.
@@ -85,7 +53,7 @@ public:
      *
      * @returns True when at least one of the buttons is pressed.
      */
-    template <HIDButton... T>
+    template <Core::HID::NpadButton... T>
     [[nodiscard]] bool IsAnyButtonPressed() {
         return (IsButtonPressed(T) || ...);
     }
@@ -98,7 +66,7 @@ public:
      *
      * @returns True when the button is pressed once.
      */
-    [[nodiscard]] bool IsButtonPressedOnce(HIDButton button) const;
+    [[nodiscard]] bool IsButtonPressedOnce(Core::HID::NpadButton button) const;
 
     /**
      * Checks whether any of the buttons in the parameter list is pressed once.
@@ -107,7 +75,7 @@ public:
      *
      * @returns True when at least one of the buttons is pressed once.
      */
-    template <HIDButton... T>
+    template <Core::HID::NpadButton... T>
     [[nodiscard]] bool IsAnyButtonPressedOnce() const {
         return (IsButtonPressedOnce(T) || ...);
     }
@@ -119,7 +87,7 @@ public:
      *
      * @returns True when the button is held down.
      */
-    [[nodiscard]] bool IsButtonHeld(HIDButton button) const;
+    [[nodiscard]] bool IsButtonHeld(Core::HID::NpadButton button) const;
 
     /**
      * Checks whether any of the buttons in the parameter list is held down.
@@ -128,7 +96,7 @@ public:
      *
      * @returns True when at least one of the buttons is held down.
      */
-    template <HIDButton... T>
+    template <Core::HID::NpadButton... T>
     [[nodiscard]] bool IsAnyButtonHeld() const {
         return (IsButtonHeld(T) || ...);
     }
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 4dd577a181..2cd5ed7185 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -9,8 +9,6 @@
 #include "common/param_package.h"
 #include "common/string_util.h"
 #include "core/core.h"
-#include "core/hid/emulated_controller.h
-#include "core/hid/hid_types.h
 #include "core/hle/lock.h"
 #include "core/hle/service/hid/controllers/npad.h"
 #include "core/hle/service/hid/hid.h"
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 33241ea986..103a12b120 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -24,7 +24,6 @@
 #include "common/settings.h"
 #include "core/hle/service/acc/profile_manager.h"
 #include "input_common/main.h"
-#include "input_common/udp/client.h"
 #include "yuzu_cmd/config.h"
 #include "yuzu_cmd/default_ini.h"
 

From 06a5ef5874144a70e30e577a83ba68d1dad79e78 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 11 Oct 2021 00:43:11 -0500
Subject: [PATCH 36/88] core/hid: Add output devices

---
 src/common/input.h                            |  39 ++++++
 src/core/hid/emulated_controller.cpp          | 119 ++++++++++++++----
 src/core/hid/emulated_controller.h            |  13 +-
 src/core/hid/hid_types.h                      |  18 +++
 src/core/hle/service/hid/controllers/npad.cpp |  27 +---
 src/core/hle/service/hid/controllers/npad.h   |  18 +--
 src/input_common/drivers/gc_adapter.cpp       |   8 +-
 src/input_common/drivers/gc_adapter.h         |   2 +-
 src/input_common/drivers/sdl_driver.cpp       |   8 +-
 src/input_common/drivers/sdl_driver.h         |   2 +-
 .../helpers/stick_from_buttons.cpp            |   3 +-
 src/input_common/helpers/stick_from_buttons.h |   3 +-
 .../helpers/touch_from_buttons.cpp            |   4 +-
 src/input_common/input_engine.h               |  18 ++-
 src/input_common/input_poller.cpp             |  40 +++++-
 src/input_common/input_poller.h               |  28 ++++-
 src/input_common/main.cpp                     |  32 +++--
 .../configuration/configure_input_player.cpp  |   7 ++
 .../configure_input_player_widget.cpp         |  59 ++++-----
 .../configure_input_player_widget.h           |  10 +-
 20 files changed, 313 insertions(+), 145 deletions(-)

diff --git a/src/common/input.h b/src/common/input.h
index 6eefc55f9c..3a28b77a7b 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -38,6 +38,27 @@ enum class BatteryLevel {
     Charging,
 };
 
+enum class PollingMode {
+    Active,
+    Pasive,
+    Camera,
+    NCF,
+    IR,
+};
+
+enum class VibrationError {
+    None,
+    NotSupported,
+    Disabled,
+    Unknown,
+};
+
+enum class PollingError {
+    None,
+    NotSupported,
+    Unknown,
+};
+
 struct AnalogProperties {
     float deadzone{};
     float range{1.0f};
@@ -149,6 +170,24 @@ private:
     InputCallback callback;
 };
 
+/// An abstract class template for an output device (rumble, LED pattern, polling mode).
+class OutputDevice {
+public:
+    virtual ~OutputDevice() = default;
+
+    virtual void SetLED([[maybe_unused]] LedStatus led_status) {
+        return;
+    }
+
+    virtual VibrationError SetVibration([[maybe_unused]] VibrationStatus vibration_status) {
+        return VibrationError::NotSupported;
+    }
+
+    virtual PollingError SetPollingMode([[maybe_unused]] PollingMode polling_mode) {
+        return PollingError::NotSupported;
+    }
+};
+
 /// An abstract class template for a factory that can create input devices.
 template <typename InputDeviceType>
 class Factory {
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 4eb5d99bc3..b9d16657a5 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -66,12 +66,32 @@ void EmulatedController::ReloadFromSettings() {
     for (std::size_t index = 0; index < player.motions.size(); ++index) {
         motion_params[index] = Common::ParamPackage(player.motions[index]);
     }
+
+    controller.colors_state.left = {
+        .body = player.body_color_left,
+        .button = player.button_color_left,
+    };
+
+    controller.colors_state.right = {
+        .body = player.body_color_right,
+        .button = player.button_color_right,
+    };
+
+    controller.colors_state.fullkey = controller.colors_state.left;
+
+    SetNpadType(MapSettingsTypeToNPad(player.controller_type));
+
+    if (player.connected) {
+        Connect();
+    } else {
+        Disconnect();
+    }
+
     ReloadInput();
 }
 
 void EmulatedController::ReloadInput() {
     const auto player_index = NpadIdTypeToIndex(npad_id_type);
-    const auto& player = Settings::values.players.GetValue()[player_index];
     const auto left_side = button_params[Settings::NativeButton::ZL];
     const auto right_side = button_params[Settings::NativeButton::ZR];
 
@@ -90,21 +110,13 @@ void EmulatedController::ReloadInput() {
     trigger_devices[1] =
         Input::CreateDevice<Input::InputDevice>(button_params[Settings::NativeButton::ZR]);
 
-    controller.colors_state.left = {
-        .body = player.body_color_left,
-        .button = player.button_color_left,
-    };
-
-    controller.colors_state.right = {
-        .body = player.body_color_right,
-        .button = player.button_color_right,
-    };
-
-    controller.colors_state.fullkey = controller.colors_state.left;
-
     battery_devices[0] = Input::CreateDevice<Input::InputDevice>(left_side);
     battery_devices[1] = Input::CreateDevice<Input::InputDevice>(right_side);
 
+    button_params[Settings::NativeButton::ZL].Set("output",true);
+    output_devices[0] =
+        Input::CreateDevice<Input::OutputDevice>(button_params[Settings::NativeButton::ZL]);
+
     for (std::size_t index = 0; index < button_devices.size(); ++index) {
         if (!button_devices[index]) {
             continue;
@@ -149,14 +161,6 @@ void EmulatedController::ReloadInput() {
             [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }};
         motion_devices[index]->SetCallback(motion_callback);
     }
-
-    SetNpadType(MapSettingsTypeToNPad(player.controller_type));
-
-    if (player.connected) {
-        Connect();
-    } else {
-        Disconnect();
-    }
 }
 
 void EmulatedController::UnloadInput() {
@@ -197,7 +201,8 @@ void EmulatedController::SaveCurrentConfig() {
 
     const auto player_index = NpadIdTypeToIndex(npad_id_type);
     auto& player = Settings::values.players.GetValue()[player_index];
-
+    player.connected = is_connected;
+    player.controller_type = MapNPadToSettingsType(npad_type);
     for (std::size_t index = 0; index < player.buttons.size(); ++index) {
         player.buttons[index] = button_params[index].Serialize();
     }
@@ -601,13 +606,50 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t
     TriggerOnChange(ControllerTriggerType::Battery);
 }
 
-bool EmulatedController::SetVibration([[maybe_unused]] std::size_t device_index,
-                                      [[maybe_unused]] VibrationValue vibration) {
-    return false;
+bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
+    if (!output_devices[device_index]) {
+        return false;
+    }
+
+    const Input::VibrationStatus status = {
+        .low_amplitude = vibration.high_amplitude,
+        .low_frequency = vibration.high_amplitude,
+        .high_amplitude = vibration.high_amplitude,
+        .high_frequency = vibration.high_amplitude,
+    };
+    return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None;
 }
 
-int EmulatedController::TestVibration(std::size_t device_index) {
-    return 1;
+bool EmulatedController::TestVibration(std::size_t device_index) {
+    if (!output_devices[device_index]) {
+        return false;
+    }
+
+    // Send a slight vibration to test for rumble support
+    constexpr Input::VibrationStatus status = {
+        .low_amplitude = 0.001f,
+        .low_frequency = 160.0f,
+        .high_amplitude = 0.001f,
+        .high_frequency = 320.0f,
+    };
+    return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None;
+}
+
+void EmulatedController::SetLedPattern() {
+    for (auto& device : output_devices) {
+        if (!device) {
+            continue;
+        }
+
+        const LedPattern pattern = GetLedPattern();
+        const Input::LedStatus status = {
+            .led_1 = pattern.position1 != 0,
+            .led_2 = pattern.position2 != 0,
+            .led_3 = pattern.position3 != 0,
+            .led_4 = pattern.position4 != 0,
+        };
+        device->SetLED(status);
+    }
 }
 
 void EmulatedController::Connect() {
@@ -655,6 +697,29 @@ void EmulatedController::SetNpadType(NpadType npad_type_) {
     TriggerOnChange(ControllerTriggerType::Type);
 }
 
+LedPattern EmulatedController::GetLedPattern() const {
+    switch (npad_id_type) {
+    case NpadIdType::Player1:
+        return LedPattern{1, 0, 0, 0};
+    case NpadIdType::Player2:
+        return LedPattern{1, 1, 0, 0};
+    case NpadIdType::Player3:
+        return LedPattern{1, 1, 1, 0};
+    case NpadIdType::Player4:
+        return LedPattern{1, 1, 1, 1};
+    case NpadIdType::Player5:
+        return LedPattern{1, 0, 0, 1};
+    case NpadIdType::Player6:
+        return LedPattern{1, 0, 1, 0};
+    case NpadIdType::Player7:
+        return LedPattern{1, 0, 1, 1};
+    case NpadIdType::Player8:
+        return LedPattern{0, 1, 1, 0};
+    default:
+        return LedPattern{0, 0, 0, 0};
+    }
+}
+
 ButtonValues EmulatedController::GetButtonsValues() const {
     return controller.button_values;
 }
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 94db9b00be..322d2cab04 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -33,12 +33,14 @@ using ControllerMotionDevices =
 using TriggerDevices =
     std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
 using BatteryDevices = std::array<std::unique_ptr<Input::InputDevice>, 2>;
+using OutputDevices = std::array<std::unique_ptr<Input::OutputDevice>, 2>;
 
 using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
 using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
 using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>;
 using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>;
 using BatteryParams = std::array<Common::ParamPackage, 2>;
+using OutputParams = std::array<Common::ParamPackage, 2>;
 
 using ButtonValues = std::array<Input::ButtonStatus, Settings::NativeButton::NumButtons>;
 using SticksValues = std::array<Input::StickStatus, Settings::NativeAnalog::NumAnalogs>;
@@ -94,6 +96,7 @@ struct ControllerStatus {
     ControllerColors colors_state{};
     BatteryLevelState battery_state{};
 };
+
 enum class ControllerTriggerType {
     Button,
     Stick,
@@ -137,6 +140,9 @@ public:
     /// Gets the NpadType for this controller.
     NpadType GetNpadType() const;
 
+    /// Gets the NpadType for this controller.
+    LedPattern GetLedPattern() const;
+
     void Connect();
     void Disconnect();
 
@@ -179,7 +185,9 @@ public:
     BatteryLevelState GetBattery() const;
 
     bool SetVibration(std::size_t device_index, VibrationValue vibration);
-    int TestVibration(std::size_t device_index);
+    bool TestVibration(std::size_t device_index);
+
+    void SetLedPattern();
 
     int SetCallback(ControllerUpdateCallback update_callback);
     void DeleteCallback(int key);
@@ -215,13 +223,14 @@ private:
     ControllerMotionParams motion_params;
     TriggerParams trigger_params;
     BatteryParams battery_params;
+    OutputParams output_params;
 
     ButtonDevices button_devices;
     StickDevices stick_devices;
     ControllerMotionDevices motion_devices;
     TriggerDevices trigger_devices;
     BatteryDevices battery_devices;
-    // VibrationDevices vibration_devices;
+    OutputDevices output_devices;
 
     mutable std::mutex mutex;
     std::unordered_map<int, ControllerUpdateCallback> callback_list;
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index d3f7930c93..f12a14cb8e 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -112,6 +112,8 @@ struct NpadStyleTag {
         BitField<7, 1, u32> lark;
         BitField<8, 1, u32> handheld_lark;
         BitField<9, 1, u32> lucia;
+        BitField<10, 1, u32> lagoon;
+        BitField<11, 1, u32> lager;
         BitField<29, 1, u32> system_ext;
         BitField<30, 1, u32> system;
     };
@@ -175,6 +177,22 @@ struct NpadPowerInfo {
 };
 static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
 
+struct LedPattern {
+    explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
+        position1.Assign(light1);
+        position2.Assign(light2);
+        position3.Assign(light3);
+        position4.Assign(light4);
+    }
+    union {
+        u64 raw{};
+        BitField<0, 1, u64> position1;
+        BitField<1, 1, u64> position2;
+        BitField<2, 1, u64> position3;
+        BitField<3, 1, u64> position4;
+    };
+};
+
 // This is nn::hid::NpadButton
 enum class NpadButton : u64 {
     None = 0,
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 03cbd42f4d..a2e9ddf4d5 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -796,7 +796,7 @@ void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index,
     }
 
     controller.vibration[device_index].device_mounted =
-        controller.device->TestVibration(device_index) == 1;
+        controller.device->TestVibration(device_index);
 }
 
 void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
@@ -954,31 +954,12 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
     return true;
 }
 
-Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
+Core::HID::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
     if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
         // These are controllers without led patterns
-        return LedPattern{0, 0, 0, 0};
-    }
-    switch (npad_id) {
-    case 0:
-        return LedPattern{1, 0, 0, 0};
-    case 1:
-        return LedPattern{1, 1, 0, 0};
-    case 2:
-        return LedPattern{1, 1, 1, 0};
-    case 3:
-        return LedPattern{1, 1, 1, 1};
-    case 4:
-        return LedPattern{1, 0, 0, 1};
-    case 5:
-        return LedPattern{1, 0, 1, 0};
-    case 6:
-        return LedPattern{1, 0, 1, 1};
-    case 7:
-        return LedPattern{0, 1, 1, 0};
-    default:
-        return LedPattern{0, 0, 0, 0};
+        return Core::HID::LedPattern{0, 0, 0, 0};
     }
+    return controller_data[npad_id].device->GetLedPattern();
 }
 
 bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 483cae5b68..b0e2f84308 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -115,22 +115,6 @@ public:
         .freq_high = 320.0f,
     };
 
-    struct LedPattern {
-        explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
-            position1.Assign(light1);
-            position2.Assign(light2);
-            position3.Assign(light3);
-            position4.Assign(light4);
-        }
-        union {
-            u64 raw{};
-            BitField<0, 1, u64> position1;
-            BitField<1, 1, u64> position2;
-            BitField<2, 1, u64> position3;
-            BitField<3, 1, u64> position4;
-        };
-    };
-
     void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
     Core::HID::NpadStyleTag GetSupportedStyleSet() const;
 
@@ -186,7 +170,7 @@ public:
     void SetSixAxisFusionParameters(f32 parameter1, f32 parameter2);
     std::pair<f32, f32> GetSixAxisFusionParameters();
     void ResetSixAxisFusionParameters();
-    LedPattern GetLedPattern(u32 npad_id);
+    Core::HID::LedPattern GetLedPattern(u32 npad_id);
     bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
     void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
     void SetAnalogStickUseCenterClamp(bool use_center_clamp);
diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp
index 6721ba4f7b..2aa5a16a6e 100644
--- a/src/input_common/drivers/gc_adapter.cpp
+++ b/src/input_common/drivers/gc_adapter.cpp
@@ -322,13 +322,17 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) {
     return true;
 }
 
-bool GCAdapter::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) {
+Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) {
     const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f;
     const auto processed_amplitude =
         static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8);
 
     pads[identifier.port].rumble_amplitude = processed_amplitude;
-    return rumble_enabled;
+
+    if (!rumble_enabled) {
+        return Input::VibrationError::Disabled;
+    }
+    return Input::VibrationError::None;
 }
 
 void GCAdapter::UpdateVibrations() {
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h
index c0bf1ed7ae..dd23dd9f3b 100644
--- a/src/input_common/drivers/gc_adapter.h
+++ b/src/input_common/drivers/gc_adapter.h
@@ -24,7 +24,7 @@ public:
     explicit GCAdapter(const std::string input_engine_);
     ~GCAdapter();
 
-    bool SetRumble(const PadIdentifier& identifier,
+    Input::VibrationError SetRumble(const PadIdentifier& identifier,
                    const Input::VibrationStatus vibration) override;
 
     /// Used for automapping features
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index efb4a21068..f7f03c5f23 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -506,7 +506,8 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
     }
     return devices;
 }
-bool SDLDriver::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) {
+Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier,
+                                           const Input::VibrationStatus vibration) {
     const auto joystick =
         GetSDLJoystickByGUID(identifier.guid.Format(), static_cast<int>(identifier.port));
     const auto process_amplitude = [](f32 amplitude) {
@@ -519,7 +520,10 @@ bool SDLDriver::SetRumble(const PadIdentifier& identifier, const Input::Vibratio
         .high_frequency = vibration.high_frequency,
     };
 
-    return joystick->RumblePlay(new_vibration);
+    if (!joystick->RumblePlay(new_vibration)) {
+        return Input::VibrationError::Unknown;
+    }
+    return Input::VibrationError::None;
 }
 Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,
                                                                  s32 axis, float value) const {
diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h
index d8d3501842..f66b33c775 100644
--- a/src/input_common/drivers/sdl_driver.h
+++ b/src/input_common/drivers/sdl_driver.h
@@ -58,7 +58,7 @@ public:
     std::string GetHatButtonName(u8 direction_value) const override;
     u8 GetHatButtonId(const std::string direction_name) const override;
 
-    bool SetRumble(const PadIdentifier& identifier,
+    Input::VibrationError SetRumble(const PadIdentifier& identifier,
                    const Input::VibrationStatus vibration) override;
 
 private:
diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp
index 38f1507462..89ba4aeb12 100644
--- a/src/input_common/helpers/stick_from_buttons.cpp
+++ b/src/input_common/helpers/stick_from_buttons.cpp
@@ -251,7 +251,8 @@ private:
     std::chrono::time_point<std::chrono::steady_clock> last_update;
 };
 
-std::unique_ptr<Input::InputDevice> StickFromButton::Create(const Common::ParamPackage& params) {
+std::unique_ptr<Input::InputDevice> StickFromButton::Create(
+    const Common::ParamPackage& params) {
     const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
     auto up = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("up", null_engine));
     auto down = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("down", null_engine));
diff --git a/src/input_common/helpers/stick_from_buttons.h b/src/input_common/helpers/stick_from_buttons.h
index 1d6e24c98e..87165e022a 100644
--- a/src/input_common/helpers/stick_from_buttons.h
+++ b/src/input_common/helpers/stick_from_buttons.h
@@ -25,7 +25,8 @@ public:
      *     - "modifier": a serialized ParamPackage for creating a button device as the modifier
      *     - "modifier_scale": a float for the multiplier the modifier gives to the position
      */
-    std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
+    std::unique_ptr<Input::InputDevice> Create(
+        const Common::ParamPackage& params) override;
 };
 
 } // namespace InputCommon
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp
index 2abfaf841d..6c9046ffb4 100644
--- a/src/input_common/helpers/touch_from_buttons.cpp
+++ b/src/input_common/helpers/touch_from_buttons.cpp
@@ -57,7 +57,9 @@ private:
     const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
 };
 
-std::unique_ptr<Input::InputDevice> TouchFromButton::Create(const Common::ParamPackage& params) {
+
+std::unique_ptr<Input::InputDevice> TouchFromButton::Create(
+    const Common::ParamPackage& params) {
     const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
     auto button =
         Input::CreateDeviceFromString<Input::InputDevice>(params.Get("button", null_engine));
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h
index 86a8e00d8e..8a953c3820 100644
--- a/src/input_common/input_engine.h
+++ b/src/input_common/input_engine.h
@@ -114,18 +114,24 @@ public:
     // Disable configuring mode for mapping
     void EndConfiguration();
 
-    // Sets rumble to a controller
-    virtual bool SetRumble([[maybe_unused]] const PadIdentifier& identifier,
-                           [[maybe_unused]] const Input::VibrationStatus vibration) {
-        return false;
-    }
-
     // Sets a led pattern for a controller
     virtual void SetLeds([[maybe_unused]] const PadIdentifier& identifier,
                          [[maybe_unused]] const Input::LedStatus led_status) {
         return;
     }
 
+    // Sets rumble to a controller
+    virtual Input::VibrationError SetRumble([[maybe_unused]] const PadIdentifier& identifier,
+                           [[maybe_unused]] const Input::VibrationStatus vibration) {
+        return Input::VibrationError::NotSupported;
+    }
+
+    // Sets polling mode to a controller
+    virtual Input::PollingError SetPollingMode([[maybe_unused]] const PadIdentifier& identifier,
+                           [[maybe_unused]] const Input::PollingMode vibration) {
+        return Input::PollingError::NotSupported;
+    }
+
     // Returns the engine name
     [[nodiscard]] const std::string& GetEngineName() const;
 
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 46a7dd2761..781012886a 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -592,6 +592,28 @@ private:
     InputEngine* input_engine;
 };
 
+class OutputFromIdentifier final : public Input::OutputDevice {
+public:
+    explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_)
+        : identifier(identifier_), input_engine(input_engine_) {}
+
+    virtual void SetLED( Input::LedStatus led_status) {
+        input_engine->SetLeds(identifier, led_status);
+    }
+
+    virtual Input::VibrationError SetVibration(Input::VibrationStatus vibration_status) {
+        return input_engine->SetRumble(identifier, vibration_status);
+    }
+
+    virtual Input::PollingError SetPollingMode(Input::PollingMode polling_mode) {
+        return input_engine->SetPollingMode(identifier, polling_mode);
+    }
+
+private:
+    const PadIdentifier identifier;
+    InputEngine* input_engine;
+};
+
 std::unique_ptr<Input::InputDevice> InputFactory::CreateButtonDevice(
     const Common::ParamPackage& params) {
     const PadIdentifier identifier = {
@@ -825,7 +847,8 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateMotionDevice(Common::Par
 InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_)
     : input_engine(std::move(input_engine_)) {}
 
-std::unique_ptr<Input::InputDevice> InputFactory::Create(const Common::ParamPackage& params) {
+std::unique_ptr<Input::InputDevice> InputFactory::Create(
+    const Common::ParamPackage& params) {
     if (params.Has("button") && params.Has("axis")) {
         return CreateTriggerDevice(params);
     }
@@ -857,4 +880,19 @@ std::unique_ptr<Input::InputDevice> InputFactory::Create(const Common::ParamPack
     return std::make_unique<DummyInput>();
 }
 
+OutputFactory::OutputFactory(std::shared_ptr<InputEngine> input_engine_)
+    : input_engine(std::move(input_engine_)) {}
+
+std::unique_ptr<Input::OutputDevice> OutputFactory::Create(
+    const Common::ParamPackage& params) {
+    const PadIdentifier identifier = {
+        .guid = Common::UUID{params.Get("guid", "")},
+        .port = static_cast<std::size_t>(params.Get("port", 0)),
+        .pad = static_cast<std::size_t>(params.Get("pad", 0)),
+    };
+
+    input_engine->PreSetController(identifier);
+    return std::make_unique<OutputFromIdentifier>(identifier, input_engine.get());
+}
+
 } // namespace InputCommon
diff --git a/src/input_common/input_poller.h b/src/input_common/input_poller.h
index 3c1e5b541f..16cade5faf 100644
--- a/src/input_common/input_poller.h
+++ b/src/input_common/input_poller.h
@@ -16,12 +16,32 @@ class InputEngine;
 /**
  * An Input factory. It receives input events and forward them to all input devices it created.
  */
+
+class OutputFactory final : public Input::Factory<Input::OutputDevice> {
+public:
+    explicit OutputFactory(std::shared_ptr<InputEngine> input_engine_);
+
+    /**
+     * Creates an output device from the parameters given.
+     * @param params contains parameters for creating the device:
+     * @param    - "guid": text string for identifing controllers
+     * @param    - "port": port of the connected device
+     * @param    - "pad": slot of the connected controller
+     * @return an unique ouput device with the parameters specified
+     */
+    std::unique_ptr<Input::OutputDevice> Create(
+        const Common::ParamPackage& params) override;
+
+private:
+    std::shared_ptr<InputEngine> input_engine;
+};
+
 class InputFactory final : public Input::Factory<Input::InputDevice> {
 public:
     explicit InputFactory(std::shared_ptr<InputEngine> input_engine_);
 
     /**
-     * Creates a input device from the parameters given. Identifies the type of input to be returned
+     * Creates an input device from the parameters given. Identifies the type of input to be returned
      * if it contains the following parameters:
      * - button: Contains "button" or "code"
      * - hat_button: Contains "hat"
@@ -32,6 +52,7 @@ public:
      * - motion: Contains "motion"
      * - touch: Contains "button", "axis_x" and "axis_y"
      * - battery: Contains "battery"
+     * - output: Contains "output"
      * @param params contains parameters for creating the device:
      * @param    - "code": the code of the keyboard key to bind with the input
      * @param    - "button": same as "code" but for controller buttons
@@ -41,10 +62,11 @@ public:
      * @param    - "axis_x": same as axis but specifing horizontal direction
      * @param    - "axis_y": same as axis but specifing vertical direction
      * @param    - "axis_z": same as axis but specifing forward direction
-     * @param   - "battery": Only used as a placeholder to set the input type
+     * @param    - "battery": Only used as a placeholder to set the input type
      * @return an unique input device with the parameters specified
      */
-    std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
+    std::unique_ptr<Input::InputDevice> Create(
+        const Common::ParamPackage& params) override;
 
 private:
     /**
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 46ca6b76c8..b7fe9cb373 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -46,8 +46,10 @@ struct InputSubsystem::Impl {
 
         gcadapter = std::make_shared<GCAdapter>("gcpad");
         gcadapter->SetMappingCallback(mapping_callback);
-        gcadapter_factory = std::make_shared<InputFactory>(gcadapter);
-        Input::RegisterFactory<Input::InputDevice>(gcadapter->GetEngineName(), gcadapter_factory);
+        gcadapter_input_factory = std::make_shared<InputFactory>(gcadapter);
+        gcadapter_output_factory = std::make_shared<OutputFactory>(gcadapter);
+        Input::RegisterFactory<Input::InputDevice>(gcadapter->GetEngineName(), gcadapter_input_factory);
+        Input::RegisterFactory<Input::OutputDevice>(gcadapter->GetEngineName(), gcadapter_output_factory);
 
         udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
         udp_client->SetMappingCallback(mapping_callback);
@@ -62,8 +64,10 @@ struct InputSubsystem::Impl {
 #ifdef HAVE_SDL2
         sdl = std::make_shared<SDLDriver>("sdl");
         sdl->SetMappingCallback(mapping_callback);
-        sdl_factory = std::make_shared<InputFactory>(sdl);
-        Input::RegisterFactory<Input::InputDevice>(sdl->GetEngineName(), sdl_factory);
+        sdl_input_factory = std::make_shared<InputFactory>(sdl);
+        sdl_output_factory = std::make_shared<OutputFactory>(sdl);
+        Input::RegisterFactory<Input::InputDevice>(sdl->GetEngineName(), sdl_input_factory);
+        Input::RegisterFactory<Input::OutputDevice>(sdl->GetEngineName(), sdl_output_factory);
 #endif
 
         Input::RegisterFactory<Input::InputDevice>("touch_from_button",
@@ -247,21 +251,27 @@ struct InputSubsystem::Impl {
     }
 
     std::shared_ptr<MappingFactory> mapping_factory;
+
     std::shared_ptr<Keyboard> keyboard;
-    std::shared_ptr<InputFactory> keyboard_factory;
     std::shared_ptr<Mouse> mouse;
-    std::shared_ptr<InputFactory> mouse_factory;
     std::shared_ptr<GCAdapter> gcadapter;
-    std::shared_ptr<InputFactory> gcadapter_factory;
     std::shared_ptr<TouchScreen> touch_screen;
-    std::shared_ptr<InputFactory> touch_screen_factory;
-    std::shared_ptr<CemuhookUDP::UDPClient> udp_client;
-    std::shared_ptr<InputFactory> udp_client_factory;
     std::shared_ptr<TasInput::Tas> tas_input;
+    std::shared_ptr<CemuhookUDP::UDPClient> udp_client;
+
+    std::shared_ptr<InputFactory> keyboard_factory;
+    std::shared_ptr<InputFactory> mouse_factory;
+    std::shared_ptr<InputFactory> gcadapter_input_factory;
+    std::shared_ptr<InputFactory> touch_screen_factory;
+    std::shared_ptr<InputFactory> udp_client_factory;
     std::shared_ptr<InputFactory> tas_input_factory;
+
+    std::shared_ptr<OutputFactory> gcadapter_output_factory;
+
 #ifdef HAVE_SDL2
     std::shared_ptr<SDLDriver> sdl;
-    std::shared_ptr<InputFactory> sdl_factory;
+    std::shared_ptr<InputFactory> sdl_input_factory;
+    std::shared_ptr<OutputFactory> sdl_output_factory;
 #endif
 };
 
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index adc9706f14..ed9c3facf5 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -465,6 +465,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
         UpdateControllerEnabledButtons();
         UpdateControllerButtonNames();
         UpdateMotionButtons();
+        emulated_controller->SetNpadType(
+            GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()));
     });
 
     connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
@@ -540,6 +542,11 @@ void ConfigureInputPlayer::LoadConfiguration() {
 
 void ConfigureInputPlayer::ConnectPlayer(bool connected) {
     ui->groupConnectedController->setChecked(connected);
+    if (connected) {
+        emulated_controller->Connect();
+    } else {
+        emulated_controller->Disconnect();
+    }
 }
 
 void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 03d29f194e..2ba9d7290c 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -24,34 +24,6 @@ PlayerControlPreview::~PlayerControlPreview() {
     }
 };
 
-PlayerControlPreview::LedPattern PlayerControlPreview::GetColorPattern(std::size_t index,
-                                                                       bool player_on) {
-    if (!player_on) {
-        return {0, 0, 0, 0};
-    }
-
-    switch (index) {
-    case 0:
-        return {1, 0, 0, 0};
-    case 1:
-        return {1, 1, 0, 0};
-    case 2:
-        return {1, 1, 1, 0};
-    case 3:
-        return {1, 1, 1, 1};
-    case 4:
-        return {1, 0, 0, 1};
-    case 5:
-        return {1, 0, 1, 0};
-    case 6:
-        return {1, 0, 1, 1};
-    case 7:
-        return {0, 1, 1, 0};
-    default:
-        return {0, 0, 0, 0};
-    }
-}
-
 void PlayerControlPreview::SetController(Core::HID::EmulatedController* controller_) {
     if (is_controller_set) {
         controller->DeleteCallback(callback_key);
@@ -160,8 +132,13 @@ void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType typ
 
     switch (type) {
     case Core::HID::ControllerTriggerType::Connected:
+        is_connected = true;
+        led_pattern = controller->GetLedPattern();
+        needs_redraw = true;
+        break;
     case Core::HID::ControllerTriggerType::Disconnected:
-        is_connected = controller->IsConnected();
+        is_connected = false;
+        led_pattern.raw = 0;
         needs_redraw = true;
         break;
     case Core::HID::ControllerTriggerType::Type:
@@ -1853,10 +1830,14 @@ void PlayerControlPreview::DrawLeftBody(QPainter& p, const QPointF center) {
     const float led_size = 5.0f;
     const QPointF led_position = sideview_center + QPointF(0, -36);
     int led_count = 0;
-    for (const auto& color : led_color) {
-        p.setBrush(color);
-        DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
-    }
+    p.setBrush(led_pattern.position1 ? colors.led_on : colors.led_off);
+    DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
+    p.setBrush(led_pattern.position2 ? colors.led_on : colors.led_off);
+    DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
+    p.setBrush(led_pattern.position3 ? colors.led_on : colors.led_off);
+    DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
+    p.setBrush(led_pattern.position4 ? colors.led_on : colors.led_off);
+    DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
 }
 
 void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) {
@@ -1949,10 +1930,14 @@ void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) {
     const float led_size = 5.0f;
     const QPointF led_position = sideview_center + QPointF(0, -36);
     int led_count = 0;
-    for (const auto& color : led_color) {
-        p.setBrush(color);
-        DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
-    }
+    p.setBrush(led_pattern.position1 ? colors.led_on : colors.led_off);
+    DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
+    p.setBrush(led_pattern.position2 ? colors.led_on : colors.led_off);
+    DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
+    p.setBrush(led_pattern.position3 ? colors.led_on : colors.led_off);
+    DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
+    p.setBrush(led_pattern.position4 ? colors.led_on : colors.led_off);
+    DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
 }
 
 void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center,
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index b44a2e347d..16f9748f54 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -59,13 +59,6 @@ private:
         SR,
     };
 
-    struct LedPattern {
-        bool position1;
-        bool position2;
-        bool position3;
-        bool position4;
-    };
-
     struct ColorMapping {
         QColor outline{};
         QColor primary{};
@@ -88,7 +81,6 @@ private:
         QColor deadzone{};
     };
 
-    static LedPattern GetColorPattern(std::size_t index, bool player_on);
     void UpdateColors();
     void ResetInputs();
 
@@ -194,7 +186,7 @@ private:
     int callback_key;
     QColor button_color{};
     ColorMapping colors{};
-    std::array<QColor, 4> led_color{};
+    Core::HID::LedPattern led_pattern{0, 0, 0, 0};
     std::size_t player_index{};
     Core::HID::EmulatedController* controller;
     std::size_t button_mapping_index{Settings::NativeButton::NumButtons};

From e0da5c1bbcdf85676f968b63c8ae2587f0464193 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Fri, 15 Oct 2021 19:07:47 -0500
Subject: [PATCH 37/88] kraken: Fix errors from rebase and format files

---
 src/core/hid/emulated_controller.cpp          |  6 ++++-
 src/core/hle/service/hid/hid.cpp              |  1 -
 src/input_common/drivers/gc_adapter.cpp       |  3 ++-
 src/input_common/drivers/gc_adapter.h         |  2 +-
 src/input_common/drivers/sdl_driver.h         |  2 +-
 .../helpers/stick_from_buttons.cpp            |  3 +--
 src/input_common/helpers/stick_from_buttons.h |  3 +--
 .../helpers/touch_from_buttons.cpp            |  4 +--
 src/input_common/input_engine.h               | 10 +++++---
 src/input_common/input_poller.cpp             |  8 +++---
 src/input_common/input_poller.h               | 10 +++-----
 src/input_common/main.cpp                     |  6 +++--
 src/yuzu/applets/qt_controller.h              |  1 -
 src/yuzu/configuration/configure_dialog.cpp   |  2 +-
 src/yuzu/configuration/configure_input.cpp    |  9 ++++---
 .../configure_input_player_widget.cpp         | 25 +++++++++++--------
 .../configure_input_player_widget.h           | 16 +++++++++++-
 src/yuzu/debugger/controller.cpp              |  9 +++++--
 src/yuzu/debugger/controller.h                |  9 ++++++-
 src/yuzu/main.cpp                             |  7 +++---
 20 files changed, 83 insertions(+), 53 deletions(-)

diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index b9d16657a5..b04ab4cd84 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -91,6 +91,7 @@ void EmulatedController::ReloadFromSettings() {
 }
 
 void EmulatedController::ReloadInput() {
+    // If you load any device here add the equivalent to the UnloadInput() function
     const auto player_index = NpadIdTypeToIndex(npad_id_type);
     const auto left_side = button_params[Settings::NativeButton::ZL];
     const auto right_side = button_params[Settings::NativeButton::ZR];
@@ -113,7 +114,7 @@ void EmulatedController::ReloadInput() {
     battery_devices[0] = Input::CreateDevice<Input::InputDevice>(left_side);
     battery_devices[1] = Input::CreateDevice<Input::InputDevice>(right_side);
 
-    button_params[Settings::NativeButton::ZL].Set("output",true);
+    button_params[Settings::NativeButton::ZL].Set("output", true);
     output_devices[0] =
         Input::CreateDevice<Input::OutputDevice>(button_params[Settings::NativeButton::ZL]);
 
@@ -179,6 +180,9 @@ void EmulatedController::UnloadInput() {
     for (auto& battery : battery_devices) {
         battery.reset();
     }
+    for (auto& output : output_devices) {
+        output.reset();
+    }
 }
 
 void EmulatedController::EnableConfiguration() {
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 18f29bb78d..5391334f43 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -8,7 +8,6 @@
 #include "common/settings.h"
 #include "core/core.h"
 #include "core/core_timing.h"
-#include "core/frontend/input.h"
 #include "core/hardware_properties.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/k_readable_event.h"
diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp
index 2aa5a16a6e..4a56abb997 100644
--- a/src/input_common/drivers/gc_adapter.cpp
+++ b/src/input_common/drivers/gc_adapter.cpp
@@ -322,7 +322,8 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) {
     return true;
 }
 
-Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) {
+Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier,
+                                           const Input::VibrationStatus vibration) {
     const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f;
     const auto processed_amplitude =
         static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8);
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h
index dd23dd9f3b..dd0e4aa1d5 100644
--- a/src/input_common/drivers/gc_adapter.h
+++ b/src/input_common/drivers/gc_adapter.h
@@ -25,7 +25,7 @@ public:
     ~GCAdapter();
 
     Input::VibrationError SetRumble(const PadIdentifier& identifier,
-                   const Input::VibrationStatus vibration) override;
+                                    const Input::VibrationStatus vibration) override;
 
     /// Used for automapping features
     std::vector<Common::ParamPackage> GetInputDevices() const override;
diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h
index f66b33c775..1ff85f48de 100644
--- a/src/input_common/drivers/sdl_driver.h
+++ b/src/input_common/drivers/sdl_driver.h
@@ -59,7 +59,7 @@ public:
     u8 GetHatButtonId(const std::string direction_name) const override;
 
     Input::VibrationError SetRumble(const PadIdentifier& identifier,
-                   const Input::VibrationStatus vibration) override;
+                                    const Input::VibrationStatus vibration) override;
 
 private:
     void InitJoystick(int joystick_index);
diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp
index 89ba4aeb12..38f1507462 100644
--- a/src/input_common/helpers/stick_from_buttons.cpp
+++ b/src/input_common/helpers/stick_from_buttons.cpp
@@ -251,8 +251,7 @@ private:
     std::chrono::time_point<std::chrono::steady_clock> last_update;
 };
 
-std::unique_ptr<Input::InputDevice> StickFromButton::Create(
-    const Common::ParamPackage& params) {
+std::unique_ptr<Input::InputDevice> StickFromButton::Create(const Common::ParamPackage& params) {
     const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
     auto up = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("up", null_engine));
     auto down = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("down", null_engine));
diff --git a/src/input_common/helpers/stick_from_buttons.h b/src/input_common/helpers/stick_from_buttons.h
index 87165e022a..1d6e24c98e 100644
--- a/src/input_common/helpers/stick_from_buttons.h
+++ b/src/input_common/helpers/stick_from_buttons.h
@@ -25,8 +25,7 @@ public:
      *     - "modifier": a serialized ParamPackage for creating a button device as the modifier
      *     - "modifier_scale": a float for the multiplier the modifier gives to the position
      */
-    std::unique_ptr<Input::InputDevice> Create(
-        const Common::ParamPackage& params) override;
+    std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
 };
 
 } // namespace InputCommon
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp
index 6c9046ffb4..2abfaf841d 100644
--- a/src/input_common/helpers/touch_from_buttons.cpp
+++ b/src/input_common/helpers/touch_from_buttons.cpp
@@ -57,9 +57,7 @@ private:
     const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
 };
 
-
-std::unique_ptr<Input::InputDevice> TouchFromButton::Create(
-    const Common::ParamPackage& params) {
+std::unique_ptr<Input::InputDevice> TouchFromButton::Create(const Common::ParamPackage& params) {
     const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
     auto button =
         Input::CreateDeviceFromString<Input::InputDevice>(params.Get("button", null_engine));
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h
index 8a953c3820..31ce900d76 100644
--- a/src/input_common/input_engine.h
+++ b/src/input_common/input_engine.h
@@ -121,14 +121,16 @@ public:
     }
 
     // Sets rumble to a controller
-    virtual Input::VibrationError SetRumble([[maybe_unused]] const PadIdentifier& identifier,
-                           [[maybe_unused]] const Input::VibrationStatus vibration) {
+    virtual Input::VibrationError SetRumble(
+        [[maybe_unused]] const PadIdentifier& identifier,
+        [[maybe_unused]] const Input::VibrationStatus vibration) {
         return Input::VibrationError::NotSupported;
     }
 
     // Sets polling mode to a controller
-    virtual Input::PollingError SetPollingMode([[maybe_unused]] const PadIdentifier& identifier,
-                           [[maybe_unused]] const Input::PollingMode vibration) {
+    virtual Input::PollingError SetPollingMode(
+        [[maybe_unused]] const PadIdentifier& identifier,
+        [[maybe_unused]] const Input::PollingMode vibration) {
         return Input::PollingError::NotSupported;
     }
 
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 781012886a..62ade951c9 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -597,7 +597,7 @@ public:
     explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_)
         : identifier(identifier_), input_engine(input_engine_) {}
 
-    virtual void SetLED( Input::LedStatus led_status) {
+    virtual void SetLED(Input::LedStatus led_status) {
         input_engine->SetLeds(identifier, led_status);
     }
 
@@ -847,8 +847,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateMotionDevice(Common::Par
 InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_)
     : input_engine(std::move(input_engine_)) {}
 
-std::unique_ptr<Input::InputDevice> InputFactory::Create(
-    const Common::ParamPackage& params) {
+std::unique_ptr<Input::InputDevice> InputFactory::Create(const Common::ParamPackage& params) {
     if (params.Has("button") && params.Has("axis")) {
         return CreateTriggerDevice(params);
     }
@@ -883,8 +882,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::Create(
 OutputFactory::OutputFactory(std::shared_ptr<InputEngine> input_engine_)
     : input_engine(std::move(input_engine_)) {}
 
-std::unique_ptr<Input::OutputDevice> OutputFactory::Create(
-    const Common::ParamPackage& params) {
+std::unique_ptr<Input::OutputDevice> OutputFactory::Create(const Common::ParamPackage& params) {
     const PadIdentifier identifier = {
         .guid = Common::UUID{params.Get("guid", "")},
         .port = static_cast<std::size_t>(params.Get("port", 0)),
diff --git a/src/input_common/input_poller.h b/src/input_common/input_poller.h
index 16cade5faf..1357e104be 100644
--- a/src/input_common/input_poller.h
+++ b/src/input_common/input_poller.h
@@ -29,8 +29,7 @@ public:
      * @param    - "pad": slot of the connected controller
      * @return an unique ouput device with the parameters specified
      */
-    std::unique_ptr<Input::OutputDevice> Create(
-        const Common::ParamPackage& params) override;
+    std::unique_ptr<Input::OutputDevice> Create(const Common::ParamPackage& params) override;
 
 private:
     std::shared_ptr<InputEngine> input_engine;
@@ -41,8 +40,8 @@ public:
     explicit InputFactory(std::shared_ptr<InputEngine> input_engine_);
 
     /**
-     * Creates an input device from the parameters given. Identifies the type of input to be returned
-     * if it contains the following parameters:
+     * Creates an input device from the parameters given. Identifies the type of input to be
+     * returned if it contains the following parameters:
      * - button: Contains "button" or "code"
      * - hat_button: Contains "hat"
      * - analog: Contains "axis"
@@ -65,8 +64,7 @@ public:
      * @param    - "battery": Only used as a placeholder to set the input type
      * @return an unique input device with the parameters specified
      */
-    std::unique_ptr<Input::InputDevice> Create(
-        const Common::ParamPackage& params) override;
+    std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
 
 private:
     /**
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index b7fe9cb373..7807dd38ff 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -48,8 +48,10 @@ struct InputSubsystem::Impl {
         gcadapter->SetMappingCallback(mapping_callback);
         gcadapter_input_factory = std::make_shared<InputFactory>(gcadapter);
         gcadapter_output_factory = std::make_shared<OutputFactory>(gcadapter);
-        Input::RegisterFactory<Input::InputDevice>(gcadapter->GetEngineName(), gcadapter_input_factory);
-        Input::RegisterFactory<Input::OutputDevice>(gcadapter->GetEngineName(), gcadapter_output_factory);
+        Input::RegisterFactory<Input::InputDevice>(gcadapter->GetEngineName(),
+                                                   gcadapter_input_factory);
+        Input::RegisterFactory<Input::OutputDevice>(gcadapter->GetEngineName(),
+                                                    gcadapter_output_factory);
 
         udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
         udp_client->SetMappingCallback(mapping_callback);
diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h
index 98060e6f81..ca09fde04f 100644
--- a/src/yuzu/applets/qt_controller.h
+++ b/src/yuzu/applets/qt_controller.h
@@ -106,7 +106,6 @@ private:
     Core::Frontend::ControllerParameters parameters;
 
     InputCommon::InputSubsystem* input_subsystem;
-    Core::System& system;
 
     std::unique_ptr<InputProfiles> input_profiles;
 
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 642a5f9660..1eb9d70e53 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -74,7 +74,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry,
     hotkeys_tab->Populate(registry);
     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
 
-    input_tab->Initialize(input_subsystem);
+    input_tab->Initialize(input_subsystem, system_);
 
     general_tab->SetResetCallback([&] { this->close(); });
 
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 61513865f4..a8611f77f9 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -146,10 +146,11 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, Co
     advanced = new ConfigureInputAdvanced(this);
     ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced));
     ui->tabAdvanced->layout()->addWidget(advanced);
-    connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] {
-        CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem, profiles.get(),
-                                                      system);
-    });
+    connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog,
+            [this, input_subsystem, &system] {
+                CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem,
+                                                              profiles.get(), system);
+            });
     connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] {
         CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem);
     });
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 2ba9d7290c..446b72e553 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -19,15 +19,11 @@ PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) {
 }
 
 PlayerControlPreview::~PlayerControlPreview() {
-    if (is_controller_set) {
-        controller->DeleteCallback(callback_key);
-    }
+    UnloadController();
 };
 
 void PlayerControlPreview::SetController(Core::HID::EmulatedController* controller_) {
-    if (is_controller_set) {
-        controller->DeleteCallback(callback_key);
-    }
+    UnloadController();
     is_controller_set = true;
     controller = controller_;
     Core::HID::ControllerUpdateCallback engine_callback{
@@ -36,14 +32,21 @@ void PlayerControlPreview::SetController(Core::HID::EmulatedController* controll
     ControllerUpdate(Core::HID::ControllerTriggerType::All);
 }
 
-void PlayerControlPreview::BeginMappingButton(std::size_t index) {
-    button_mapping_index = index;
+void PlayerControlPreview::UnloadController() {
+    if (is_controller_set) {
+        controller->DeleteCallback(callback_key);
+        is_controller_set = false;
+    }
+}
+
+void PlayerControlPreview::BeginMappingButton(std::size_t button_id) {
+    button_mapping_index = button_id;
     mapping_active = true;
 }
 
-void PlayerControlPreview::BeginMappingAnalog(std::size_t index) {
-    button_mapping_index = Settings::NativeButton::LStick + index;
-    analog_mapping_index = index;
+void PlayerControlPreview::BeginMappingAnalog(std::size_t stick_id) {
+    button_mapping_index = Settings::NativeButton::LStick + stick_id;
+    analog_mapping_index = stick_id;
     mapping_active = true;
 }
 
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index 16f9748f54..333c3fc56b 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -25,11 +25,25 @@ public:
     explicit PlayerControlPreview(QWidget* parent);
     ~PlayerControlPreview() override;
 
+    // Sets the emulated controller to be displayed
     void SetController(Core::HID::EmulatedController* controller);
+
+    // Disables events from the emulated controller
+    void UnloadController();
+
+    // Starts blinking animation at the button specified
     void BeginMappingButton(std::size_t button_id);
-    void BeginMappingAnalog(std::size_t button_id);
+
+    // Starts moving animation at the stick specified
+    void BeginMappingAnalog(std::size_t stick_id);
+
+    // Stops any ongoing animation
     void EndMapping();
+
+    // Handles emulated controller events
     void ControllerUpdate(Core::HID::ControllerTriggerType type);
+
+    // Updates input on sheduled interval
     void UpdateInput();
 
 protected:
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
index d8e41f8b69..3619aed260 100644
--- a/src/yuzu/debugger/controller.cpp
+++ b/src/yuzu/debugger/controller.cpp
@@ -10,7 +10,8 @@
 #include "yuzu/configuration/configure_input_player_widget.h"
 #include "yuzu/debugger/controller.h"
 
-ControllerDialog::ControllerDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) {
+ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent)
+    : QWidget(parent, Qt::Dialog) {
     setObjectName(QStringLiteral("Controller"));
     setWindowTitle(tr("Controller P1"));
     resize(500, 350);
@@ -20,7 +21,7 @@ ControllerDialog::ControllerDialog(QWidget* parent) : QWidget(parent, Qt::Dialog
                    Qt::WindowMaximizeButtonHint);
 
     widget = new PlayerControlPreview(this);
-    widget->SetController(Core::System::GetInstance().HIDCore().GetEmulatedController(
+    widget->SetController(system.HIDCore().GetEmulatedController(
         Core::HID::NpadIdType::Player1));
     QLayout* layout = new QVBoxLayout(this);
     layout->setContentsMargins(0, 0, 0, 0);
@@ -45,6 +46,10 @@ QAction* ControllerDialog::toggleViewAction() {
     return toggle_view_action;
 }
 
+void ControllerDialog::UnloadController() {
+    widget->UnloadController();
+}
+
 void ControllerDialog::showEvent(QShowEvent* ev) {
     if (toggle_view_action) {
         toggle_view_action->setChecked(isVisible());
diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h
index 697489cbbd..33f617b9b9 100644
--- a/src/yuzu/debugger/controller.h
+++ b/src/yuzu/debugger/controller.h
@@ -11,6 +11,10 @@ class QHideEvent;
 class QShowEvent;
 class PlayerControlPreview;
 
+namespace Core {
+class System;
+}
+
 namespace InputCommon {
 class InputSubsystem;
 }
@@ -19,11 +23,14 @@ class ControllerDialog : public QWidget {
     Q_OBJECT
 
 public:
-    explicit ControllerDialog(QWidget* parent = nullptr);
+    explicit ControllerDialog(Core::System& system, QWidget* parent = nullptr);
 
     /// Returns a QAction that can be used to toggle visibility of this dialog.
     QAction* toggleViewAction();
 
+    // Disables events from the emulated controller
+    void UnloadController();
+
 protected:
     void showEvent(QShowEvent* ev) override;
     void hideEvent(QHideEvent* ev) override;
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 19cb5313fd..ae997ccfa3 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -228,7 +228,7 @@ GMainWindow::GMainWindow()
     ConnectMenuEvents();
     ConnectWidgetEvents();
 
-    Core::System::GetInstance().HIDCore().ReloadInputDevices();
+    system->HIDCore().ReloadInputDevices();
 
     const auto branch_name = std::string(Common::g_scm_branch);
     const auto description = std::string(Common::g_scm_desc);
@@ -924,7 +924,7 @@ void GMainWindow::InitializeDebugWidgets() {
     waitTreeWidget->hide();
     debug_menu->addAction(waitTreeWidget->toggleViewAction());
 
-    controller_dialog = new ControllerDialog(this);
+    controller_dialog = new ControllerDialog(*system, this);
     controller_dialog->hide();
     debug_menu->addAction(controller_dialog->toggleViewAction());
 
@@ -3372,7 +3372,8 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
     UpdateUISettings();
     game_list->SaveInterfaceLayout();
     hotkey_registry.SaveHotkeys();
-    Core::System::GetInstance().HIDCore().UnloadInputDevices();
+    controller_dialog->UnloadController();
+    system->HIDCore().UnloadInputDevices();
 
     // Shutdown session if the emu thread is active...
     if (emu_thread != nullptr) {

From 72e5920240381cbe775dc38fcdff88cf46b55101 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 17 Oct 2021 00:33:00 -0500
Subject: [PATCH 38/88] core/hid: Documment some files

---
 src/core/hid/emulated_console.h    |  69 +++++++++++---
 src/core/hid/emulated_controller.h | 148 +++++++++++++++++++++++++----
 src/core/hid/emulated_devices.cpp  |  16 +++-
 src/core/hid/emulated_devices.h    |  84 ++++++++++++----
 4 files changed, 265 insertions(+), 52 deletions(-)

diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h
index d9e275042c..7d6cf95069 100644
--- a/src/core/hid/emulated_console.h
+++ b/src/core/hid/emulated_console.h
@@ -38,9 +38,10 @@ struct TouchFinger {
     Common::Point<float> position{};
     u32_le id{};
     bool pressed{};
-    Core::HID::TouchAttribute attribute{};
+    TouchAttribute attribute{};
 };
 
+// Contains all motion related data that is used on the services
 struct ConsoleMotion {
     bool is_at_rest{};
     Common::Vec3f accel{};
@@ -57,7 +58,7 @@ struct ConsoleStatus {
     ConsoleMotionValues motion_values{};
     TouchValues touch_values{};
 
-    // Data for Nintendo devices;
+    // Data for HID services
     ConsoleMotion motion_state{};
     TouchFingerState touch_state{};
 };
@@ -75,52 +76,90 @@ struct ConsoleUpdateCallback {
 class EmulatedConsole {
 public:
     /**
-     * TODO: Write description
-     *
-     * @param npad_id_type
+     * Contains all input data related to the console like motion and touch input
      */
-    explicit EmulatedConsole();
+    EmulatedConsole();
     ~EmulatedConsole();
 
     YUZU_NON_COPYABLE(EmulatedConsole);
     YUZU_NON_MOVEABLE(EmulatedConsole);
 
-    void ReloadFromSettings();
-    void ReloadInput();
+    /// Removes all callbacks created from input devices
     void UnloadInput();
 
+    /// Sets the emulated console into configuring mode. Locking all HID service events from being
+    /// moddified
     void EnableConfiguration();
+
+    /// Returns the emulated console to the normal behaivour
     void DisableConfiguration();
+
+    /// Returns true if the emulated console is on configuring mode
     bool IsConfiguring() const;
+
+    /// Reload all input devices
+    void ReloadInput();
+
+    /// Overrides current mapped devices with the stored configuration and reloads all input devices
+    void ReloadFromSettings();
+
+    /// Saves the current mapped configuration
     void SaveCurrentConfig();
+
+    /// Reverts any mapped changes made that weren't saved
     void RestoreConfig();
 
+    // Returns the current mapped motion device
     Common::ParamPackage GetMotionParam() const;
 
+    /**
+     * Updates the current mapped motion device
+     * @param ParamPackage with controller data to be mapped
+     */
     void SetMotionParam(Common::ParamPackage param);
 
+    /// Returns the latest status of motion input from the console with parameters
     ConsoleMotionValues GetMotionValues() const;
+
+    /// Returns the latest status of touch input from the console with parameters
     TouchValues GetTouchValues() const;
 
+    /// Returns the latest status of motion input from the console
     ConsoleMotion GetMotion() const;
+
+    /// Returns the latest status of touch input from the console
     TouchFingerState GetTouch() const;
 
+    /**
+     * Adds a callback to the list of events
+     * @param ConsoleUpdateCallback that will be triggered
+     * @return an unique key corresponding to the callback index in the list
+     */
     int SetCallback(ConsoleUpdateCallback update_callback);
+
+    /**
+     * Removes a callback from the list stopping any future events to this object
+     * @param Key corresponding to the callback index in the list
+     */
     void DeleteCallback(int key);
 
 private:
     /**
-     * Sets the status of a button. Applies toggle properties to the output.
-     *
-     * @param A CallbackStatus and a button index number
+     * Updates the motion status of the console
+     * @param A CallbackStatus containing gyro and accelerometer data
      */
     void SetMotion(Input::CallbackStatus callback);
+
+    /**
+     * Updates the touch status of the console
+     * @param callback: A CallbackStatus containing the touch position
+     * @param index: Finger ID to be updated
+     */
     void SetTouch(Input::CallbackStatus callback, std::size_t index);
 
     /**
-     * Triggers a callback that something has changed
-     *
-     * @param Input type of the trigger
+     * Triggers a callback that something has changed on the console status
+     * @param Input type of the event to trigger
      */
     void TriggerOnChange(ConsoleTriggerType type);
 
@@ -136,6 +175,8 @@ private:
     mutable std::mutex mutex;
     std::unordered_map<int, ConsoleUpdateCallback> callback_list;
     int last_callback_key = 0;
+
+    // Stores the current status of all console input
     ConsoleStatus console;
 };
 
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 322d2cab04..096fe17052 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -87,7 +87,7 @@ struct ControllerStatus {
     BatteryValues battery_values{};
     VibrationValues vibration_values{};
 
-    // Data for Nintendo devices
+    // Data for HID serices
     NpadButtonState npad_button_state{};
     DebugPadButton debug_pad_button_state{};
     AnalogSticks analog_stick_state{};
@@ -118,9 +118,8 @@ struct ControllerUpdateCallback {
 class EmulatedController {
 public:
     /**
-     * TODO: Write description
-     *
-     * @param npad_id_type
+     * Contains all input data related to this controller. Like buttons, joysticks, motion.
+     * @param Npad id type for this specific controller
      */
     explicit EmulatedController(NpadIdType npad_id_type_);
     ~EmulatedController();
@@ -128,86 +127,197 @@ public:
     YUZU_NON_COPYABLE(EmulatedController);
     YUZU_NON_MOVEABLE(EmulatedController);
 
+    /// Converts the controller type from settings to npad type
     static NpadType MapSettingsTypeToNPad(Settings::ControllerType type);
+
+    /// Converts npad type to the equivalent of controller type from settings
     static Settings::ControllerType MapNPadToSettingsType(NpadType type);
 
-    /// Gets the NpadIdType for this controller.
+    /// Gets the NpadIdType for this controller
     NpadIdType GetNpadIdType() const;
 
-    /// Sets the NpadType for this controller.
+    /// Sets the NpadType for this controller
     void SetNpadType(NpadType npad_type_);
 
-    /// Gets the NpadType for this controller.
+    /// Gets the NpadType for this controller
     NpadType GetNpadType() const;
 
-    /// Gets the NpadType for this controller.
-    LedPattern GetLedPattern() const;
-
+    /// Sets the connected status to true
     void Connect();
+
+    /// Sets the connected status to false
     void Disconnect();
 
+    /// Returns true if the controller has the connected status
     bool IsConnected() const;
+
+    /// Returns true if vibration is enabled
     bool IsVibrationEnabled() const;
 
-    void ReloadFromSettings();
-    void ReloadInput();
+    /// Removes all callbacks created from input devices
     void UnloadInput();
 
+    /// Sets the emulated console into configuring mode. Locking all HID service events from being
+    /// moddified
     void EnableConfiguration();
+
+    /// Returns the emulated console to the normal behaivour
     void DisableConfiguration();
+
+    /// Returns true if the emulated device is on configuring mode
     bool IsConfiguring() const;
+
+    /// Reload all input devices
+    void ReloadInput();
+
+    /// Overrides current mapped devices with the stored configuration and reloads all input devices
+    void ReloadFromSettings();
+
+    /// Saves the current mapped configuration
     void SaveCurrentConfig();
+
+    /// Reverts any mapped changes made that weren't saved
     void RestoreConfig();
 
+    /// Returns a vector of mapped devices from the mapped button and stick parameters
     std::vector<Common::ParamPackage> GetMappedDevices() const;
 
+    // Returns the current mapped button device
     Common::ParamPackage GetButtonParam(std::size_t index) const;
+
+    // Returns the current mapped stick device
     Common::ParamPackage GetStickParam(std::size_t index) const;
+
+    // Returns the current mapped motion device
     Common::ParamPackage GetMotionParam(std::size_t index) const;
 
+    /**
+     * Updates the current mapped button device
+     * @param ParamPackage with controller data to be mapped
+     */
     void SetButtonParam(std::size_t index, Common::ParamPackage param);
+
+    /**
+     * Updates the current mapped stick device
+     * @param ParamPackage with controller data to be mapped
+     */
     void SetStickParam(std::size_t index, Common::ParamPackage param);
+
+    /**
+     * Updates the current mapped motion device
+     * @param ParamPackage with controller data to be mapped
+     */
     void SetMotionParam(std::size_t index, Common::ParamPackage param);
 
+    /// Returns the latest button status from the controller with parameters
     ButtonValues GetButtonsValues() const;
+
+    /// Returns the latest analog stick status from the controller with parameters
     SticksValues GetSticksValues() const;
+
+    /// Returns the latest trigger status from the controller with parameters
     TriggerValues GetTriggersValues() const;
+
+    /// Returns the latest motion status from the controller with parameters
     ControllerMotionValues GetMotionValues() const;
+
+    /// Returns the latest color status from the controller with parameters
     ColorValues GetColorsValues() const;
+
+    /// Returns the latest battery status from the controller with parameters
     BatteryValues GetBatteryValues() const;
 
+    /// Returns the latest status of button input for the npad service
     NpadButtonState GetNpadButtons() const;
+
+    /// Returns the latest status of button input for the debug pad service
     DebugPadButton GetDebugPadButtons() const;
+
+    /// Returns the latest status of stick input from the mouse
     AnalogSticks GetSticks() const;
+
+    /// Returns the latest status of trigger input from the mouse
     NpadGcTriggerState GetTriggers() const;
+
+    /// Returns the latest status of motion input from the mouse
     MotionState GetMotions() const;
+
+    /// Returns the latest color value from the controller
     ControllerColors GetColors() const;
+
+    /// Returns the latest battery status from the controller
     BatteryLevelState GetBattery() const;
 
+    /*
+     * Sends a specific vibration to the output device
+     * @return returns true if vibration had no errors
+     */
     bool SetVibration(std::size_t device_index, VibrationValue vibration);
+
+    /*
+     * Sends a small vibration to the output device
+     * @return returns true if SetVibration was successfull
+     */
     bool TestVibration(std::size_t device_index);
 
+    /// Returns the led pattern corresponding to this emulated controller
+    LedPattern GetLedPattern() const;
+
+    /// Asks the output device to change the player led pattern
     void SetLedPattern();
 
+    /**
+     * Adds a callback to the list of events
+     * @param ConsoleUpdateCallback that will be triggered
+     * @return an unique key corresponding to the callback index in the list
+     */
     int SetCallback(ControllerUpdateCallback update_callback);
+
+    /**
+     * Removes a callback from the list stopping any future events to this object
+     * @param Key corresponding to the callback index in the list
+     */
     void DeleteCallback(int key);
 
 private:
     /**
-     * Sets the status of a button. Applies toggle properties to the output.
-     *
-     * @param A CallbackStatus and a button index number
+     * Updates the button status of the controller
+     * @param callback: A CallbackStatus containing the button status
+     * @param index: Button ID of the to be updated
      */
     void SetButton(Input::CallbackStatus callback, std::size_t index);
+
+    /**
+     * Updates the analog stick status of the controller
+     * @param callback: A CallbackStatus containing the analog stick status
+     * @param index: stick ID of the to be updated
+     */
     void SetStick(Input::CallbackStatus callback, std::size_t index);
+
+    /**
+     * Updates the trigger status of the controller
+     * @param callback: A CallbackStatus containing the trigger status
+     * @param index: trigger ID of the to be updated
+     */
     void SetTrigger(Input::CallbackStatus callback, std::size_t index);
+
+    /**
+     * Updates the motion status of the controller
+     * @param callback: A CallbackStatus containing gyro and accelerometer data
+     * @param index: motion ID of the to be updated
+     */
     void SetMotion(Input::CallbackStatus callback, std::size_t index);
+
+    /**
+     * Updates the battery status of the controller
+     * @param callback: A CallbackStatus containing the battery status
+     * @param index: Button ID of the to be updated
+     */
     void SetBattery(Input::CallbackStatus callback, std::size_t index);
 
     /**
-     * Triggers a callback that something has changed
-     *
-     * @param Input type of the trigger
+     * Triggers a callback that something has changed on the controller status
+     * @param Input type of the event to trigger
      */
     void TriggerOnChange(ControllerTriggerType type);
 
@@ -235,6 +345,8 @@ private:
     mutable std::mutex mutex;
     std::unordered_map<int, ControllerUpdateCallback> callback_list;
     int last_callback_key = 0;
+
+    // Stores the current status of all controller input
     ControllerStatus controller;
 };
 
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
index 3caf90714a..54a753d8a5 100644
--- a/src/core/hid/emulated_devices.cpp
+++ b/src/core/hid/emulated_devices.cpp
@@ -114,7 +114,7 @@ Common::ParamPackage EmulatedDevices::GetMouseButtonParam(std::size_t index) con
     return mouse_button_params[index];
 }
 
-void EmulatedDevices::SetButtonParam(std::size_t index, Common::ParamPackage param) {
+void EmulatedDevices::SetMouseButtonParam(std::size_t index, Common::ParamPackage param) {
     if (index >= mouse_button_params.size()) {
         return;
     }
@@ -132,7 +132,7 @@ void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::siz
     auto& current_status = device_status.keyboard_values[index];
     current_status.toggle = new_status.toggle;
 
-    // Update button status with current
+    // Update button status with current status
     if (!current_status.toggle) {
         current_status.locked = false;
         if (current_status.value != new_status.value) {
@@ -147,7 +147,7 @@ void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::siz
             value_changed = true;
         }
 
-        // Unlock button ready for next press
+        // Unlock button, ready for next press
         if (!new_status.value && current_status.locked) {
             current_status.locked = false;
         }
@@ -168,7 +168,7 @@ void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::siz
     //    interface_status.keyboard_state.a.Assign(current_status.value);
     //    break;
     //    ....
-    //}
+    // }
 
     TriggerOnChange(DeviceTriggerType::Keyboard);
 }
@@ -303,6 +303,14 @@ void EmulatedDevices::SetMouseButton(Input::CallbackStatus callback, std::size_t
     TriggerOnChange(DeviceTriggerType::Mouse);
 }
 
+KeyboardValues EmulatedDevices::GetKeyboardValues() const {
+    return device_status.keyboard_values;
+}
+
+KeyboardModifierValues EmulatedDevices::GetKeyboardModdifierValues() const {
+    return device_status.keyboard_moddifier_values;
+}
+
 MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const {
     return device_status.mouse_button_values;
 }
diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h
index 6f728eff55..c6c19fae4e 100644
--- a/src/core/hid/emulated_devices.h
+++ b/src/core/hid/emulated_devices.h
@@ -45,7 +45,7 @@ struct DeviceStatus {
     KeyboardModifierValues keyboard_moddifier_values{};
     MouseButtonValues mouse_button_values{};
 
-    // Data for Nintendo devices
+    // Data for HID serices
     KeyboardKey keyboard_state{};
     KeyboardModifier keyboard_moddifier_state{};
     MouseButton mouse_button_state{};
@@ -65,58 +65,108 @@ struct InterfaceUpdateCallback {
 class EmulatedDevices {
 public:
     /**
-     * TODO: Write description
-     *
-     * @param npad_id_type
+     * Contains all input data related to external devices that aren't necesarily a controller
+     * like keyboard and mouse
      */
-    explicit EmulatedDevices();
+    EmulatedDevices();
     ~EmulatedDevices();
 
     YUZU_NON_COPYABLE(EmulatedDevices);
     YUZU_NON_MOVEABLE(EmulatedDevices);
 
-    void ReloadFromSettings();
-    void ReloadInput();
+    /// Removes all callbacks created from input devices
     void UnloadInput();
 
+    /// Sets the emulated console into configuring mode. Locking all HID service events from being
+    /// moddified
     void EnableConfiguration();
+
+    /// Returns the emulated console to the normal behaivour
     void DisableConfiguration();
+
+    /// Returns true if the emulated device is on configuring mode
     bool IsConfiguring() const;
+
+    /// Reload all input devices
+    void ReloadInput();
+
+    /// Overrides current mapped devices with the stored configuration and reloads all input devices
+    void ReloadFromSettings();
+
+    /// Saves the current mapped configuration
     void SaveCurrentConfig();
+
+    /// Reverts any mapped changes made that weren't saved
     void RestoreConfig();
 
-    std::vector<Common::ParamPackage> GetMappedDevices() const;
-
+    /// Returns the current mapped motion device
     Common::ParamPackage GetMouseButtonParam(std::size_t index) const;
 
-    void SetButtonParam(std::size_t index, Common::ParamPackage param);
+    /**
+     * Updates the current mapped mouse button device
+     * @param ParamPackage with controller data to be mapped
+     */
+    void SetMouseButtonParam(std::size_t index, Common::ParamPackage param);
 
+    /// Returns the latest status of button input from the keyboard with parameters
     KeyboardValues GetKeyboardValues() const;
+
+    /// Returns the latest status of button input from the keyboard modifiers with parameters
     KeyboardModifierValues GetKeyboardModdifierValues() const;
+
+    /// Returns the latest status of button input from the mouse with parameters
     MouseButtonValues GetMouseButtonsValues() const;
 
+    /// Returns the latest status of button input from the keyboard
     KeyboardKey GetKeyboard() const;
+
+    /// Returns the latest status of button input from the keyboard modifiers
     KeyboardModifier GetKeyboardModifier() const;
+
+    /// Returns the latest status of button input from the mouse
     MouseButton GetMouseButtons() const;
+
+    /// Returns the latest mouse coordinates
     MousePosition GetMousePosition() const;
 
+    /**
+     * Adds a callback to the list of events
+     * @param ConsoleUpdateCallback that will be triggered
+     * @return an unique key corresponding to the callback index in the list
+     */
     int SetCallback(InterfaceUpdateCallback update_callback);
+
+    /**
+     * Removes a callback from the list stopping any future events to this object
+     * @param Key corresponding to the callback index in the list
+     */
     void DeleteCallback(int key);
 
 private:
     /**
-     * Sets the status of a button. Applies toggle properties to the output.
-     *
-     * @param A CallbackStatus and a button index number
+     * Updates the touch status of the console
+     * @param callback: A CallbackStatus containing the key status
+     * @param index: key ID to be updated
      */
     void SetKeyboardButton(Input::CallbackStatus callback, std::size_t index);
+
+    /**
+     * Updates the touch status of the console
+     * @param callback: A CallbackStatus containing the modifier key status
+     * @param index: modifier key ID to be updated
+     */
     void SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index);
+
+    /**
+     * Updates the touch status of the console
+     * @param callback: A CallbackStatus containing the button status
+     * @param index: Button ID of the to be updated
+     */
     void SetMouseButton(Input::CallbackStatus callback, std::size_t index);
 
     /**
-     * Triggers a callback that something has changed
-     *
-     * @param Input type of the trigger
+     * Triggers a callback that something has changed on the device status
+     * @param Input type of the event to trigger
      */
     void TriggerOnChange(DeviceTriggerType type);
 
@@ -131,6 +181,8 @@ private:
     mutable std::mutex mutex;
     std::unordered_map<int, InterfaceUpdateCallback> callback_list;
     int last_callback_key = 0;
+
+    // Stores the current status of all external device input
     DeviceStatus device_status;
 };
 

From 4d308fd0b4fc8f14754c47811e751bf068b330b8 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 18 Oct 2021 23:15:46 -0500
Subject: [PATCH 39/88] hid: Fix controller connection/disconnection

---
 src/core/hid/emulated_console.cpp             |  1 -
 src/core/hid/emulated_controller.cpp          | 98 +++++++++++++++----
 src/core/hid/emulated_controller.h            | 18 +++-
 src/core/hid/hid_types.h                      |  8 +-
 .../hid/controllers/controller_base.cpp       |  2 +-
 src/core/hle/service/hid/controllers/npad.cpp | 77 ++++++++++-----
 src/core/hle/service/hid/controllers/npad.h   |  3 +
 src/yuzu/configuration/configure_input.cpp    |  1 +
 .../configuration/configure_input_player.cpp  | 81 +++++++++++++--
 .../configure_input_player_widget.cpp         |  2 +-
 10 files changed, 226 insertions(+), 65 deletions(-)

diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index c65d050411..7f7c8fd59d 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -53,7 +53,6 @@ void EmulatedConsole::ReloadInput() {
         touch_button_params.Set("x", x);
         touch_button_params.Set("y", y);
         touch_button_params.Set("touch_id", static_cast<int>(index));
-        LOG_ERROR(Common, "{} ", touch_button_params.Serialize());
         touch_devices[index] =
             Input::CreateDeviceFromString<Input::InputDevice>(touch_button_params.Serialize());
         if (!touch_devices[index]) {
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index b04ab4cd84..7ef6ef1180 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -54,6 +54,7 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type
 }
 
 void EmulatedController::ReloadFromSettings() {
+    //LOG_ERROR(Service_HID, "reload config from settings {}", NpadIdTypeToIndex(npad_id_type));
     const auto player_index = NpadIdTypeToIndex(npad_id_type);
     const auto& player = Settings::values.players.GetValue()[player_index];
 
@@ -91,6 +92,7 @@ void EmulatedController::ReloadFromSettings() {
 }
 
 void EmulatedController::ReloadInput() {
+    //LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type));
     // If you load any device here add the equivalent to the UnloadInput() function
     const auto player_index = NpadIdTypeToIndex(npad_id_type);
     const auto left_side = button_params[Settings::NativeButton::ZL];
@@ -187,11 +189,29 @@ void EmulatedController::UnloadInput() {
 
 void EmulatedController::EnableConfiguration() {
     is_configuring = true;
-    SaveCurrentConfig();
+    temporary_is_connected = is_connected;
+    temporary_npad_type = npad_type;
 }
 
 void EmulatedController::DisableConfiguration() {
     is_configuring = false;
+
+    // Apply temporary npad type to the real controller
+    if (temporary_npad_type != npad_type) {
+        if (is_connected) {
+            Disconnect();
+        }
+        SetNpadType(temporary_npad_type);
+    }
+
+    // Apply temporary connected status to the real controller
+    if (temporary_is_connected != is_connected) {
+        if (temporary_is_connected) {
+            Connect();
+            return;
+        }
+        Disconnect();
+    }
 }
 
 bool EmulatedController::IsConfiguring() const {
@@ -199,10 +219,6 @@ bool EmulatedController::IsConfiguring() const {
 }
 
 void EmulatedController::SaveCurrentConfig() {
-    if (!is_configuring) {
-        return;
-    }
-
     const auto player_index = NpadIdTypeToIndex(npad_id_type);
     auto& player = Settings::values.players.GetValue()[player_index];
     player.connected = is_connected;
@@ -657,26 +673,47 @@ void EmulatedController::SetLedPattern() {
 }
 
 void EmulatedController::Connect() {
-    std::lock_guard lock{mutex};
-    if (is_connected) {
-        LOG_WARNING(Service_HID, "Tried to turn on a connected controller {}", npad_id_type);
-        return;
+    {
+        std::lock_guard lock{mutex};
+        if (is_configuring) {
+            temporary_is_connected = true;
+            TriggerOnChange(ControllerTriggerType::Connected);
+            return;
+        }
+
+        if (is_connected) {
+            return;
+        }
+        is_connected = true;
     }
-    is_connected = true;
+    LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type));
     TriggerOnChange(ControllerTriggerType::Connected);
 }
 
 void EmulatedController::Disconnect() {
-    std::lock_guard lock{mutex};
-    if (!is_connected) {
-        LOG_WARNING(Service_HID, "Tried to turn off a disconnected controller {}", npad_id_type);
-        return;
+    {
+        std::lock_guard lock{mutex};
+        if (is_configuring) {
+            temporary_is_connected = false;
+            LOG_ERROR(Service_HID, "Disconnected temporal controller {}",
+                      NpadIdTypeToIndex(npad_id_type));
+            TriggerOnChange(ControllerTriggerType::Disconnected);
+            return;
+        }
+
+        if (!is_connected) {
+            return;
+        }
+        is_connected = false;
     }
-    is_connected = false;
+    LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type));
     TriggerOnChange(ControllerTriggerType::Disconnected);
 }
 
-bool EmulatedController::IsConnected() const {
+bool EmulatedController::IsConnected(bool temporary) const {
+    if (temporary) {
+        return temporary_is_connected;
+    }
     return is_connected;
 }
 
@@ -688,16 +725,35 @@ NpadIdType EmulatedController::GetNpadIdType() const {
     return npad_id_type;
 }
 
-NpadType EmulatedController::GetNpadType() const {
+NpadType EmulatedController::GetNpadType(bool temporary) const {
+    if (temporary) {
+        return temporary_npad_type;
+    }
     return npad_type;
 }
 
 void EmulatedController::SetNpadType(NpadType npad_type_) {
-    std::lock_guard lock{mutex};
-    if (npad_type == npad_type_) {
-        return;
+    {
+        std::lock_guard lock{mutex};
+
+        if (is_configuring) {
+            if (temporary_npad_type == npad_type_) {
+                return;
+            }
+            temporary_npad_type = npad_type_;
+            TriggerOnChange(ControllerTriggerType::Type);
+            return;
+        }
+
+        if (npad_type == npad_type_) {
+            return;
+        }
+        if (is_connected) {
+            LOG_WARNING(Service_HID, "Controller {} type changed while it's connected",
+                        NpadIdTypeToIndex(npad_id_type));
+        }
+        npad_type = npad_type_;
     }
-    npad_type = npad_type_;
     TriggerOnChange(ControllerTriggerType::Type);
 }
 
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 096fe17052..6a6dc18927 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -139,8 +139,12 @@ public:
     /// Sets the NpadType for this controller
     void SetNpadType(NpadType npad_type_);
 
-    /// Gets the NpadType for this controller
-    NpadType GetNpadType() const;
+    /**
+     * Gets the NpadType for this controller
+     * @param Returns the temporary value if true
+     * @return NpadType set on the controller
+     */
+    NpadType GetNpadType(bool temporary = false) const;
 
     /// Sets the connected status to true
     void Connect();
@@ -148,8 +152,12 @@ public:
     /// Sets the connected status to false
     void Disconnect();
 
-    /// Returns true if the controller has the connected status
-    bool IsConnected() const;
+    /**
+     * Is the emulated connected
+     * @param Returns the temporary value if true
+     * @return true if the controller has the connected status
+     */
+    bool IsConnected(bool temporary = false) const;
 
     /// Returns true if vibration is enabled
     bool IsVibrationEnabled() const;
@@ -323,7 +331,9 @@ private:
 
     NpadIdType npad_id_type;
     NpadType npad_type{NpadType::None};
+    NpadType temporary_npad_type{NpadType::None};
     bool is_connected{false};
+    bool temporary_is_connected{false};
     bool is_configuring{false};
     bool is_vibration_enabled{true};
     f32 motion_sensitivity{0.01f};
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index f12a14cb8e..539436283d 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -47,9 +47,9 @@ constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
         return 6;
     case NpadIdType::Player8:
         return 7;
-    case NpadIdType::Other:
-        return 8;
     case NpadIdType::Handheld:
+        return 8;
+    case NpadIdType::Other:
         return 9;
     default:
         return 0;
@@ -76,9 +76,9 @@ constexpr NpadIdType IndexToNpadIdType(size_t index) {
     case 7:
         return NpadIdType::Player8;
     case 8:
-        return NpadIdType::Other;
-    case 9:
         return NpadIdType::Handheld;
+    case 9:
+        return NpadIdType::Other;
     default:
         return NpadIdType::Invalid;
     }
diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp
index 9d1e6db6a2..74a3947842 100644
--- a/src/core/hle/service/hid/controllers/controller_base.cpp
+++ b/src/core/hle/service/hid/controllers/controller_base.cpp
@@ -11,7 +11,7 @@ ControllerBase::~ControllerBase() = default;
 
 void ControllerBase::ActivateController() {
     if (is_activated) {
-        OnRelease();
+        return;
     }
     is_activated = true;
     OnInit();
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index a2e9ddf4d5..144abab653 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -125,18 +125,22 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
         return;
     }
 
+    auto& controller = controller_data[controller_idx];
+    const auto is_connected = controller.device->IsConnected();
+    const auto npad_type = controller.device->GetNpadType();
     switch (type) {
     case Core::HID::ControllerTriggerType::Connected:
-        InitNewlyAddedController(controller_idx);
-        break;
     case Core::HID::ControllerTriggerType::Disconnected:
-        DisconnectNpadAtIndex(controller_idx);
+        if (is_connected == controller.is_connected) {
+            return;
+        }
+        UpdateControllerAt(npad_type, controller_idx, is_connected);
         break;
     case Core::HID::ControllerTriggerType::Type: {
-        auto& controller = controller_data[controller_idx];
-        if (controller.device->IsConnected()) {
-            LOG_ERROR(Service_HID, "Controller type changed without turning off the controller");
+        if (npad_type == controller.npad_type) {
+            return;
         }
+        // UpdateControllerAt(npad_type, controller_idx, is_connected);
         break;
     }
     default:
@@ -146,6 +150,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
 
 void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
     auto& controller = controller_data[controller_idx];
+    LOG_ERROR(Service_HID, "Connect {} {}", controller_idx, controller.is_connected);
     const auto controller_type = controller.device->GetNpadType();
     auto& shared_memory = controller.shared_memory_entry;
     if (controller_type == Core::HID::NpadType::None) {
@@ -235,20 +240,23 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
     shared_memory.battery_level_left = battery_level.left.battery_level;
     shared_memory.battery_level_right = battery_level.right.battery_level;
 
+    controller.is_connected = true;
+    controller.device->Connect();
     SignalStyleSetChangedEvent(IndexToNPad(controller_idx));
+    WriteEmptyEntry(controller.shared_memory_entry);
 }
 
 void Controller_NPad::OnInit() {
+    if (!IsControllerActivated()) {
+        return;
+    }
+
     for (std::size_t i = 0; i < controller_data.size(); ++i) {
         auto& controller = controller_data[i];
         controller.styleset_changed_event =
             service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
     }
 
-    if (!IsControllerActivated()) {
-        return;
-    }
-
     if (system.HIDCore().GetSupportedStyleTag().raw == 0) {
         // We want to support all controllers
         Core::HID::NpadStyleTag style{};
@@ -277,20 +285,33 @@ void Controller_NPad::OnInit() {
     for (auto& controller : controller_data) {
         NPadGenericState dummy_pad_state{};
         auto& npad = controller.shared_memory_entry;
-        for (std::size_t i = 0; i < 17; ++i) {
-            dummy_pad_state.sampling_number =
-                npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
-            npad.fullkey_lifo.WriteNextEntry(dummy_pad_state);
-            npad.handheld_lifo.WriteNextEntry(dummy_pad_state);
-            npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state);
-            npad.joy_left_lifo.WriteNextEntry(dummy_pad_state);
-            npad.joy_right_lifo.WriteNextEntry(dummy_pad_state);
-            npad.joy_right_lifo.WriteNextEntry(dummy_pad_state);
-            npad.palma_lifo.WriteNextEntry(dummy_pad_state);
+        for (std::size_t i = 0; i < 19; ++i) {
+            WriteEmptyEntry(npad);
         }
     }
 }
 
+void Controller_NPad::WriteEmptyEntry(NpadInternalState& npad) {
+    NPadGenericState dummy_pad_state{};
+    NpadGcTriggerState dummy_gc_state{};
+    dummy_pad_state.sampling_number = npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
+    npad.fullkey_lifo.WriteNextEntry(dummy_pad_state);
+    dummy_pad_state.sampling_number = npad.handheld_lifo.ReadCurrentEntry().sampling_number + 1;
+    npad.handheld_lifo.WriteNextEntry(dummy_pad_state);
+    dummy_pad_state.sampling_number = npad.joy_dual_lifo.ReadCurrentEntry().sampling_number + 1;
+    npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state);
+    dummy_pad_state.sampling_number = npad.joy_left_lifo.ReadCurrentEntry().sampling_number + 1;
+    npad.joy_left_lifo.WriteNextEntry(dummy_pad_state);
+    dummy_pad_state.sampling_number = npad.joy_right_lifo.ReadCurrentEntry().sampling_number + 1;
+    npad.joy_right_lifo.WriteNextEntry(dummy_pad_state);
+    dummy_pad_state.sampling_number = npad.palma_lifo.ReadCurrentEntry().sampling_number + 1;
+    npad.palma_lifo.WriteNextEntry(dummy_pad_state);
+    dummy_pad_state.sampling_number = npad.system_ext_lifo.ReadCurrentEntry().sampling_number + 1;
+    npad.system_ext_lifo.WriteNextEntry(dummy_pad_state);
+    dummy_gc_state.sampling_number = npad.gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1;
+    npad.gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
+}
+
 void Controller_NPad::OnRelease() {
     for (std::size_t i = 0; i < controller_data.size(); ++i) {
         auto& controller = controller_data[i];
@@ -359,6 +380,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
     if (!IsControllerActivated()) {
         return;
     }
+
     for (std::size_t i = 0; i < controller_data.size(); ++i) {
         auto& controller = controller_data[i];
         auto& npad = controller.shared_memory_entry;
@@ -366,6 +388,9 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
         const auto& controller_type = controller.device->GetNpadType();
 
         if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) {
+            // Refresh shared memory
+            std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
+                        &controller.shared_memory_entry, sizeof(NpadInternalState));
             continue;
         }
         const u32 npad_index = static_cast<u32>(i);
@@ -830,14 +855,14 @@ void Controller_NPad::AddNewControllerAt(Core::HID::NpadType controller, std::si
 
 void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t npad_index,
                                          bool connected) {
-    auto& controller = controller_data[npad_index].device;
+    auto& controller = controller_data[npad_index];
     if (!connected) {
         DisconnectNpadAtIndex(npad_index);
         return;
     }
 
-    controller->SetNpadType(type);
-    controller->Connect();
+    controller.device->SetNpadType(type);
+    controller.device->Connect();
     InitNewlyAddedController(npad_index);
 }
 
@@ -847,14 +872,13 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) {
 
 void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
     auto& controller = controller_data[npad_index];
+    LOG_ERROR(Service_HID, "Disconnect {} {}", npad_index, controller.is_connected);
     for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
         // Send an empty vibration to stop any vibrations.
         VibrateControllerAtIndex(npad_index, device_idx, {});
         controller.vibration[device_idx].device_mounted = false;
     }
 
-    controller.device->Disconnect();
-
     auto& shared_memory_entry = controller.shared_memory_entry;
     shared_memory_entry.style_set.raw = 0; // Zero out
     shared_memory_entry.device_type.raw = 0;
@@ -868,7 +892,10 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
     shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual;
     shared_memory_entry.footer_type = AppletFooterUiType::None;
 
+    controller.is_connected = false;
+    controller.device->Disconnect();
     SignalStyleSetChangedEvent(IndexToNPad(npad_index));
+    WriteEmptyEntry(controller.shared_memory_entry);
 }
 
 void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index b0e2f84308..d805ccb97a 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -417,6 +417,8 @@ private:
 
         std::array<VibrationData, 2> vibration{};
         bool unintended_home_button_input_protection{};
+        bool is_connected{};
+        Core::HID::NpadType npad_type{Core::HID::NpadType::None};
 
         // Current pad state
         NPadGenericState npad_pad_state{};
@@ -435,6 +437,7 @@ private:
     void InitNewlyAddedController(std::size_t controller_idx);
     bool IsControllerSupported(Core::HID::NpadType controller) const;
     void RequestPadStateUpdate(u32 npad_id);
+    void WriteEmptyEntry(NpadInternalState& npad);
 
     std::atomic<u32> press_state{};
 
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index a8611f77f9..67faa8be8a 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -114,6 +114,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, Co
         player_tabs[i]->setLayout(new QHBoxLayout(player_tabs[i]));
         player_tabs[i]->layout()->addWidget(player_controllers[i]);
         connect(player_controllers[i], &ConfigureInputPlayer::Connected, [&, i](bool is_connected) {
+            // Ensures that the controllers are always connected in sequential order
             if (is_connected) {
                 for (std::size_t index = 0; index <= i; ++index) {
                     player_connected[index]->setChecked(is_connected);
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index ed9c3facf5..81310a5b3b 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -143,8 +143,26 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
       timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()),
       bottom_row(bottom_row), system{system_} {
 
-    emulated_controller = system_.HIDCore().GetEmulatedControllerByIndex(player_index);
-    emulated_controller->EnableConfiguration();
+    if (player_index == 0) {
+        auto* emulated_controller_p1 =
+            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+        auto* emulated_controller_hanheld =
+            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+        emulated_controller_p1->SaveCurrentConfig();
+        emulated_controller_p1->EnableConfiguration();
+        emulated_controller_hanheld->SaveCurrentConfig();
+        emulated_controller_hanheld->EnableConfiguration();
+        if (emulated_controller_hanheld->IsConnected(true)) {
+            emulated_controller_p1->Disconnect();
+            emulated_controller = emulated_controller_hanheld;
+        } else {
+            emulated_controller = emulated_controller_p1;
+        }
+    } else {
+        emulated_controller = system_.HIDCore().GetEmulatedControllerByIndex(player_index);
+        emulated_controller->SaveCurrentConfig();
+        emulated_controller->EnableConfiguration();
+    }
     ui->setupUi(this);
 
     setFocusPolicy(Qt::ClickFocus);
@@ -460,13 +478,36 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
     UpdateControllerEnabledButtons();
     UpdateControllerButtonNames();
     UpdateMotionButtons();
-    connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) {
+    connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this, player_index](int) {
         UpdateControllerAvailableButtons();
         UpdateControllerEnabledButtons();
         UpdateControllerButtonNames();
         UpdateMotionButtons();
-        emulated_controller->SetNpadType(
-            GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()));
+        const Core::HID::NpadType type = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
+
+        if (player_index == 0) {
+            auto* emulated_controller_p1 =
+                system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+            auto* emulated_controller_hanheld =
+                system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+            bool is_connected = emulated_controller->IsConnected(true);
+
+            emulated_controller_p1->SetNpadType(type);
+            emulated_controller_hanheld->SetNpadType(type);
+            if (is_connected) {
+                if (type == Core::HID::NpadType::Handheld) {
+                    emulated_controller_p1->Disconnect();
+                    emulated_controller_hanheld->Connect();
+                    emulated_controller = emulated_controller_hanheld;
+                } else {
+                    emulated_controller_hanheld->Disconnect();
+                    emulated_controller_p1->Connect();
+                    emulated_controller = emulated_controller_p1;
+                }
+            }
+            ui->controllerFrame->SetController(emulated_controller);
+        }
+        emulated_controller->SetNpadType(type);
     });
 
     connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
@@ -504,11 +545,35 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
 }
 
 ConfigureInputPlayer::~ConfigureInputPlayer() {
-    emulated_controller->DisableConfiguration();
+    if (player_index == 0) {
+        auto* emulated_controller_p1 =
+            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+        auto* emulated_controller_hanheld =
+            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+        emulated_controller_p1->DisableConfiguration();
+        emulated_controller_hanheld->DisableConfiguration();
+    } else {
+        emulated_controller->DisableConfiguration();
+    }
 };
 
 void ConfigureInputPlayer::ApplyConfiguration() {
+    if (player_index == 0) {
+        auto* emulated_controller_p1 =
+            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+        auto* emulated_controller_hanheld =
+            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+        emulated_controller_p1->DisableConfiguration();
+        emulated_controller_p1->SaveCurrentConfig();
+        emulated_controller_p1->EnableConfiguration();
+        emulated_controller_hanheld->DisableConfiguration();
+        emulated_controller_hanheld->SaveCurrentConfig();
+        emulated_controller_hanheld->EnableConfiguration();
+        return;
+    }
+    emulated_controller->DisableConfiguration();
     emulated_controller->SaveCurrentConfig();
+    emulated_controller->EnableConfiguration();
 }
 
 void ConfigureInputPlayer::showEvent(QShowEvent* event) {
@@ -535,9 +600,9 @@ void ConfigureInputPlayer::RetranslateUI() {
 void ConfigureInputPlayer::LoadConfiguration() {
     UpdateUI();
     UpdateInputDeviceCombobox();
-    const int comboBoxIndex = GetIndexFromControllerType(emulated_controller->GetNpadType());
+    const int comboBoxIndex = GetIndexFromControllerType(emulated_controller->GetNpadType(true));
     ui->comboControllerType->setCurrentIndex(comboBoxIndex);
-    ui->groupConnectedController->setChecked(emulated_controller->IsConnected());
+    ui->groupConnectedController->setChecked(emulated_controller->IsConnected(true));
 }
 
 void ConfigureInputPlayer::ConnectPlayer(bool connected) {
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 446b72e553..3b79b6076e 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -145,7 +145,7 @@ void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType typ
         needs_redraw = true;
         break;
     case Core::HID::ControllerTriggerType::Type:
-        controller_type = controller->GetNpadType();
+        controller_type = controller->GetNpadType(true);
         needs_redraw = true;
         break;
     case Core::HID::ControllerTriggerType::Color:

From 601ac43495904f3f7666d79a800a8b4eda5a8461 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Tue, 19 Oct 2021 00:12:24 -0500
Subject: [PATCH 40/88] core/hid: Only signal when needed

---
 src/common/input.h                            |   1 +
 src/core/hid/emulated_controller.cpp          | 263 +++++++++---------
 src/core/hid/emulated_controller.h            |   6 +-
 src/core/hid/input_converter.cpp              |   2 +-
 src/core/hle/service/hid/controllers/npad.cpp |   6 +-
 src/input_common/drivers/gc_adapter.cpp       |  75 ++++-
 src/input_common/drivers/gc_adapter.h         |   6 +-
 src/input_common/drivers/keyboard.cpp         |   2 +-
 src/input_common/drivers/sdl_driver.cpp       |  22 +-
 src/input_common/drivers/tas_input.cpp        |   2 +-
 .../configure_input_player_widget.cpp         |  12 +-
 11 files changed, 242 insertions(+), 155 deletions(-)

diff --git a/src/common/input.h b/src/common/input.h
index 3a28b77a7b..8871a9d078 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -30,6 +30,7 @@ enum class InputType {
 };
 
 enum class BatteryLevel {
+    None,
     Empty,
     Critical,
     Low,
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 7ef6ef1180..e102c9437e 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -94,7 +94,6 @@ void EmulatedController::ReloadFromSettings() {
 void EmulatedController::ReloadInput() {
     //LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type));
     // If you load any device here add the equivalent to the UnloadInput() function
-    const auto player_index = NpadIdTypeToIndex(npad_id_type);
     const auto left_side = button_params[Settings::NativeButton::ZL];
     const auto right_side = button_params[Settings::NativeButton::ZR];
 
@@ -337,120 +336,130 @@ void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t i
     if (index >= controller.button_values.size()) {
         return;
     }
-    std::lock_guard lock{mutex};
-    bool value_changed = false;
-    const auto new_status = TransformToButton(callback);
-    auto& current_status = controller.button_values[index];
-    current_status.toggle = new_status.toggle;
+    {
+        std::lock_guard lock{mutex};
+        bool value_changed = false;
+        const auto new_status = TransformToButton(callback);
+        auto& current_status = controller.button_values[index];
+        current_status.toggle = new_status.toggle;
 
-    // Update button status with current
-    if (!current_status.toggle) {
-        current_status.locked = false;
-        if (current_status.value != new_status.value) {
-            current_status.value = new_status.value;
-            value_changed = true;
-        }
-    } else {
-        // Toggle button and lock status
-        if (new_status.value && !current_status.locked) {
-            current_status.locked = true;
-            current_status.value = !current_status.value;
-            value_changed = true;
-        }
-
-        // Unlock button ready for next press
-        if (!new_status.value && current_status.locked) {
+        // Update button status with current
+        if (!current_status.toggle) {
             current_status.locked = false;
+            if (current_status.value != new_status.value) {
+                current_status.value = new_status.value;
+                value_changed = true;
+            }
+        } else {
+            // Toggle button and lock status
+            if (new_status.value && !current_status.locked) {
+                current_status.locked = true;
+                current_status.value = !current_status.value;
+                value_changed = true;
+            }
+
+            // Unlock button ready for next press
+            if (!new_status.value && current_status.locked) {
+                current_status.locked = false;
+            }
+        }
+
+        if (!value_changed) {
+            return;
+        }
+
+        if (is_configuring) {
+            controller.npad_button_state.raw = NpadButton::None;
+            controller.debug_pad_button_state.raw = 0;
+            TriggerOnChange(ControllerTriggerType::Button, false);
+            return;
+        }
+
+        switch (index) {
+        case Settings::NativeButton::A:
+            controller.npad_button_state.a.Assign(current_status.value);
+            controller.debug_pad_button_state.a.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::B:
+            controller.npad_button_state.b.Assign(current_status.value);
+            controller.debug_pad_button_state.b.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::X:
+            controller.npad_button_state.x.Assign(current_status.value);
+            controller.debug_pad_button_state.x.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::Y:
+            controller.npad_button_state.y.Assign(current_status.value);
+            controller.debug_pad_button_state.y.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::LStick:
+            controller.npad_button_state.stick_l.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::RStick:
+            controller.npad_button_state.stick_r.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::L:
+            controller.npad_button_state.l.Assign(current_status.value);
+            controller.debug_pad_button_state.l.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::R:
+            controller.npad_button_state.r.Assign(current_status.value);
+            controller.debug_pad_button_state.r.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::ZL:
+            controller.npad_button_state.zl.Assign(current_status.value);
+            controller.debug_pad_button_state.zl.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::ZR:
+            controller.npad_button_state.zr.Assign(current_status.value);
+            controller.debug_pad_button_state.zr.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::Plus:
+            controller.npad_button_state.plus.Assign(current_status.value);
+            controller.debug_pad_button_state.plus.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::Minus:
+            controller.npad_button_state.minus.Assign(current_status.value);
+            controller.debug_pad_button_state.minus.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::DLeft:
+            controller.npad_button_state.left.Assign(current_status.value);
+            controller.debug_pad_button_state.d_left.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::DUp:
+            controller.npad_button_state.up.Assign(current_status.value);
+            controller.debug_pad_button_state.d_up.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::DRight:
+            controller.npad_button_state.right.Assign(current_status.value);
+            controller.debug_pad_button_state.d_right.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::DDown:
+            controller.npad_button_state.down.Assign(current_status.value);
+            controller.debug_pad_button_state.d_down.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::SL:
+            controller.npad_button_state.left_sl.Assign(current_status.value);
+            controller.npad_button_state.right_sl.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::SR:
+            controller.npad_button_state.left_sr.Assign(current_status.value);
+            controller.npad_button_state.right_sr.Assign(current_status.value);
+            break;
+        case Settings::NativeButton::Home:
+        case Settings::NativeButton::Screenshot:
+            break;
         }
     }
-
-    if (!value_changed) {
-        return;
+    if (!is_connected) {
+        if (npad_id_type == NpadIdType::Player1 && npad_type != NpadType::Handheld) {
+            Connect();
+        }
+        if (npad_id_type == NpadIdType::Handheld && npad_type == NpadType::Handheld) {
+            Connect();
+        }
     }
-
-    if (is_configuring) {
-        controller.npad_button_state.raw = NpadButton::None;
-        controller.debug_pad_button_state.raw = 0;
-        TriggerOnChange(ControllerTriggerType::Button);
-        return;
-    }
-
-    switch (index) {
-    case Settings::NativeButton::A:
-        controller.npad_button_state.a.Assign(current_status.value);
-        controller.debug_pad_button_state.a.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::B:
-        controller.npad_button_state.b.Assign(current_status.value);
-        controller.debug_pad_button_state.b.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::X:
-        controller.npad_button_state.x.Assign(current_status.value);
-        controller.debug_pad_button_state.x.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::Y:
-        controller.npad_button_state.y.Assign(current_status.value);
-        controller.debug_pad_button_state.y.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::LStick:
-        controller.npad_button_state.stick_l.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::RStick:
-        controller.npad_button_state.stick_r.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::L:
-        controller.npad_button_state.l.Assign(current_status.value);
-        controller.debug_pad_button_state.l.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::R:
-        controller.npad_button_state.r.Assign(current_status.value);
-        controller.debug_pad_button_state.r.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::ZL:
-        controller.npad_button_state.zl.Assign(current_status.value);
-        controller.debug_pad_button_state.zl.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::ZR:
-        controller.npad_button_state.zr.Assign(current_status.value);
-        controller.debug_pad_button_state.zr.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::Plus:
-        controller.npad_button_state.plus.Assign(current_status.value);
-        controller.debug_pad_button_state.plus.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::Minus:
-        controller.npad_button_state.minus.Assign(current_status.value);
-        controller.debug_pad_button_state.minus.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::DLeft:
-        controller.npad_button_state.left.Assign(current_status.value);
-        controller.debug_pad_button_state.d_left.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::DUp:
-        controller.npad_button_state.up.Assign(current_status.value);
-        controller.debug_pad_button_state.d_up.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::DRight:
-        controller.npad_button_state.right.Assign(current_status.value);
-        controller.debug_pad_button_state.d_right.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::DDown:
-        controller.npad_button_state.down.Assign(current_status.value);
-        controller.debug_pad_button_state.d_down.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::SL:
-        controller.npad_button_state.left_sl.Assign(current_status.value);
-        controller.npad_button_state.right_sl.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::SR:
-        controller.npad_button_state.left_sr.Assign(current_status.value);
-        controller.npad_button_state.right_sr.Assign(current_status.value);
-        break;
-    case Settings::NativeButton::Home:
-    case Settings::NativeButton::Screenshot:
-        break;
-    }
-    TriggerOnChange(ControllerTriggerType::Button);
+    TriggerOnChange(ControllerTriggerType::Button, true);
 }
 
 void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t index) {
@@ -463,7 +472,7 @@ void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t in
     if (is_configuring) {
         controller.analog_stick_state.left = {};
         controller.analog_stick_state.right = {};
-        TriggerOnChange(ControllerTriggerType::Stick);
+        TriggerOnChange(ControllerTriggerType::Stick, false);
         return;
     }
 
@@ -489,7 +498,7 @@ void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t in
         break;
     }
 
-    TriggerOnChange(ControllerTriggerType::Stick);
+    TriggerOnChange(ControllerTriggerType::Stick, true);
 }
 
 void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t index) {
@@ -502,7 +511,7 @@ void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t
     if (is_configuring) {
         controller.gc_trigger_state.left = 0;
         controller.gc_trigger_state.right = 0;
-        TriggerOnChange(ControllerTriggerType::Trigger);
+        TriggerOnChange(ControllerTriggerType::Trigger, false);
         return;
     }
 
@@ -520,7 +529,7 @@ void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t
         break;
     }
 
-    TriggerOnChange(ControllerTriggerType::Trigger);
+    TriggerOnChange(ControllerTriggerType::Trigger, true);
 }
 
 void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t index) {
@@ -546,7 +555,7 @@ void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t i
     emulated.UpdateOrientation(raw_status.delta_timestamp);
 
     if (is_configuring) {
-        TriggerOnChange(ControllerTriggerType::Motion);
+        TriggerOnChange(ControllerTriggerType::Motion, false);
         return;
     }
 
@@ -557,7 +566,7 @@ void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t i
     motion.orientation = emulated.GetOrientation();
     motion.is_at_rest = emulated.IsMoving(motion_sensitivity);
 
-    TriggerOnChange(ControllerTriggerType::Motion);
+    TriggerOnChange(ControllerTriggerType::Motion, true);
 }
 
 void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t index) {
@@ -568,7 +577,7 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t
     controller.battery_values[index] = TransformToBattery(callback);
 
     if (is_configuring) {
-        TriggerOnChange(ControllerTriggerType::Battery);
+        TriggerOnChange(ControllerTriggerType::Battery, false);
         return;
     }
 
@@ -593,6 +602,7 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t
     case Input::BatteryLevel::Empty:
         battery_level = 0;
         break;
+    case Input::BatteryLevel::None:
     case Input::BatteryLevel::Full:
     default:
         is_powered = true;
@@ -623,7 +633,7 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t
         };
         break;
     }
-    TriggerOnChange(ControllerTriggerType::Battery);
+    TriggerOnChange(ControllerTriggerType::Battery, true);
 }
 
 bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
@@ -677,7 +687,7 @@ void EmulatedController::Connect() {
         std::lock_guard lock{mutex};
         if (is_configuring) {
             temporary_is_connected = true;
-            TriggerOnChange(ControllerTriggerType::Connected);
+            TriggerOnChange(ControllerTriggerType::Connected,false);
             return;
         }
 
@@ -687,7 +697,7 @@ void EmulatedController::Connect() {
         is_connected = true;
     }
     LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type));
-    TriggerOnChange(ControllerTriggerType::Connected);
+    TriggerOnChange(ControllerTriggerType::Connected,true);
 }
 
 void EmulatedController::Disconnect() {
@@ -697,7 +707,7 @@ void EmulatedController::Disconnect() {
             temporary_is_connected = false;
             LOG_ERROR(Service_HID, "Disconnected temporal controller {}",
                       NpadIdTypeToIndex(npad_id_type));
-            TriggerOnChange(ControllerTriggerType::Disconnected);
+            TriggerOnChange(ControllerTriggerType::Disconnected,false);
             return;
         }
 
@@ -707,7 +717,7 @@ void EmulatedController::Disconnect() {
         is_connected = false;
     }
     LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type));
-    TriggerOnChange(ControllerTriggerType::Disconnected);
+    TriggerOnChange(ControllerTriggerType::Disconnected,true);
 }
 
 bool EmulatedController::IsConnected(bool temporary) const {
@@ -741,7 +751,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) {
                 return;
             }
             temporary_npad_type = npad_type_;
-            TriggerOnChange(ControllerTriggerType::Type);
+            TriggerOnChange(ControllerTriggerType::Type,false);
             return;
         }
 
@@ -754,7 +764,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) {
         }
         npad_type = npad_type_;
     }
-    TriggerOnChange(ControllerTriggerType::Type);
+    TriggerOnChange(ControllerTriggerType::Type,true);
 }
 
 LedPattern EmulatedController::GetLedPattern() const {
@@ -844,9 +854,12 @@ BatteryLevelState EmulatedController::GetBattery() const {
     return controller.battery_state;
 }
 
-void EmulatedController::TriggerOnChange(ControllerTriggerType type) {
+void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_service_update) {
     for (const std::pair<int, ControllerUpdateCallback> poller_pair : callback_list) {
         const ControllerUpdateCallback& poller = poller_pair.second;
+        if (!is_service_update && poller.is_service) {
+            continue;
+        }
         if (poller.on_change) {
             poller.on_change(type);
         }
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 6a6dc18927..3a0b20cf81 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -113,6 +113,7 @@ enum class ControllerTriggerType {
 
 struct ControllerUpdateCallback {
     std::function<void(ControllerTriggerType)> on_change;
+    bool is_service;
 };
 
 class EmulatedController {
@@ -325,9 +326,10 @@ private:
 
     /**
      * Triggers a callback that something has changed on the controller status
-     * @param Input type of the event to trigger
+     * @param type: Input type of the event to trigger
+     * @param is_service_update: indicates if this event should be sended to only services
      */
-    void TriggerOnChange(ControllerTriggerType type);
+    void TriggerOnChange(ControllerTriggerType type, bool  is_service_update);
 
     NpadIdType npad_id_type;
     NpadType npad_type{NpadType::None};
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index 5834622e92..128a48ec91 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -10,7 +10,7 @@
 namespace Core::HID {
 
 Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback) {
-    Input::BatteryStatus battery{};
+    Input::BatteryStatus battery{Input::BatteryStatus::None};
     switch (callback.type) {
     case Input::InputType::Analog:
     case Input::InputType::Trigger: {
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 144abab653..6b9d6d11c3 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -104,7 +104,10 @@ Controller_NPad::Controller_NPad(Core::System& system_,
         controller.vibration[0].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
         controller.vibration[1].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
         Core::HID::ControllerUpdateCallback engine_callback{
-            [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }};
+            .on_change = [this,
+                          i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
+            .is_service = true,
+        };
         controller.callback_key = controller.device->SetCallback(engine_callback);
     }
 }
@@ -283,7 +286,6 @@ void Controller_NPad::OnInit() {
 
     // Prefill controller buffers
     for (auto& controller : controller_data) {
-        NPadGenericState dummy_pad_state{};
         auto& npad = controller.shared_memory_entry;
         for (std::size_t i = 0; i < 19; ++i) {
             WriteEmptyEntry(npad);
diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp
index 4a56abb997..4fb6ab5af8 100644
--- a/src/input_common/drivers/gc_adapter.cpp
+++ b/src/input_common/drivers/gc_adapter.cpp
@@ -150,7 +150,10 @@ void GCAdapter::UpdatePadType(std::size_t port, ControllerTypes pad_type) {
         return;
     }
     // Device changed reset device and set new type
-    pads[port] = {};
+    pads[port].axis_origin = {};
+    pads[port].reset_origin_counter = {};
+    pads[port].enable_vibration = {};
+    pads[port].rumble_amplitude = {};
     pads[port].type = pad_type;
 }
 
@@ -396,12 +399,11 @@ std::vector<Common::ParamPackage> GCAdapter::GetInputDevices() const {
         if (!DeviceConnected(port)) {
             continue;
         }
-        const std::string name = fmt::format("Gamecube Controller {}", port + 1);
-        devices.emplace_back(Common::ParamPackage{
-            {"engine", "gcpad"},
-            {"display", std::move(name)},
-            {"port", std::to_string(port)},
-        });
+        Common::ParamPackage identifier{};
+        identifier.Set("engine", GetEngineName());
+        identifier.Set("display", fmt::format("Gamecube Controller {}", port + 1));
+        identifier.Set("port", static_cast<int>(port));
+        devices.emplace_back(identifier);
     }
     return devices;
 }
@@ -431,7 +433,8 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p
 
     ButtonMapping mapping{};
     for (const auto& [switch_button, gcadapter_button] : switch_to_gcadapter_button) {
-        Common::ParamPackage button_params({{"engine", "gcpad"}});
+        Common::ParamPackage button_params{};
+        button_params.Set("engine", GetEngineName());
         button_params.Set("port", params.Get("port", 0));
         button_params.Set("button", static_cast<int>(gcadapter_button));
         mapping.insert_or_assign(switch_button, std::move(button_params));
@@ -444,7 +447,8 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p
             {Settings::NativeButton::ZR, PadButton::TriggerR, PadAxes::TriggerRight},
         };
     for (const auto& [switch_button, gcadapter_buton, gcadapter_axis] : switch_to_gcadapter_axis) {
-        Common::ParamPackage button_params({{"engine", "gcpad"}});
+        Common::ParamPackage button_params{};
+        button_params.Set("engine", GetEngineName());
         button_params.Set("port", params.Get("port", 0));
         button_params.Set("button", static_cast<s32>(gcadapter_buton));
         button_params.Set("axis", static_cast<s32>(gcadapter_axis));
@@ -463,13 +467,13 @@ AnalogMapping GCAdapter::GetAnalogMappingForDevice(const Common::ParamPackage& p
 
     AnalogMapping mapping = {};
     Common::ParamPackage left_analog_params;
-    left_analog_params.Set("engine", "gcpad");
+    left_analog_params.Set("engine", GetEngineName());
     left_analog_params.Set("port", params.Get("port", 0));
     left_analog_params.Set("axis_x", static_cast<int>(PadAxes::StickX));
     left_analog_params.Set("axis_y", static_cast<int>(PadAxes::StickY));
     mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params));
     Common::ParamPackage right_analog_params;
-    right_analog_params.Set("engine", "gcpad");
+    right_analog_params.Set("engine", GetEngineName());
     right_analog_params.Set("port", params.Get("port", 0));
     right_analog_params.Set("axis_x", static_cast<int>(PadAxes::SubstickX));
     right_analog_params.Set("axis_y", static_cast<int>(PadAxes::SubstickY));
@@ -477,9 +481,56 @@ AnalogMapping GCAdapter::GetAnalogMappingForDevice(const Common::ParamPackage& p
     return mapping;
 }
 
+std::string GCAdapter::GetUIButtonName(const Common::ParamPackage& params) const {
+    PadButton button = static_cast<PadButton>(params.Get("button", 0));
+    switch (button) {
+    case PadButton::ButtonLeft:
+        return "left";
+        break;
+    case PadButton::ButtonRight:
+        return "right";
+        break;
+    case PadButton::ButtonDown:
+        return "down";
+        break;
+    case PadButton::ButtonUp:
+        return "up";
+        break;
+    case PadButton::TriggerZ:
+        return "Z";
+        break;
+    case PadButton::TriggerR:
+        return "R";
+        break;
+    case PadButton::TriggerL:
+        return "L";
+        break;
+    case PadButton::ButtonA:
+        return "A";
+        break;
+    case PadButton::ButtonB:
+        return "B";
+        break;
+    case PadButton::ButtonX:
+        return "X";
+        break;
+    case PadButton::ButtonY:
+        return "Y";
+        break;
+    case PadButton::ButtonStart:
+        return "start";
+        break;
+    default:
+        return "Unkown GC";
+    }
+}
+
 std::string GCAdapter::GetUIName(const Common::ParamPackage& params) const {
     if (params.Has("button")) {
-        return fmt::format("Button {}", params.Get("button", 0));
+        return fmt::format("Button {}", GetUIButtonName(params));
+    }
+    if (params.Has("axis")) {
+        return fmt::format("Axis {}", params.Get("axis",0));
     }
 
     return "Bad GC Adapter";
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h
index dd0e4aa1d5..b82e4803dd 100644
--- a/src/input_common/drivers/gc_adapter.h
+++ b/src/input_common/drivers/gc_adapter.h
@@ -105,8 +105,12 @@ private:
     void Reset();
 
     void UpdateVibrations();
-    // Updates vibration state of all controllers
+
+    /// Updates vibration state of all controllers
     void SendVibrations();
+
+    std::string GetUIButtonName(const Common::ParamPackage& params) const;
+
     std::unique_ptr<LibUSBDeviceHandle> usb_adapter_handle;
     std::array<GCController, 4> pads;
 
diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp
index b00a4b8d95..85a781a304 100644
--- a/src/input_common/drivers/keyboard.cpp
+++ b/src/input_common/drivers/keyboard.cpp
@@ -26,7 +26,7 @@ void Keyboard::ReleaseAllKeys() {
 std::vector<Common::ParamPackage> Keyboard::GetInputDevices() const {
     std::vector<Common::ParamPackage> devices;
     devices.emplace_back(Common::ParamPackage{
-        {"engine", "keyboard"},
+        {"engine", GetEngineName()},
         {"display", "Keyboard Only"},
     });
     return devices;
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index f7f03c5f23..cee2d965fe 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -305,6 +305,7 @@ void SDLDriver::InitJoystick(int joystick_index) {
     if (joystick_map.find(guid) == joystick_map.end()) {
         auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller);
         PreSetController(joystick->GetPadIdentifier());
+        SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
         joystick_map[guid].emplace_back(std::move(joystick));
         return;
     }
@@ -322,6 +323,7 @@ void SDLDriver::InitJoystick(int joystick_index) {
     const int port = static_cast<int>(joystick_guid_list.size());
     auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller);
     PreSetController(joystick->GetPadIdentifier());
+    SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
     joystick_guid_list.emplace_back(std::move(joystick));
 }
 
@@ -472,7 +474,7 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
             const std::string name =
                 fmt::format("{} {}", joystick->GetControllerName(), joystick->GetPort());
             devices.emplace_back(Common::ParamPackage{
-                {"engine", "sdl"},
+                {"engine", GetEngineName()},
                 {"display", std::move(name)},
                 {"guid", joystick->GetGUID()},
                 {"port", std::to_string(joystick->GetPort())},
@@ -495,7 +497,7 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
                 const std::string name =
                     fmt::format("{} {}", "Nintendo Dual Joy-Con", joystick->GetPort());
                 devices.emplace_back(Common::ParamPackage{
-                    {"engine", "sdl"},
+                    {"engine", GetEngineName()},
                     {"display", std::move(name)},
                     {"guid", joystick->GetGUID()},
                     {"guid2", joystick2->GetGUID()},
@@ -527,7 +529,8 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier,
 }
 Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,
                                                                  s32 axis, float value) const {
-    Common::ParamPackage params({{"engine", "sdl"}});
+    Common::ParamPackage params{};
+    params.Set("engine", GetEngineName());
     params.Set("port", port);
     params.Set("guid", std::move(guid));
     params.Set("axis", axis);
@@ -538,7 +541,8 @@ Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::
 
 Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, std::string guid,
                                                                  s32 button) const {
-    Common::ParamPackage params({{"engine", "sdl"}});
+    Common::ParamPackage params{};
+    params.Set("engine", GetEngineName());
     params.Set("port", port);
     params.Set("guid", std::move(guid));
     params.Set("button", button);
@@ -547,8 +551,8 @@ Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, std::
 
 Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, std::string guid, s32 hat,
                                                               u8 value) const {
-    Common::ParamPackage params({{"engine", "sdl"}});
-
+    Common::ParamPackage params{};
+    params.Set("engine", GetEngineName());
     params.Set("port", port);
     params.Set("guid", std::move(guid));
     params.Set("hat", hat);
@@ -557,7 +561,9 @@ Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, std::str
 }
 
 Common::ParamPackage SDLDriver::BuildMotionParam(int port, std::string guid) const {
-    Common::ParamPackage params({{"engine", "sdl"}, {"motion", "0"}});
+    Common::ParamPackage params{};
+    params.Set("engine", GetEngineName());
+    params.Set("motion", 0);
     params.Set("port", port);
     params.Set("guid", std::move(guid));
     return params;
@@ -583,7 +589,7 @@ Common::ParamPackage SDLDriver::BuildParamPackageForAnalog(PadIdentifier identif
                                                            int axis_y, float offset_x,
                                                            float offset_y) const {
     Common::ParamPackage params;
-    params.Set("engine", "sdl");
+    params.Set("engine", GetEngineName());
     params.Set("port", static_cast<int>(identifier.port));
     params.Set("guid", identifier.guid.Format());
     params.Set("axis_x", axis_x);
diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp
index 5e2101b27d..7e7a1d58f9 100644
--- a/src/input_common/drivers/tas_input.cpp
+++ b/src/input_common/drivers/tas_input.cpp
@@ -127,7 +127,7 @@ void Tas::WriteTasFile(std::u8string file_name) {
     std::string output_text;
     for (size_t frame = 0; frame < record_commands.size(); frame++) {
         const TASCommand& line = record_commands[frame];
-        output_text += fmt::format("{} {} {} {} {}\n", frame, WriteCommandButtons(line.buttons),
+        output_text += fmt::format("{} {} {} {}\n", frame, WriteCommandButtons(line.buttons),
                                    WriteCommandAxis(line.l_axis), WriteCommandAxis(line.r_axis));
     }
     const auto bytes_written = Common::FS::WriteStringToFile(
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 3b79b6076e..93f7eddc92 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -27,7 +27,9 @@ void PlayerControlPreview::SetController(Core::HID::EmulatedController* controll
     is_controller_set = true;
     controller = controller_;
     Core::HID::ControllerUpdateCallback engine_callback{
-        [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); }};
+        .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); },
+        .is_service = false,
+    };
     callback_key = controller->SetCallback(engine_callback);
     ControllerUpdate(Core::HID::ControllerTriggerType::All);
 }
@@ -810,7 +812,7 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
     DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(-30, -165), battery_values[0]);
+    DrawBattery(p, center + QPoint(-30, -160), battery_values[0]);
 }
 
 void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
@@ -2655,6 +2657,9 @@ void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center,
 }
 
 void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::BatteryLevel battery) {
+    if (battery == Input::BatteryLevel::None) {
+        return;
+    }
     p.setPen(colors.outline);
     p.setBrush(colors.transparent);
     p.drawRect(center.x(), center.y(), 56, 20);
@@ -2669,6 +2674,7 @@ void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::Batte
         p.drawRect(center.x() + 42, center.y(), 14, 20);
         p.drawRect(center.x() + 28, center.y(), 14, 20);
         p.drawRect(center.x() + 14, center.y(), 14, 20);
+        p.drawRect(center.x(), center.y(), 14, 20);
         break;
     case Input::BatteryLevel::Medium:
         p.drawRect(center.x() + 28, center.y(), 14, 20);
@@ -2685,6 +2691,8 @@ void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::Batte
     case Input::BatteryLevel::Empty:
         p.drawRect(center.x(), center.y(), 5, 20);
         break;
+    default:
+        break;
     }
 }
 

From c3ff0a8ac0d1c3f9c0791b5263dae53c06ad6048 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Wed, 20 Oct 2021 14:41:56 -0500
Subject: [PATCH 41/88] core/hid: Fix rumble too strong at 1%

---
 src/common/input.h                      |  7 +++++
 src/core/hid/emulated_controller.cpp    | 34 ++++++++++++++++---------
 src/input_common/drivers/sdl_driver.cpp | 20 ++++++++++++++-
 3 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/src/common/input.h b/src/common/input.h
index 8871a9d078..cdacd46897 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -60,6 +60,12 @@ enum class PollingError {
     Unknown,
 };
 
+// Hint for amplification curve to be used
+enum class VibrationAmplificationType {
+    Linear,
+    Exponential,
+};
+
 struct AnalogProperties {
     float deadzone{};
     float range{1.0f};
@@ -126,6 +132,7 @@ struct VibrationStatus {
     f32 low_frequency{};
     f32 high_amplitude{};
     f32 high_frequency{};
+    VibrationAmplificationType type;
 };
 
 struct LedStatus {
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index e102c9437e..7b0c4a49b1 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -54,7 +54,6 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type
 }
 
 void EmulatedController::ReloadFromSettings() {
-    //LOG_ERROR(Service_HID, "reload config from settings {}", NpadIdTypeToIndex(npad_id_type));
     const auto player_index = NpadIdTypeToIndex(npad_id_type);
     const auto& player = Settings::values.players.GetValue()[player_index];
 
@@ -92,7 +91,7 @@ void EmulatedController::ReloadFromSettings() {
 }
 
 void EmulatedController::ReloadInput() {
-    //LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type));
+    // LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type));
     // If you load any device here add the equivalent to the UnloadInput() function
     const auto left_side = button_params[Settings::NativeButton::ZL];
     const auto right_side = button_params[Settings::NativeButton::ZR];
@@ -640,12 +639,22 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
     if (!output_devices[device_index]) {
         return false;
     }
+    const auto player_index = NpadIdTypeToIndex(npad_id_type);
+    const auto& player = Settings::values.players.GetValue()[player_index];
+    const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f;
+
+    // Exponential amplification is too strong at low amplitudes. Switch to a linear
+    // amplification if strength is set below 0.7f
+    const Input::VibrationAmplificationType type =
+        strength > 0.7f ? Input::VibrationAmplificationType::Exponential
+                        : Input::VibrationAmplificationType::Linear;
 
     const Input::VibrationStatus status = {
-        .low_amplitude = vibration.high_amplitude,
-        .low_frequency = vibration.high_amplitude,
-        .high_amplitude = vibration.high_amplitude,
-        .high_frequency = vibration.high_amplitude,
+        .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f),
+        .low_frequency = vibration.low_frequency,
+        .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f),
+        .high_frequency = vibration.high_frequency,
+        .type = type,
     };
     return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None;
 }
@@ -661,6 +670,7 @@ bool EmulatedController::TestVibration(std::size_t device_index) {
         .low_frequency = 160.0f,
         .high_amplitude = 0.001f,
         .high_frequency = 320.0f,
+        .type = Input::VibrationAmplificationType::Linear,
     };
     return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None;
 }
@@ -687,7 +697,7 @@ void EmulatedController::Connect() {
         std::lock_guard lock{mutex};
         if (is_configuring) {
             temporary_is_connected = true;
-            TriggerOnChange(ControllerTriggerType::Connected,false);
+            TriggerOnChange(ControllerTriggerType::Connected, false);
             return;
         }
 
@@ -697,7 +707,7 @@ void EmulatedController::Connect() {
         is_connected = true;
     }
     LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type));
-    TriggerOnChange(ControllerTriggerType::Connected,true);
+    TriggerOnChange(ControllerTriggerType::Connected, true);
 }
 
 void EmulatedController::Disconnect() {
@@ -707,7 +717,7 @@ void EmulatedController::Disconnect() {
             temporary_is_connected = false;
             LOG_ERROR(Service_HID, "Disconnected temporal controller {}",
                       NpadIdTypeToIndex(npad_id_type));
-            TriggerOnChange(ControllerTriggerType::Disconnected,false);
+            TriggerOnChange(ControllerTriggerType::Disconnected, false);
             return;
         }
 
@@ -717,7 +727,7 @@ void EmulatedController::Disconnect() {
         is_connected = false;
     }
     LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type));
-    TriggerOnChange(ControllerTriggerType::Disconnected,true);
+    TriggerOnChange(ControllerTriggerType::Disconnected, true);
 }
 
 bool EmulatedController::IsConnected(bool temporary) const {
@@ -751,7 +761,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) {
                 return;
             }
             temporary_npad_type = npad_type_;
-            TriggerOnChange(ControllerTriggerType::Type,false);
+            TriggerOnChange(ControllerTriggerType::Type, false);
             return;
         }
 
@@ -764,7 +774,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) {
         }
         npad_type = npad_type_;
     }
-    TriggerOnChange(ControllerTriggerType::Type,true);
+    TriggerOnChange(ControllerTriggerType::Type, true);
 }
 
 LedPattern EmulatedController::GetLedPattern() const {
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index cee2d965fe..d56351815c 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -107,6 +107,14 @@ public:
 
         return false;
     }
+
+    bool HasHDRumble() const {
+        if (sdl_controller) {
+            return (SDL_GameControllerGetType(sdl_controller.get()) ==
+                    SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO);
+        }
+        return false;
+    }
     /**
      * The Pad identifier of the joystick
      */
@@ -515,16 +523,26 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier,
     const auto process_amplitude = [](f32 amplitude) {
         return (amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF;
     };
-    const Input::VibrationStatus new_vibration{
+    const Input::VibrationStatus exponential_vibration{
         .low_amplitude = process_amplitude(vibration.low_amplitude),
         .low_frequency = vibration.low_frequency,
         .high_amplitude = process_amplitude(vibration.high_amplitude),
         .high_frequency = vibration.high_frequency,
+        .type = Input::VibrationAmplificationType::Exponential,
     };
 
+    Input::VibrationStatus new_vibration{};
+
+    if (vibration.type == Input::VibrationAmplificationType::Linear || joystick->HasHDRumble()) {
+        new_vibration = vibration;
+    } else {
+        new_vibration = exponential_vibration;
+    }
+
     if (!joystick->RumblePlay(new_vibration)) {
         return Input::VibrationError::Unknown;
     }
+
     return Input::VibrationError::None;
 }
 Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,

From af55dd193533be577d0a3d01f93a4a3a2c27cd5d Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Wed, 20 Oct 2021 17:53:14 -0500
Subject: [PATCH 42/88] configuration: Migrate controller settings to emulated
 controller

---
 src/core/hid/emulated_controller.cpp          |   1 -
 src/core/hid/emulated_controller.h            |   2 +-
 src/core/hid/hid_core.cpp                     |  21 +++
 src/core/hid/hid_core.h                       |  10 +-
 .../service/am/applets/applet_controller.cpp  |  12 +-
 src/input_common/main.cpp                     |  10 ++
 src/yuzu/applets/qt_controller.cpp            | 143 +++++++-----------
 src/yuzu/applets/qt_controller.h              |  14 +-
 src/yuzu/applets/qt_software_keyboard.cpp     |  21 +--
 src/yuzu/configuration/configure_input.cpp    |  17 ++-
 .../configure_input_player_widget.cpp         |   4 +-
 src/yuzu/main.cpp                             |  11 +-
 12 files changed, 140 insertions(+), 126 deletions(-)

diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 7b0c4a49b1..6622603277 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -91,7 +91,6 @@ void EmulatedController::ReloadFromSettings() {
 }
 
 void EmulatedController::ReloadInput() {
-    // LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type));
     // If you load any device here add the equivalent to the UnloadInput() function
     const auto left_side = button_params[Settings::NativeButton::ZL];
     const auto right_side = button_params[Settings::NativeButton::ZR];
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 3a0b20cf81..f3ee707264 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -329,7 +329,7 @@ private:
      * @param type: Input type of the event to trigger
      * @param is_service_update: indicates if this event should be sended to only services
      */
-    void TriggerOnChange(ControllerTriggerType type, bool  is_service_update);
+    void TriggerOnChange(ControllerTriggerType type, bool is_service_update);
 
     NpadIdType npad_id_type;
     NpadType npad_type{NpadType::None};
diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp
index ee76db1106..bd17081bdf 100644
--- a/src/core/hid/hid_core.cpp
+++ b/src/core/hid/hid_core.cpp
@@ -111,6 +111,27 @@ NpadStyleTag HIDCore::GetSupportedStyleTag() const {
     return supported_style_tag;
 }
 
+s8 HIDCore::GetPlayerCount() const {
+    s8 active_players = 0;
+    for (std::size_t player_index = 0; player_index < 8; player_index++) {
+        const auto* controller = GetEmulatedControllerByIndex(player_index);
+        if (controller->IsConnected()) {
+            active_players++;
+        }
+    }
+    return active_players;
+}
+
+NpadIdType HIDCore::GetFirstNpadId() const {
+    for (std::size_t player_index = 0; player_index < 10; player_index++) {
+        const auto* controller = GetEmulatedControllerByIndex(player_index);
+        if (controller->IsConnected()) {
+            return controller->GetNpadIdType();
+        }
+    }
+    return NpadIdType::Player1;
+}
+
 void HIDCore::ReloadInputDevices() {
     player_1->ReloadFromSettings();
     player_2->ReloadFromSettings();
diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h
index f11f48b617..196466a72c 100644
--- a/src/core/hid/hid_core.h
+++ b/src/core/hid/hid_core.h
@@ -35,10 +35,16 @@ public:
     void SetSupportedStyleTag(NpadStyleTag style_tag);
     NpadStyleTag GetSupportedStyleTag() const;
 
-    // Reloads all input devices from settings
+    /// Counts the connected players from P1-P8
+    s8 GetPlayerCount() const;
+
+    /// Returns the first connected npad id
+    NpadIdType GetFirstNpadId() const;
+
+    /// Reloads all input devices from settings
     void ReloadInputDevices();
 
-    // Removes all callbacks from input common
+    /// Removes all callbacks from input common
     void UnloadInputDevices();
 
 private:
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index c1b6cd1266..658265a004 100644
--- a/src/core/hle/service/am/applets/applet_controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -243,19 +243,11 @@ void Controller::Execute() {
 void Controller::ConfigurationComplete() {
     ControllerSupportResultInfo result_info{};
 
-    const auto& players = Settings::values.players.GetValue();
-
     // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters.
     // Otherwise, only count connected players from P1-P8.
-    result_info.player_count =
-        is_single_mode
-            ? 1
-            : static_cast<s8>(std::count_if(players.begin(), players.end() - 2,
-                                            [](const auto& player) { return player.connected; }));
+    result_info.player_count = is_single_mode ? 1 : system.HIDCore().GetPlayerCount();
 
-    result_info.selected_id = HID::Controller_NPad::IndexToNPad(std::distance(
-        players.begin(), std::find_if(players.begin(), players.end(),
-                                      [](const auto& player) { return player.connected; })));
+    result_info.selected_id = static_cast<u32>(system.HIDCore().GetFirstNpadId());
 
     result_info.result = 0;
 
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 7807dd38ff..b048783c91 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -32,12 +32,17 @@ struct InputSubsystem::Impl {
         keyboard = std::make_shared<Keyboard>("keyboard");
         keyboard->SetMappingCallback(mapping_callback);
         keyboard_factory = std::make_shared<InputFactory>(keyboard);
+        keyboard_output_factory = std::make_shared<OutputFactory>(keyboard);
         Input::RegisterFactory<Input::InputDevice>(keyboard->GetEngineName(), keyboard_factory);
+        Input::RegisterFactory<Input::OutputDevice>(keyboard->GetEngineName(),
+                                                    keyboard_output_factory);
 
         mouse = std::make_shared<Mouse>("mouse");
         mouse->SetMappingCallback(mapping_callback);
         mouse_factory = std::make_shared<InputFactory>(mouse);
+        mouse_output_factory = std::make_shared<OutputFactory>(mouse);
         Input::RegisterFactory<Input::InputDevice>(mouse->GetEngineName(), mouse_factory);
+        Input::RegisterFactory<Input::OutputDevice>(mouse->GetEngineName(), mouse_output_factory);
 
         touch_screen = std::make_shared<TouchScreen>("touch");
         touch_screen_factory = std::make_shared<InputFactory>(touch_screen);
@@ -61,7 +66,9 @@ struct InputSubsystem::Impl {
         tas_input = std::make_shared<TasInput::Tas>("tas");
         tas_input->SetMappingCallback(mapping_callback);
         tas_input_factory = std::make_shared<InputFactory>(tas_input);
+        tas_output_factory = std::make_shared<OutputFactory>(tas_input);
         Input::RegisterFactory<Input::InputDevice>(tas_input->GetEngineName(), tas_input_factory);
+        Input::RegisterFactory<Input::OutputDevice>(tas_input->GetEngineName(), tas_output_factory);
 
 #ifdef HAVE_SDL2
         sdl = std::make_shared<SDLDriver>("sdl");
@@ -268,7 +275,10 @@ struct InputSubsystem::Impl {
     std::shared_ptr<InputFactory> udp_client_factory;
     std::shared_ptr<InputFactory> tas_input_factory;
 
+    std::shared_ptr<OutputFactory> keyboard_output_factory;
+    std::shared_ptr<OutputFactory> mouse_output_factory;
     std::shared_ptr<OutputFactory> gcadapter_output_factory;
+    std::shared_ptr<OutputFactory> tas_output_factory;
 
 #ifdef HAVE_SDL2
     std::shared_ptr<SDLDriver> sdl;
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 2cd5ed7185..32cb5b5fff 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -9,6 +9,8 @@
 #include "common/param_package.h"
 #include "common/string_util.h"
 #include "core/core.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/hid_types.h"
 #include "core/hle/lock.h"
 #include "core/hle/service/hid/controllers/npad.h"
 #include "core/hle/service/hid/hid.h"
@@ -26,48 +28,31 @@ namespace {
 
 constexpr std::size_t HANDHELD_INDEX = 8;
 
-constexpr std::array<std::array<bool, 4>, 8> led_patterns{{
-    {true, false, false, false},
-    {true, true, false, false},
-    {true, true, true, false},
-    {true, true, true, true},
-    {true, false, false, true},
-    {true, false, true, false},
-    {true, false, true, true},
-    {false, true, true, false},
-}};
-
-void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index,
-                      bool connected, Core::System& system) {
-    if (!system.IsPoweredOn()) {
-        return;
+void UpdateController(Core::HID::EmulatedController* controller, Core::HID::NpadType controller_type, bool connected) {
+    if (controller->IsConnected()) {
+        controller->Disconnect();
+    }
+    controller->SetNpadType(controller_type);
+    if (connected) {
+        controller->Connect();
     }
-
-    auto& npad =
-        system.ServiceManager()
-            .GetService<Service::HID::Hid>("hid")
-            ->GetAppletResource()
-            ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
-
-    npad.UpdateControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(controller_type),
-                            npad_index, connected);
 }
 
 // Returns true if the given controller type is compatible with the given parameters.
-bool IsControllerCompatible(Settings::ControllerType controller_type,
+bool IsControllerCompatible(Core::HID::NpadType controller_type,
                             Core::Frontend::ControllerParameters parameters) {
     switch (controller_type) {
-    case Settings::ControllerType::ProController:
+    case Core::HID::NpadType::ProController:
         return parameters.allow_pro_controller;
-    case Settings::ControllerType::DualJoyconDetached:
+    case Core::HID::NpadType::JoyconDual:
         return parameters.allow_dual_joycons;
-    case Settings::ControllerType::LeftJoycon:
+    case Core::HID::NpadType::JoyconLeft:
         return parameters.allow_left_joycon;
-    case Settings::ControllerType::RightJoycon:
+    case Core::HID::NpadType::JoyconRight:
         return parameters.allow_right_joycon;
-    case Settings::ControllerType::Handheld:
+    case Core::HID::NpadType::Handheld:
         return parameters.enable_single_mode && parameters.allow_handheld;
-    case Settings::ControllerType::GameCube:
+    case Core::HID::NpadType::GameCube:
         return parameters.allow_gamecube_controller;
     default:
         return false;
@@ -198,7 +183,7 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
             connect(emulated_controllers[i], qOverload<int>(&QComboBox::currentIndexChanged),
                     [this, i](int index) {
                         UpdateDockedState(GetControllerTypeFromIndex(index, i) ==
-                                          Settings::ControllerType::Handheld);
+                                          Core::HID::NpadType::Handheld);
                     });
         }
     }
@@ -251,17 +236,17 @@ void QtControllerSelectorDialog::ApplyConfiguration() {
 }
 
 void QtControllerSelectorDialog::LoadConfiguration() {
+    const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
     for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
-        const auto connected =
-            Settings::values.players.GetValue()[index].connected ||
-            (index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
+        const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index);
+        const auto connected = controller->IsConnected() || (index == 0 && handheld->IsConnected());
         player_groupboxes[index]->setChecked(connected);
         connected_controller_checkboxes[index]->setChecked(connected);
-        emulated_controllers[index]->setCurrentIndex(GetIndexFromControllerType(
-            Settings::values.players.GetValue()[index].controller_type, index));
+        emulated_controllers[index]->setCurrentIndex(
+            GetIndexFromControllerType(controller->GetNpadType(), index));
     }
 
-    UpdateDockedState(Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
+    UpdateDockedState(handheld->IsConnected());
 
     ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
     ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
@@ -417,33 +402,32 @@ void QtControllerSelectorDialog::SetEmulatedControllers(std::size_t player_index
     emulated_controllers[player_index]->clear();
 
     pairs.emplace_back(emulated_controllers[player_index]->count(),
-                       Settings::ControllerType::ProController);
+                       Core::HID::NpadType::ProController);
     emulated_controllers[player_index]->addItem(tr("Pro Controller"));
 
     pairs.emplace_back(emulated_controllers[player_index]->count(),
-                       Settings::ControllerType::DualJoyconDetached);
+                       Core::HID::NpadType::JoyconDual);
     emulated_controllers[player_index]->addItem(tr("Dual Joycons"));
 
     pairs.emplace_back(emulated_controllers[player_index]->count(),
-                       Settings::ControllerType::LeftJoycon);
+                       Core::HID::NpadType::JoyconLeft);
     emulated_controllers[player_index]->addItem(tr("Left Joycon"));
 
     pairs.emplace_back(emulated_controllers[player_index]->count(),
-                       Settings::ControllerType::RightJoycon);
+                       Core::HID::NpadType::JoyconRight);
     emulated_controllers[player_index]->addItem(tr("Right Joycon"));
 
     if (player_index == 0) {
         pairs.emplace_back(emulated_controllers[player_index]->count(),
-                           Settings::ControllerType::Handheld);
+                           Core::HID::NpadType::Handheld);
         emulated_controllers[player_index]->addItem(tr("Handheld"));
     }
 
-    pairs.emplace_back(emulated_controllers[player_index]->count(),
-                       Settings::ControllerType::GameCube);
+    pairs.emplace_back(emulated_controllers[player_index]->count(), Core::HID::NpadType::GameCube);
     emulated_controllers[player_index]->addItem(tr("GameCube Controller"));
 }
 
-Settings::ControllerType QtControllerSelectorDialog::GetControllerTypeFromIndex(
+Core::HID::NpadType QtControllerSelectorDialog::GetControllerTypeFromIndex(
     int index, std::size_t player_index) const {
     const auto& pairs = index_controller_type_pairs[player_index];
 
@@ -451,13 +435,13 @@ Settings::ControllerType QtControllerSelectorDialog::GetControllerTypeFromIndex(
                                  [index](const auto& pair) { return pair.first == index; });
 
     if (it == pairs.end()) {
-        return Settings::ControllerType::ProController;
+        return Core::HID::NpadType::ProController;
     }
 
     return it->second;
 }
 
-int QtControllerSelectorDialog::GetIndexFromControllerType(Settings::ControllerType type,
+int QtControllerSelectorDialog::GetIndexFromControllerType(Core::HID::NpadType type,
                                                            std::size_t player_index) const {
     const auto& pairs = index_controller_type_pairs[player_index];
 
@@ -481,16 +465,16 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
     const QString stylesheet = [this, player_index] {
         switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(),
                                            player_index)) {
-        case Settings::ControllerType::ProController:
-        case Settings::ControllerType::GameCube:
+        case Core::HID::NpadType::ProController:
+        case Core::HID::NpadType::GameCube:
             return QStringLiteral("image: url(:/controller/applet_pro_controller%0); ");
-        case Settings::ControllerType::DualJoyconDetached:
+        case Core::HID::NpadType::JoyconDual:
             return QStringLiteral("image: url(:/controller/applet_dual_joycon%0); ");
-        case Settings::ControllerType::LeftJoycon:
+        case Core::HID::NpadType::JoyconLeft:
             return QStringLiteral("image: url(:/controller/applet_joycon_left%0); ");
-        case Settings::ControllerType::RightJoycon:
+        case Core::HID::NpadType::JoyconRight:
             return QStringLiteral("image: url(:/controller/applet_joycon_right%0); ");
-        case Settings::ControllerType::Handheld:
+        case Core::HID::NpadType::Handheld:
             return QStringLiteral("image: url(:/controller/applet_handheld%0); ");
         default:
             return QString{};
@@ -518,54 +502,42 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
 }
 
 void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) {
-    auto& player = Settings::values.players.GetValue()[player_index];
+    auto* controller = system.HIDCore().GetEmulatedControllerByIndex(player_index);
 
     const auto controller_type = GetControllerTypeFromIndex(
         emulated_controllers[player_index]->currentIndex(), player_index);
     const auto player_connected = player_groupboxes[player_index]->isChecked() &&
-                                  controller_type != Settings::ControllerType::Handheld;
+                                  controller_type != Core::HID::NpadType::Handheld;
 
-    if (player.controller_type == controller_type && player.connected == player_connected) {
+    if (controller->GetNpadType() == controller_type &&
+        controller->IsConnected() == player_connected) {
         // Set vibration devices in the event that the input device has changed.
         ConfigureVibration::SetVibrationDevices(player_index);
         return;
     }
 
     // Disconnect the controller first.
-    UpdateController(controller_type, player_index, false, system);
-
-    player.controller_type = controller_type;
-    player.connected = player_connected;
+    UpdateController(controller, controller_type, false);
 
     ConfigureVibration::SetVibrationDevices(player_index);
 
     // Handheld
     if (player_index == 0) {
-        auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
-        if (controller_type == Settings::ControllerType::Handheld) {
-            handheld = player;
+        if (controller_type == Core::HID::NpadType::Handheld) {
+            auto* handheld =
+                system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+            UpdateController(handheld, Core::HID::NpadType::Handheld,
+                             player_groupboxes[player_index]->isChecked());
         }
-        handheld.connected = player_groupboxes[player_index]->isChecked() &&
-                             controller_type == Settings::ControllerType::Handheld;
-        UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected, system);
     }
 
-    if (!player.connected) {
-        return;
-    }
-
-    // This emulates a delay between disconnecting and reconnecting controllers as some games
-    // do not respond to a change in controller type if it was instantaneous.
-    using namespace std::chrono_literals;
-    std::this_thread::sleep_for(60ms);
-
-    UpdateController(controller_type, player_index, player_connected, system);
+    UpdateController(controller, controller_type, player_connected);
 }
 
 void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) {
     if (!player_groupboxes[player_index]->isChecked() ||
         GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(),
-                                   player_index) == Settings::ControllerType::Handheld) {
+                                   player_index) == Core::HID::NpadType::Handheld) {
         led_patterns_boxes[player_index][0]->setChecked(false);
         led_patterns_boxes[player_index][1]->setChecked(false);
         led_patterns_boxes[player_index][2]->setChecked(false);
@@ -573,10 +545,12 @@ void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) {
         return;
     }
 
-    led_patterns_boxes[player_index][0]->setChecked(led_patterns[player_index][0]);
-    led_patterns_boxes[player_index][1]->setChecked(led_patterns[player_index][1]);
-    led_patterns_boxes[player_index][2]->setChecked(led_patterns[player_index][2]);
-    led_patterns_boxes[player_index][3]->setChecked(led_patterns[player_index][3]);
+    const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(player_index);
+    const auto led_pattern = controller->GetLedPattern();
+    led_patterns_boxes[player_index][0]->setChecked(led_pattern.position1);
+    led_patterns_boxes[player_index][1]->setChecked(led_pattern.position2);
+    led_patterns_boxes[player_index][2]->setChecked(led_pattern.position3);
+    led_patterns_boxes[player_index][3]->setChecked(led_pattern.position4);
 }
 
 void QtControllerSelectorDialog::UpdateBorderColor(std::size_t player_index) {
@@ -656,10 +630,9 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
     }
 
     for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) {
+        auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index);
         // Disconnect any unsupported players here and disable or hide them if applicable.
-        Settings::values.players.GetValue()[index].connected = false;
-        UpdateController(Settings::values.players.GetValue()[index].controller_type, index, false,
-                         system);
+        UpdateController(controller, controller->GetNpadType(), false);
         // Hide the player widgets when max_supported_controllers is less than or equal to 4.
         if (max_supported_players <= 4) {
             player_widgets[index]->hide();
diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h
index ca09fde04f..dd981f4795 100644
--- a/src/yuzu/applets/qt_controller.h
+++ b/src/yuzu/applets/qt_controller.h
@@ -23,10 +23,6 @@ namespace InputCommon {
 class InputSubsystem;
 }
 
-namespace Settings {
-enum class ControllerType;
-}
-
 namespace Ui {
 class QtControllerSelectorDialog;
 }
@@ -35,6 +31,10 @@ namespace Core {
 class System;
 }
 
+namespace Core::HID {
+enum class NpadType : u8;
+}
+
 class QtControllerSelectorDialog final : public QDialog {
     Q_OBJECT
 
@@ -74,10 +74,10 @@ private:
     void SetEmulatedControllers(std::size_t player_index);
 
     // Gets the Controller Type for a given controller combobox index per player.
-    Settings::ControllerType GetControllerTypeFromIndex(int index, std::size_t player_index) const;
+    Core::HID::NpadType GetControllerTypeFromIndex(int index, std::size_t player_index) const;
 
     // Gets the controller combobox index for a given Controller Type per player.
-    int GetIndexFromControllerType(Settings::ControllerType type, std::size_t player_index) const;
+    int GetIndexFromControllerType(Core::HID::NpadType type, std::size_t player_index) const;
 
     // Updates the controller icons per player.
     void UpdateControllerIcon(std::size_t player_index);
@@ -139,7 +139,7 @@ private:
     std::array<QComboBox*, NUM_PLAYERS> emulated_controllers;
 
     /// Pairs of emulated controller index and Controller Type enum per player.
-    std::array<std::vector<std::pair<int, Settings::ControllerType>>, NUM_PLAYERS>
+    std::array<std::vector<std::pair<int, Core::HID::NpadType>>, NUM_PLAYERS>
         index_controller_type_pairs;
 
     // Labels representing the number of connected controllers
diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp
index 7e87312322..3d91f80341 100644
--- a/src/yuzu/applets/qt_software_keyboard.cpp
+++ b/src/yuzu/applets/qt_software_keyboard.cpp
@@ -10,6 +10,8 @@
 #include "common/settings.h"
 #include "common/string_util.h"
 #include "core/core.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
 #include "core/hid/hid_types.h"
 #include "core/hid/input_interpreter.h"
 #include "ui_qt_software_keyboard.h"
@@ -796,9 +798,10 @@ void QtSoftwareKeyboardDialog::SetTextDrawType() {
 }
 
 void QtSoftwareKeyboardDialog::SetControllerImage() {
-    const auto controller_type = Settings::values.players.GetValue()[8].connected
-                                     ? Settings::values.players.GetValue()[8].controller_type
-                                     : Settings::values.players.GetValue()[0].controller_type;
+    const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+    const auto* player_1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+    const auto controller_type =
+        handheld->IsConnected() ? handheld->GetNpadType() : player_1->GetNpadType();
 
     const QString theme = [] {
         if (QIcon::themeName().contains(QStringLiteral("dark")) ||
@@ -810,8 +813,8 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
     }();
 
     switch (controller_type) {
-    case Settings::ControllerType::ProController:
-    case Settings::ControllerType::GameCube:
+    case Core::HID::NpadType::ProController:
+    case Core::HID::NpadType::GameCube:
         ui->icon_controller->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme));
         ui->icon_controller_shift->setStyleSheet(
@@ -819,7 +822,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
         ui->icon_controller_num->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme));
         break;
-    case Settings::ControllerType::DualJoyconDetached:
+    case Core::HID::NpadType::JoyconDual:
         ui->icon_controller->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme));
         ui->icon_controller_shift->setStyleSheet(
@@ -827,7 +830,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
         ui->icon_controller_num->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme));
         break;
-    case Settings::ControllerType::LeftJoycon:
+    case Core::HID::NpadType::JoyconLeft:
         ui->icon_controller->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);")
                 .arg(theme));
@@ -838,7 +841,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
             QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);")
                 .arg(theme));
         break;
-    case Settings::ControllerType::RightJoycon:
+    case Core::HID::NpadType::JoyconRight:
         ui->icon_controller->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);")
                 .arg(theme));
@@ -849,7 +852,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
             QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);")
                 .arg(theme));
         break;
-    case Settings::ControllerType::Handheld:
+    case Core::HID::NpadType::Handheld:
         ui->icon_controller->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme));
         ui->icon_controller_shift->setStyleSheet(
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 67faa8be8a..dece27fdeb 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -211,8 +211,10 @@ void ConfigureInput::RetranslateUI() {
 }
 
 void ConfigureInput::LoadConfiguration() {
+    const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+
     LoadPlayerControllerIndices();
-    UpdateDockedState(Settings::values.players.GetValue()[8].connected);
+    UpdateDockedState(handheld->IsConnected());
 
     ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
     ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
@@ -220,9 +222,16 @@ void ConfigureInput::LoadConfiguration() {
 
 void ConfigureInput::LoadPlayerControllerIndices() {
     for (std::size_t i = 0; i < player_connected.size(); ++i) {
-        const auto connected = Settings::values.players.GetValue()[i].connected ||
-                               (i == 0 && Settings::values.players.GetValue()[8].connected);
-        player_connected[i]->setChecked(connected);
+        if (i == 0) {
+            auto* handheld =
+                system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+            if (handheld->IsConnected()) {
+                player_connected[i]->setChecked(true);
+                continue;
+            }
+        }
+        const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(i);
+        player_connected[i]->setChecked(controller->IsConnected());
     }
 }
 
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 93f7eddc92..be87204fc3 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -104,8 +104,8 @@ void PlayerControlPreview::UpdateColors() {
     colors.left = colors.primary;
     colors.right = colors.primary;
     // Possible alternative to set colors from settings
-    // colors.left = QColor(Settings::values.players.GetValue()[player_index].body_color_left);
-    // colors.right = QColor(Settings::values.players.GetValue()[player_index].body_color_right);
+    // colors.left = QColor(controller->GetColors().left.body);
+    // colors.right = QColor(controller->GetColors().right.body);
 }
 
 void PlayerControlPreview::ResetInputs() {
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index ae997ccfa3..46a5f62adf 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -832,15 +832,16 @@ void GMainWindow::InitializeWidgets() {
     dock_status_button->setFocusPolicy(Qt::NoFocus);
     connect(dock_status_button, &QPushButton::clicked, [&] {
         const bool is_docked = Settings::values.use_docked_mode.GetValue();
-        auto& controller_type = Settings::values.players.GetValue()[0].controller_type;
+        auto* player_1 = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+        auto* handheld = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
 
-        if (!is_docked && controller_type == Settings::ControllerType::Handheld) {
+        if (!is_docked && handheld->IsConnected()) {
             QMessageBox::warning(this, tr("Invalid config detected"),
                                  tr("Handheld controller can't be used on docked mode. Pro "
                                     "controller will be selected."));
-            controller_type = Settings::ControllerType::ProController;
-            ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get(), *system);
-            configure_dialog.ApplyConfiguration();
+            handheld->Disconnect();
+            player_1->SetNpadType(Core::HID::NpadType::ProController);
+            player_1->Connect();
         }
 
         Settings::values.use_docked_mode.SetValue(!is_docked);

From 85052b8662d9512077780f717fb2e168390ed705 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Wed, 20 Oct 2021 23:18:04 -0500
Subject: [PATCH 43/88] service/hid: Fix gesture input

---
 src/core/hid/emulated_console.cpp             |  55 ++++----
 src/core/hid/emulated_console.h               |   3 +
 src/core/hid/emulated_controller.cpp          |   4 -
 .../hle/service/hid/controllers/gesture.cpp   | 124 ++++++++++--------
 .../hle/service/hid/controllers/gesture.h     |  29 +++-
 src/input_common/drivers/gc_adapter.cpp       |   4 +-
 src/input_common/drivers/udp_client.cpp       |  27 ++++
 src/yuzu/main.cpp                             |   2 +-
 8 files changed, 158 insertions(+), 90 deletions(-)

diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index 7f7c8fd59d..e82cf59905 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -20,27 +20,21 @@ void EmulatedConsole::ReloadFromSettings() {
     ReloadInput();
 }
 
-void EmulatedConsole::ReloadInput() {
-    motion_devices = Input::CreateDevice<Input::InputDevice>(motion_params);
-    if (motion_devices) {
-        Input::InputCallback motion_callback{
-            [this](Input::CallbackStatus callback) { SetMotion(callback); }};
-        motion_devices->SetCallback(motion_callback);
-    }
-
-    // TODO: Fix this mess
+void EmulatedConsole::SetTouchParams() {
+    // TODO(german77): Support any number of fingers
     std::size_t index = 0;
-    const std::string mouse_device_string =
-        fmt::format("engine:mouse,axis_x:10,axis_y:11,button:{}", index);
-    touch_devices[index] = Input::CreateDeviceFromString<Input::InputDevice>(mouse_device_string);
-    Input::InputCallback trigger_callbackk{
-        [this, index](Input::CallbackStatus callback) { SetTouch(callback, index); }};
-    touch_devices[index]->SetCallback(trigger_callbackk);
 
-    index++;
+    // Hardcode mouse, touchscreen and cemuhook parameters
+    touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};
+    touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"};
+    touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"};
+    touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:0,axis_y:1,button:0"};
+    touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:2,axis_y:3,button:1"};
+
     const auto button_index =
         static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
     const auto& touch_buttons = Settings::values.touch_from_button_maps[button_index].buttons;
+
     for (const auto& config_entry : touch_buttons) {
         Common::ParamPackage params{config_entry};
         Common::ParamPackage touch_button_params;
@@ -53,15 +47,32 @@ void EmulatedConsole::ReloadInput() {
         touch_button_params.Set("x", x);
         touch_button_params.Set("y", y);
         touch_button_params.Set("touch_id", static_cast<int>(index));
-        touch_devices[index] =
-            Input::CreateDeviceFromString<Input::InputDevice>(touch_button_params.Serialize());
-        if (!touch_devices[index]) {
+        touch_params[index] = touch_button_params;
+        index++;
+        if (index >= touch_params.size()) {
+            return;
+        }
+    }
+}
+
+void EmulatedConsole::ReloadInput() {
+    SetTouchParams();
+    motion_devices = Input::CreateDevice<Input::InputDevice>(motion_params);
+    if (motion_devices) {
+        Input::InputCallback motion_callback{
+            [this](Input::CallbackStatus callback) { SetMotion(callback); }};
+        motion_devices->SetCallback(motion_callback);
+    }
+
+    std::size_t index = 0;
+    for (auto& touch_device : touch_devices) {
+        touch_device = Input::CreateDevice<Input::InputDevice>(touch_params[index]);
+        if (!touch_device) {
             continue;
         }
-
-        Input::InputCallback trigger_callback{
+        Input::InputCallback touch_callback{
             [this, index](Input::CallbackStatus callback) { SetTouch(callback, index); }};
-        touch_devices[index]->SetCallback(trigger_callback);
+        touch_device->SetCallback(touch_callback);
         index++;
     }
 }
diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h
index 7d6cf95069..c48d25794f 100644
--- a/src/core/hid/emulated_console.h
+++ b/src/core/hid/emulated_console.h
@@ -144,6 +144,9 @@ public:
     void DeleteCallback(int key);
 
 private:
+    /// Creates and stores the touch params
+    void SetTouchParams();
+
     /**
      * Updates the motion status of the console
      * @param A CallbackStatus containing gyro and accelerometer data
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 6622603277..1ff3022c5f 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -705,7 +705,6 @@ void EmulatedController::Connect() {
         }
         is_connected = true;
     }
-    LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type));
     TriggerOnChange(ControllerTriggerType::Connected, true);
 }
 
@@ -714,8 +713,6 @@ void EmulatedController::Disconnect() {
         std::lock_guard lock{mutex};
         if (is_configuring) {
             temporary_is_connected = false;
-            LOG_ERROR(Service_HID, "Disconnected temporal controller {}",
-                      NpadIdTypeToIndex(npad_id_type));
             TriggerOnChange(ControllerTriggerType::Disconnected, false);
             return;
         }
@@ -725,7 +722,6 @@ void EmulatedController::Disconnect() {
         }
         is_connected = false;
     }
-    LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type));
     TriggerOnChange(ControllerTriggerType::Disconnected, true);
 }
 
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 2f98cc54b0..a26ce53837 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -28,12 +28,10 @@ constexpr f32 Square(s32 num) {
 Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) {
     console = system.HIDCore().GetEmulatedConsole();
 }
-
 Controller_Gesture::~Controller_Gesture() = default;
 
 void Controller_Gesture::OnInit() {
-    gesture_lifo.entry_count = 0;
-    gesture_lifo.last_entry_index = 0;
+    shared_memory.header.entry_count = 0;
     force_update = true;
 }
 
@@ -41,27 +39,27 @@ void Controller_Gesture::OnRelease() {}
 
 void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                   std::size_t size) {
-    // TODO FIND WTF IS WRONG HERE!!!!!!!!
-    return;
+    shared_memory.header.timestamp = core_timing.GetCPUTicks();
+    shared_memory.header.total_entry_count = 17;
+
     if (!IsControllerActivated()) {
-        gesture_lifo.entry_count = 0;
-        gesture_lifo.last_entry_index = 0;
-        std::memcpy(data, &gesture_lifo, sizeof(gesture_lifo));
+        shared_memory.header.entry_count = 0;
+        shared_memory.header.last_entry_index = 0;
         return;
     }
 
     ReadTouchInput();
 
     GestureProperties gesture = GetGestureProperties();
-    f32 time_difference =
-        static_cast<f32>(gesture_lifo.timestamp - last_update_timestamp) / (1000 * 1000 * 1000);
+    f32 time_difference = static_cast<f32>(shared_memory.header.timestamp - last_update_timestamp) /
+                          (1000 * 1000 * 1000);
 
     // Only update if necesary
     if (!ShouldUpdateGesture(gesture, time_difference)) {
         return;
     }
 
-    last_update_timestamp = gesture_lifo.timestamp;
+    last_update_timestamp = shared_memory.header.timestamp;
     UpdateGestureSharedMemory(data, size, gesture, time_difference);
 }
 
@@ -77,7 +75,7 @@ void Controller_Gesture::ReadTouchInput() {
 
 bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
                                              f32 time_difference) {
-    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
+    const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
     if (force_update) {
         force_update = false;
         return true;
@@ -105,16 +103,24 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
     GestureType type = GestureType::Idle;
     GestureAttribute attributes{};
 
-    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
+    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];
 
-    // 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 (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;
+
+    // Reset values to default
+    cur_entry.delta = {};
+    cur_entry.vel_x = 0;
+    cur_entry.vel_y = 0;
+    cur_entry.direction = GestureDirection::None;
+    cur_entry.rotation_angle = 0;
+    cur_entry.scale = 0;
 
     if (gesture.active_points > 0) {
         if (last_gesture.active_points == 0) {
@@ -127,21 +133,20 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
     }
 
     // Apply attributes
-    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;
+    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;
     last_gesture = gesture;
 
-    gesture_lifo.WriteNextEntry(next_state);
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo));
+    std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
 }
 
 void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
                                     GestureAttribute& attributes) {
-    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
+    const auto& last_entry = GetLastGestureEntry();
 
     gesture.detection_count++;
     type = GestureType::Touch;
@@ -155,7 +160,7 @@ void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& typ
 
 void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type,
                                                f32 time_difference) {
-    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
+    const auto& last_entry = GetLastGestureEntry();
 
     // Promote to pan type if touch moved
     for (size_t id = 0; id < MAX_POINTS; id++) {
@@ -190,7 +195,7 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Gestu
 void Controller_Gesture::EndGesture(GestureProperties& gesture,
                                     GestureProperties& last_gesture_props, GestureType& type,
                                     GestureAttribute& attributes, f32 time_difference) {
-    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
+    const auto& last_entry = GetLastGestureEntry();
 
     if (last_gesture_props.active_points != 0) {
         switch (last_entry.type) {
@@ -240,18 +245,19 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
 void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
                                         GestureProperties& last_gesture_props, GestureType& type,
                                         f32 time_difference) {
-    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
+    auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
+    const auto& last_entry = GetLastGestureEntry();
 
-    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;
+    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;
     last_pan_time_difference = time_difference;
 
     // Promote to pinch type
     if (std::abs(gesture.average_distance - last_gesture_props.average_distance) >
         pinch_threshold) {
         type = GestureType::Pinch;
-        next_state.scale = gesture.average_distance / last_gesture_props.average_distance;
+        cur_entry.scale = gesture.average_distance / last_gesture_props.average_distance;
     }
 
     const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) /
@@ -259,21 +265,22 @@ void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
     // Promote to rotate type
     if (std::abs(angle_between_two_lines) > angle_threshold) {
         type = GestureType::Rotate;
-        next_state.scale = 0;
-        next_state.rotation_angle = angle_between_two_lines * 180.0f / Common::PI;
+        cur_entry.scale = 0;
+        cur_entry.rotation_angle = angle_between_two_lines * 180.0f / Common::PI;
     }
 }
 
 void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
                                      GestureProperties& last_gesture_props, GestureType& type,
                                      f32 time_difference) {
-    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
-    next_state.vel_x =
+    auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
+    const auto& last_entry = GetLastGestureEntry();
+    cur_entry.vel_x =
         static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference);
-    next_state.vel_y =
+    cur_entry.vel_y =
         static_cast<f32>(last_entry.delta.y) / (last_pan_time_difference + time_difference);
     const f32 curr_vel =
-        std::sqrt((next_state.vel_x * next_state.vel_x) + (next_state.vel_y * next_state.vel_y));
+        std::sqrt((cur_entry.vel_x * cur_entry.vel_x) + (cur_entry.vel_y * cur_entry.vel_y));
 
     // Set swipe event with parameters
     if (curr_vel > swipe_threshold) {
@@ -283,33 +290,42 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
 
     // End panning without swipe
     type = GestureType::Complete;
-    next_state.vel_x = 0;
-    next_state.vel_y = 0;
+    cur_entry.vel_x = 0;
+    cur_entry.vel_y = 0;
     force_update = true;
 }
 
 void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
                                        GestureProperties& last_gesture_props, GestureType& type) {
-    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
+    auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
+    const auto& last_entry = GetLastGestureEntry();
 
     type = GestureType::Swipe;
     gesture = last_gesture_props;
     force_update = true;
-    next_state.delta = last_entry.delta;
+    cur_entry.delta = last_entry.delta;
 
-    if (std::abs(next_state.delta.x) > std::abs(next_state.delta.y)) {
-        if (next_state.delta.x > 0) {
-            next_state.direction = GestureDirection::Right;
+    if (std::abs(cur_entry.delta.x) > std::abs(cur_entry.delta.y)) {
+        if (cur_entry.delta.x > 0) {
+            cur_entry.direction = GestureDirection::Right;
             return;
         }
-        next_state.direction = GestureDirection::Left;
+        cur_entry.direction = GestureDirection::Left;
         return;
     }
-    if (next_state.delta.y > 0) {
-        next_state.direction = GestureDirection::Down;
+    if (cur_entry.delta.y > 0) {
+        cur_entry.direction = GestureDirection::Down;
         return;
     }
-    next_state.direction = GestureDirection::Up;
+    cur_entry.direction = GestureDirection::Up;
+}
+
+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];
 }
 
 Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() {
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 8e6f315a41..6128fb0ad3 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -71,6 +71,7 @@ private:
     // This is nn::hid::GestureState
     struct GestureState {
         s64_le sampling_number;
+        s64_le sampling_number2;
         s64_le detection_count;
         GestureType type;
         GestureDirection direction;
@@ -84,7 +85,21 @@ private:
         s32_le point_count;
         std::array<Common::Point<s32_le>, 4> points;
     };
-    static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
+    static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size");
+
+    struct CommonHeader {
+        s64_le timestamp;
+        s64_le total_entry_count;
+        s64_le last_entry_index;
+        s64_le entry_count;
+    };
+    static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
+
+    struct SharedMemory {
+        CommonHeader header;
+        std::array<GestureState, 17> gesture_states;
+    };
+    static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size");
 
     struct Finger {
         Common::Point<f32> pos{};
@@ -137,17 +152,17 @@ private:
     void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
                        GestureType& type);
 
+    // Retrieves the last gesture entry, as indicated by shared memory indices.
+    [[nodiscard]] GestureState& GetLastGestureEntry();
+    [[nodiscard]] const GestureState& GetLastGestureEntry() const;
+
     // Returns the average distance, angle and middle point of the active fingers
     GestureProperties GetGestureProperties();
 
-    // 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{};
+    SharedMemory shared_memory{};
     Core::HID::EmulatedConsole* console;
 
+    std::array<Finger, MAX_POINTS> fingers{};
     GestureProperties last_gesture{};
     s64_le last_update_timestamp{};
     s64_le last_tap_timestamp{};
diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp
index 4fb6ab5af8..25b66f528b 100644
--- a/src/input_common/drivers/gc_adapter.cpp
+++ b/src/input_common/drivers/gc_adapter.cpp
@@ -209,7 +209,7 @@ void GCAdapter::UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_
             pads[port].axis_origin[index] = axis_value;
             pads[port].reset_origin_counter++;
         }
-        const f32 axis_status = (axis_value - pads[port].axis_origin[index]) / 110.0f;
+        const f32 axis_status = (axis_value - pads[port].axis_origin[index]) / 100.0f;
         SetAxis(pads[port].identifier, static_cast<int>(index), axis_status);
     }
 }
@@ -530,7 +530,7 @@ std::string GCAdapter::GetUIName(const Common::ParamPackage& params) const {
         return fmt::format("Button {}", GetUIButtonName(params));
     }
     if (params.Has("axis")) {
-        return fmt::format("Axis {}", params.Get("axis",0));
+        return fmt::format("Axis {}", params.Get("axis", 0));
     }
 
     return "Bad GC Adapter";
diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp
index 6fcc3a01b7..f0c0a6b8bf 100644
--- a/src/input_common/drivers/udp_client.cpp
+++ b/src/input_common/drivers/udp_client.cpp
@@ -243,6 +243,33 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
     };
     const PadIdentifier identifier = GetPadIdentifier(pad_index);
     SetMotion(identifier, 0, motion);
+
+    for (std::size_t id = 0; id < data.touch.size(); ++id) {
+        const auto touch_pad = data.touch[id];
+        const int touch_id = static_cast<int>(client * 2 + id);
+
+        // TODO: Use custom calibration per device
+        const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue());
+        const u16 min_x = static_cast<u16>(touch_param.Get("min_x", 100));
+        const u16 min_y = static_cast<u16>(touch_param.Get("min_y", 50));
+        const u16 max_x = static_cast<u16>(touch_param.Get("max_x", 1800));
+        const u16 max_y = static_cast<u16>(touch_param.Get("max_y", 850));
+
+        const f32 x =
+            static_cast<f32>(std::clamp(static_cast<u16>(touch_pad.x), min_x, max_x) - min_x) /
+            static_cast<f32>(max_x - min_x);
+        const f32 y =
+            static_cast<f32>(std::clamp(static_cast<u16>(touch_pad.y), min_y, max_y) - min_y) /
+            static_cast<f32>(max_y - min_y);
+
+        if (touch_pad.is_active) {
+            SetAxis(identifier, touch_id * 2, x);
+            SetAxis(identifier, touch_id * 2 + 1, y);
+            SetButton(identifier, touch_id, true);
+            continue;
+        }
+        SetButton(identifier, touch_id, false);
+    }
 }
 
 void UDPClient::StartCommunication(std::size_t client, const std::string& host, u16 port) {
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 46a5f62adf..022d11cc49 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2973,7 +2973,7 @@ void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_vie
 QString GMainWindow::GetTasStateDescription() const {
     auto [tas_status, current_tas_frame, total_tas_frames] = input_subsystem->GetTas()->GetStatus();
     switch (tas_status) {
-    case InputCommon::TasInput::TasState::Running :
+    case InputCommon::TasInput::TasState::Running:
         return tr("TAS state: Running %1/%2").arg(current_tas_frame).arg(total_tas_frames);
     case InputCommon::TasInput::TasState::Recording:
         return tr("TAS state: Recording %1").arg(total_tas_frames);

From 95cf66b6559c3e7a1eb40be919f16217566ffdbc Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Thu, 21 Oct 2021 00:49:09 -0500
Subject: [PATCH 44/88] service/hid: Use ring buffer for gestures

---
 .../hle/service/hid/controllers/gesture.cpp   | 107 ++++++++----------
 .../hle/service/hid/controllers/gesture.h     |  24 +---
 2 files changed, 52 insertions(+), 79 deletions(-)

diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index a26ce53837..a82d04b3b9 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -31,7 +31,8 @@ Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(s
 Controller_Gesture::~Controller_Gesture() = default;
 
 void Controller_Gesture::OnInit() {
-    shared_memory.header.entry_count = 0;
+    gesture_lifo.entry_count = 0;
+    gesture_lifo.last_entry_index = 0;
     force_update = true;
 }
 
@@ -39,27 +40,25 @@ void Controller_Gesture::OnRelease() {}
 
 void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                   std::size_t size) {
-    shared_memory.header.timestamp = core_timing.GetCPUTicks();
-    shared_memory.header.total_entry_count = 17;
-
     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;
     }
 
     ReadTouchInput();
 
     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
     if (!ShouldUpdateGesture(gesture, time_difference)) {
         return;
     }
 
-    last_update_timestamp = shared_memory.header.timestamp;
+    last_update_timestamp = gesture_lifo.timestamp;
     UpdateGestureSharedMemory(data, size, gesture, time_difference);
 }
 
@@ -75,7 +74,7 @@ void Controller_Gesture::ReadTouchInput() {
 
 bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
                                              f32 time_difference) {
-    const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
+    const auto& last_entry = GetLastGestureEntry();
     if (force_update) {
         force_update = false;
         return true;
@@ -103,24 +102,16 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
     GestureType type = GestureType::Idle;
     GestureAttribute 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];
+    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
 
-    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;
-
-    // Reset values to default
-    cur_entry.delta = {};
-    cur_entry.vel_x = 0;
-    cur_entry.vel_y = 0;
-    cur_entry.direction = GestureDirection::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 (last_gesture.active_points == 0) {
@@ -133,15 +124,16 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
     }
 
     // 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;
 
-    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, GestureType& type,
@@ -245,19 +237,18 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
 void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
                                         GestureProperties& last_gesture_props, GestureType& type,
                                         f32 time_difference) {
-    auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
     const auto& last_entry = GetLastGestureEntry();
 
-    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;
 
     // Promote to pinch type
     if (std::abs(gesture.average_distance - last_gesture_props.average_distance) >
         pinch_threshold) {
         type = GestureType::Pinch;
-        cur_entry.scale = gesture.average_distance / last_gesture_props.average_distance;
+        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) /
@@ -265,22 +256,21 @@ void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
     // Promote to rotate type
     if (std::abs(angle_between_two_lines) > angle_threshold) {
         type = GestureType::Rotate;
-        cur_entry.scale = 0;
-        cur_entry.rotation_angle = angle_between_two_lines * 180.0f / Common::PI;
+        next_state.scale = 0;
+        next_state.rotation_angle = angle_between_two_lines * 180.0f / Common::PI;
     }
 }
 
 void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
                                      GestureProperties& last_gesture_props, GestureType& type,
                                      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 =
+    next_state.vel_x =
         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);
     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
     if (curr_vel > swipe_threshold) {
@@ -290,42 +280,37 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
 
     // End panning without swipe
     type = GestureType::Complete;
-    cur_entry.vel_x = 0;
-    cur_entry.vel_y = 0;
+    next_state.vel_x = 0;
+    next_state.vel_y = 0;
     force_update = true;
 }
 
 void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
                                        GestureProperties& last_gesture_props, GestureType& type) {
-    auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
     const auto& last_entry = GetLastGestureEntry();
 
     type = GestureType::Swipe;
     gesture = last_gesture_props;
     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 = GestureDirection::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;
         }
-        cur_entry.direction = GestureDirection::Left;
+        next_state.direction = GestureDirection::Left;
         return;
     }
-    if (cur_entry.delta.y > 0) {
-        cur_entry.direction = GestureDirection::Down;
+    if (next_state.delta.y > 0) {
+        next_state.direction = GestureDirection::Down;
         return;
     }
-    cur_entry.direction = GestureDirection::Up;
-}
-
-Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() {
-    return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17];
+    next_state.direction = GestureDirection::Up;
 }
 
 const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const {
-    return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17];
+    return gesture_lifo.ReadCurrentEntry().state;
 }
 
 Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() {
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 6128fb0ad3..6f5abaa4fa 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -71,7 +71,6 @@ private:
     // This is nn::hid::GestureState
     struct GestureState {
         s64_le sampling_number;
-        s64_le sampling_number2;
         s64_le detection_count;
         GestureType type;
         GestureDirection direction;
@@ -85,21 +84,7 @@ private:
         s32_le point_count;
         std::array<Common::Point<s32_le>, 4> points;
     };
-    static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size");
-
-    struct CommonHeader {
-        s64_le timestamp;
-        s64_le total_entry_count;
-        s64_le last_entry_index;
-        s64_le entry_count;
-    };
-    static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader 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 {
         Common::Point<f32> pos{};
@@ -153,13 +138,16 @@ private:
                        GestureType& type);
 
     // Retrieves the last gesture entry, as indicated by shared memory indices.
-    [[nodiscard]] GestureState& GetLastGestureEntry();
     [[nodiscard]] const GestureState& GetLastGestureEntry() const;
 
     // Returns the average distance, angle and middle point of the active fingers
     GestureProperties GetGestureProperties();
 
-    SharedMemory shared_memory{};
+    // 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{};
+
     Core::HID::EmulatedConsole* console;
 
     std::array<Finger, MAX_POINTS> fingers{};

From b5e72de753ae4de5c5fae7087abb00dc4242451d Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Thu, 21 Oct 2021 13:56:52 -0500
Subject: [PATCH 45/88] kraken: Address comments from review

review fixes
---
 src/core/frontend/applets/controller.cpp      | 51 ++++++++-----------
 src/core/frontend/applets/controller.h        |  8 +--
 src/core/hid/emulated_console.cpp             |  2 -
 src/core/hid/emulated_controller.cpp          | 12 +++--
 src/core/hid/emulated_controller.h            |  1 -
 src/core/hid/hid_core.cpp                     |  4 +-
 src/core/hid/hid_core.h                       |  3 ++
 src/core/hle/service/am/applets/applets.cpp   |  2 +-
 src/core/hle/service/hid/controllers/npad.cpp | 10 ++--
 src/core/hle/service/hid/controllers/npad.h   |  2 +-
 src/core/hle/service/hid/hid.cpp              |  3 +-
 src/input_common/drivers/udp_client.cpp       |  2 +
 src/input_common/drivers/udp_client.h         |  4 +-
 src/input_common/helpers/stick_from_buttons.h |  1 -
 src/input_common/main.cpp                     |  7 ++-
 15 files changed, 56 insertions(+), 56 deletions(-)

diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp
index ca1edce15f..30500ef1ef 100644
--- a/src/core/frontend/applets/controller.cpp
+++ b/src/core/frontend/applets/controller.cpp
@@ -5,16 +5,16 @@
 #include "common/assert.h"
 #include "common/logging/log.h"
 #include "core/frontend/applets/controller.h"
-#include "core/hle/service/hid/controllers/npad.h"
-#include "core/hle/service/hid/hid.h"
-#include "core/hle/service/sm/sm.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
+#include "core/hid/hid_types.h"
 
 namespace Core::Frontend {
 
 ControllerApplet::~ControllerApplet() = default;
 
-DefaultControllerApplet::DefaultControllerApplet(Service::SM::ServiceManager& service_manager_)
-    : service_manager{service_manager_} {}
+DefaultControllerApplet::DefaultControllerApplet(HID::HIDCore& hid_core_)
+    : hid_core{hid_core_} {}
 
 DefaultControllerApplet::~DefaultControllerApplet() = default;
 
@@ -22,24 +22,20 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
                                                      const ControllerParameters& parameters) const {
     LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!");
 
-    auto& npad =
-        service_manager.GetService<Service::HID::Hid>("hid")
-            ->GetAppletResource()
-            ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
-
-    auto& players = Settings::values.players.GetValue();
-
     const std::size_t min_supported_players =
         parameters.enable_single_mode ? 1 : parameters.min_players;
 
     // Disconnect Handheld first.
-    npad.DisconnectNpadAtIndex(8);
+    auto* handheld =hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
+    handheld->Disconnect();
 
     // Deduce the best configuration based on the input parameters.
-    for (std::size_t index = 0; index < players.size() - 2; ++index) {
+    for (std::size_t index = 0; index < hid_core.available_controllers - 2; ++index) {
+        auto* controller = hid_core.GetEmulatedControllerByIndex(index);
+
         // First, disconnect all controllers regardless of the value of keep_controllers_connected.
         // This makes it easy to connect the desired controllers.
-        npad.DisconnectNpadAtIndex(index);
+        controller->Disconnect();
 
         // Only connect the minimum number of required players.
         if (index >= min_supported_players) {
@@ -49,32 +45,27 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
         // Connect controllers based on the following priority list from highest to lowest priority:
         // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
         if (parameters.allow_pro_controller) {
-            npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(
-                                        Settings::ControllerType::ProController),
-                                    index);
+            controller->SetNpadType(Core::HID::NpadType::ProController);
+            controller->Connect();
         } else if (parameters.allow_dual_joycons) {
-            npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(
-                                        Settings::ControllerType::DualJoyconDetached),
-                                    index);
+            controller->SetNpadType(Core::HID::NpadType::JoyconDual);
+            controller->Connect();
         } else if (parameters.allow_left_joycon && parameters.allow_right_joycon) {
             // Assign left joycons to even player indices and right joycons to odd player indices.
             // We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and
             // a right Joycon for Player 2 in 2 Player Assist mode.
             if (index % 2 == 0) {
-                npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(
-                                            Settings::ControllerType::LeftJoycon),
-                                        index);
+                controller->SetNpadType(Core::HID::NpadType::JoyconLeft);
+                controller->Connect();
             } else {
-                npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(
-                                            Settings::ControllerType::RightJoycon),
-                                        index);
+                controller->SetNpadType(Core::HID::NpadType::JoyconRight);
+                controller->Connect();
             }
         } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
                    !Settings::values.use_docked_mode.GetValue()) {
             // We should *never* reach here under any normal circumstances.
-            npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(
-                                        Settings::ControllerType::Handheld),
-                                    index);
+            controller->SetNpadType(Core::HID::NpadType::Handheld);
+            controller->Connect();
         } else {
             UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!");
         }
diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h
index b0626a0f9c..014bc89011 100644
--- a/src/core/frontend/applets/controller.h
+++ b/src/core/frontend/applets/controller.h
@@ -8,8 +8,8 @@
 
 #include "common/common_types.h"
 
-namespace Service::SM {
-class ServiceManager;
+namespace Core::HID {
+class HIDCore;
 }
 
 namespace Core::Frontend {
@@ -44,14 +44,14 @@ public:
 
 class DefaultControllerApplet final : public ControllerApplet {
 public:
-    explicit DefaultControllerApplet(Service::SM::ServiceManager& service_manager_);
+    explicit DefaultControllerApplet(HID::HIDCore& hid_core_);
     ~DefaultControllerApplet() override;
 
     void ReconfigureControllers(std::function<void()> callback,
                                 const ControllerParameters& parameters) const override;
 
 private:
-    Service::SM::ServiceManager& service_manager;
+    HID::HIDCore& hid_core;
 };
 
 } // namespace Core::Frontend
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index e82cf59905..540fd107be 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -2,8 +2,6 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included
 
-#include <fmt/format.h>
-
 #include "core/hid/emulated_console.h"
 #include "core/hid/input_converter.h"
 
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 1ff3022c5f..d59758e999 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -2,8 +2,6 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included
 
-#include <fmt/format.h>
-
 #include "core/hid/emulated_controller.h"
 #include "core/hid/input_converter.h"
 
@@ -635,6 +633,9 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t
 }
 
 bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
+    if (device_index >= output_devices.size()) {
+        return false;
+    }
     if (!output_devices[device_index]) {
         return false;
     }
@@ -659,6 +660,9 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
 }
 
 bool EmulatedController::TestVibration(std::size_t device_index) {
+    if (device_index >= output_devices.size()) {
+        return false;
+    }
     if (!output_devices[device_index]) {
         return false;
     }
@@ -733,7 +737,9 @@ bool EmulatedController::IsConnected(bool temporary) const {
 }
 
 bool EmulatedController::IsVibrationEnabled() const {
-    return is_vibration_enabled;
+    const auto player_index = NpadIdTypeToIndex(npad_id_type);
+    const auto& player = Settings::values.players.GetValue()[player_index];
+    return player.vibration_enabled;
 }
 
 NpadIdType EmulatedController::GetNpadIdType() const {
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index f3ee707264..50f21ccd9c 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -337,7 +337,6 @@ private:
     bool is_connected{false};
     bool temporary_is_connected{false};
     bool is_configuring{false};
-    bool is_vibration_enabled{true};
     f32 motion_sensitivity{0.01f};
 
     ButtonParams button_params;
diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp
index bd17081bdf..cc1b3c2950 100644
--- a/src/core/hid/hid_core.cpp
+++ b/src/core/hid/hid_core.cpp
@@ -113,7 +113,7 @@ NpadStyleTag HIDCore::GetSupportedStyleTag() const {
 
 s8 HIDCore::GetPlayerCount() const {
     s8 active_players = 0;
-    for (std::size_t player_index = 0; player_index < 8; player_index++) {
+    for (std::size_t player_index = 0; player_index < available_controllers -2; player_index++) {
         const auto* controller = GetEmulatedControllerByIndex(player_index);
         if (controller->IsConnected()) {
             active_players++;
@@ -123,7 +123,7 @@ s8 HIDCore::GetPlayerCount() const {
 }
 
 NpadIdType HIDCore::GetFirstNpadId() const {
-    for (std::size_t player_index = 0; player_index < 10; player_index++) {
+    for (std::size_t player_index = 0; player_index < available_controllers; player_index++) {
         const auto* controller = GetEmulatedControllerByIndex(player_index);
         if (controller->IsConnected()) {
             return controller->GetNpadIdType();
diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h
index 196466a72c..a4a66a3a44 100644
--- a/src/core/hid/hid_core.h
+++ b/src/core/hid/hid_core.h
@@ -47,6 +47,9 @@ public:
     /// Removes all callbacks from input common
     void UnloadInputDevices();
 
+    /// Number of emulated controllers
+    const std::size_t available_controllers{10};
+
 private:
     std::unique_ptr<EmulatedController> player_1;
     std::unique_ptr<EmulatedController> player_2;
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 7320b1c0fe..134ac1ee2c 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -231,7 +231,7 @@ void AppletManager::SetDefaultAppletFrontendSet() {
 void AppletManager::SetDefaultAppletsIfMissing() {
     if (frontend.controller == nullptr) {
         frontend.controller =
-            std::make_unique<Core::Frontend::DefaultControllerApplet>(system.ServiceManager());
+            std::make_unique<Core::Frontend::DefaultControllerApplet>(system.HIDCore());
     }
 
     if (frontend.error == nullptr) {
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 6b9d6d11c3..62b324080e 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -608,15 +608,15 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
         sixaxis_fullkey_state.sampling_number =
             npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
         sixaxis_handheld_state.sampling_number =
-            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
         sixaxis_dual_left_state.sampling_number =
-            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
         sixaxis_dual_right_state.sampling_number =
-            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
         sixaxis_left_lifo_state.sampling_number =
-            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
         sixaxis_right_lifo_state.sampling_number =
-            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad.sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
 
         npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
         npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index d805ccb97a..1c6ea6f888 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -342,7 +342,7 @@ private:
         INSERT_PADDING_BYTES(0x4);
     };
 
-    // This is nn::hid::server::NpadGcTriggerState
+    // This is nn::hid::system::AppletFooterUiType
     enum class AppletFooterUiType : u8 {
         None = 0,
         HandheldNone = 1,
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 5391334f43..ac48f96d3b 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -8,7 +8,6 @@
 #include "common/settings.h"
 #include "core/core.h"
 #include "core/core_timing.h"
-#include "core/hardware_properties.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_shared_memory.h"
@@ -34,7 +33,7 @@
 namespace Service::HID {
 
 // Updating period for each HID device.
-// Period time is obtained by measuring the number of samples in a second
+// Period time is obtained by measuring the number of samples in a second on HW using a homebrew
 constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000};    // (4ms, 250Hz)
 constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
 constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp
index f0c0a6b8bf..192ab336b9 100644
--- a/src/input_common/drivers/udp_client.cpp
+++ b/src/input_common/drivers/udp_client.cpp
@@ -268,6 +268,8 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
             SetButton(identifier, touch_id, true);
             continue;
         }
+        SetAxis(identifier, touch_id * 2, 0);
+        SetAxis(identifier, touch_id * 2 + 1, 0);
         SetButton(identifier, touch_id, false);
     }
 }
diff --git a/src/input_common/drivers/udp_client.h b/src/input_common/drivers/udp_client.h
index 58b2e921d1..639325b177 100644
--- a/src/input_common/drivers/udp_client.h
+++ b/src/input_common/drivers/udp_client.h
@@ -1,6 +1,6 @@
-// Copyright 2021 yuzu Emulator Project
+// Copyright 2018 Citra Emulator Project
 // Licensed under GPLv2 or any later version
-// Refer to the license.txt file included
+// Refer to the license.txt file included.
 
 #pragma once
 
diff --git a/src/input_common/helpers/stick_from_buttons.h b/src/input_common/helpers/stick_from_buttons.h
index 1d6e24c98e..82dff5ca87 100644
--- a/src/input_common/helpers/stick_from_buttons.h
+++ b/src/input_common/helpers/stick_from_buttons.h
@@ -1,4 +1,3 @@
-
 // Copyright 2017 Citra Emulator Project
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index b048783c91..8f7ce59b78 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -87,25 +87,30 @@ struct InputSubsystem::Impl {
 
     void Shutdown() {
         Input::UnregisterFactory<Input::InputDevice>(keyboard->GetEngineName());
+        Input::UnregisterFactory<Input::OutputDevice>(keyboard->GetEngineName());
         keyboard.reset();
 
         Input::UnregisterFactory<Input::InputDevice>(mouse->GetEngineName());
+        Input::UnregisterFactory<Input::OutputDevice>(mouse->GetEngineName());
         mouse.reset();
 
         Input::UnregisterFactory<Input::InputDevice>(touch_screen->GetEngineName());
         touch_screen.reset();
 
         Input::UnregisterFactory<Input::InputDevice>(gcadapter->GetEngineName());
+        Input::UnregisterFactory<Input::OutputDevice>(gcadapter->GetEngineName());
         gcadapter.reset();
 
         Input::UnregisterFactory<Input::InputDevice>(udp_client->GetEngineName());
         udp_client.reset();
 
         Input::UnregisterFactory<Input::InputDevice>(tas_input->GetEngineName());
+        Input::UnregisterFactory<Input::OutputDevice>(tas_input->GetEngineName());
         tas_input.reset();
 
 #ifdef HAVE_SDL2
         Input::UnregisterFactory<Input::InputDevice>(sdl->GetEngineName());
+        Input::UnregisterFactory<Input::OutputDevice>(sdl->GetEngineName());
         sdl.reset();
 #endif
 
@@ -124,8 +129,6 @@ struct InputSubsystem::Impl {
         devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end());
         auto gcadapter_devices = gcadapter->GetInputDevices();
         devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end());
-        auto tas_input_devices = tas_input->GetInputDevices();
-        devices.insert(devices.end(), tas_input_devices.begin(), tas_input_devices.end());
 #ifdef HAVE_SDL2
         auto sdl_devices = sdl->GetInputDevices();
         devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());

From 21819da8cd7da60be8f8ba82dc940c2496a5317e Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Fri, 22 Oct 2021 12:34:44 -0500
Subject: [PATCH 46/88] yuzu: Fix loading input profiles

---
 src/core/hid/motion_input.cpp                     | 2 ++
 src/yuzu/configuration/configure_input_player.cpp | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/src/core/hid/motion_input.cpp b/src/core/hid/motion_input.cpp
index 93f37b77bd..c25fea966b 100644
--- a/src/core/hid/motion_input.cpp
+++ b/src/core/hid/motion_input.cpp
@@ -73,6 +73,8 @@ void MotionInput::UpdateRotation(u64 elapsed_time) {
     rotations += gyro * sample_period;
 }
 
+// Based on Madgwick's implementation of Mayhony's AHRS algorithm.
+// https://github.com/xioTechnologies/Open-Source-AHRS-With-x-IMU/blob/master/x-IMU%20IMU%20and%20AHRS%20Algorithms/x-IMU%20IMU%20and%20AHRS%20Algorithms/AHRS/MahonyAHRS.cs
 void MotionInput::UpdateOrientation(u64 elapsed_time) {
     if (!IsCalibrated(0.1f)) {
         ResetOrientation();
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 81310a5b3b..cd33b57118 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -598,8 +598,15 @@ void ConfigureInputPlayer::RetranslateUI() {
 }
 
 void ConfigureInputPlayer::LoadConfiguration() {
+    emulated_controller->ReloadFromSettings();
+
     UpdateUI();
     UpdateInputDeviceCombobox();
+
+    if (debug) {
+        return;
+    }
+
     const int comboBoxIndex = GetIndexFromControllerType(emulated_controller->GetNpadType(true));
     ui->comboControllerType->setCurrentIndex(comboBoxIndex);
     ui->groupConnectedController->setChecked(emulated_controller->IsConnected(true));

From e2e5f1beaf602f801bdd93d24c3cfc7862131890 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Fri, 22 Oct 2021 22:31:37 -0500
Subject: [PATCH 47/88] service/hid: Match shared memory closer to HW

---
 src/core/hle/service/hid/controllers/npad.cpp | 58 +++++++++++++------
 src/core/hle/service/hid/controllers/npad.h   | 43 +++++++++++---
 2 files changed, 75 insertions(+), 26 deletions(-)

diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 62b324080e..aad298364c 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -123,8 +123,8 @@ Controller_NPad::~Controller_NPad() {
 void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
                                        std::size_t controller_idx) {
     if (type == Core::HID::ControllerTriggerType::All) {
-        ControllerUpdate(Core::HID::ControllerTriggerType::Type, controller_idx);
         ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
+        ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
         return;
     }
 
@@ -139,11 +139,15 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
         }
         UpdateControllerAt(npad_type, controller_idx, is_connected);
         break;
-    case Core::HID::ControllerTriggerType::Type: {
-        if (npad_type == controller.npad_type) {
+    case Core::HID::ControllerTriggerType::Battery: {
+        if (!controller.is_connected) {
             return;
         }
-        // UpdateControllerAt(npad_type, controller_idx, is_connected);
+        auto& shared_memory = controller.shared_memory_entry;
+        const auto& battery_level = controller.device->GetBattery();
+        shared_memory.battery_level_dual = battery_level.dual.battery_level;
+        shared_memory.battery_level_left = battery_level.left.battery_level;
+        shared_memory.battery_level_right = battery_level.right.battery_level;
         break;
     }
     default:
@@ -153,7 +157,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
 
 void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
     auto& controller = controller_data[controller_idx];
-    LOG_ERROR(Service_HID, "Connect {} {}", controller_idx, controller.is_connected);
+    LOG_WARNING(Service_HID, "Connect {} {}", controller_idx, controller.is_connected);
     const auto controller_type = controller.device->GetNpadType();
     auto& shared_memory = controller.shared_memory_entry;
     if (controller_type == Core::HID::NpadType::None) {
@@ -277,20 +281,29 @@ void Controller_NPad::OnInit() {
     std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
                 npad_id_list.size() * sizeof(u32));
 
-    for (std::size_t i = 0; i < controller_data.size(); ++i) {
-        auto& controller = controller_data[i].device;
-        if (controller->IsConnected()) {
-            AddNewControllerAt(controller->GetNpadType(), i);
-        }
-    }
-
     // Prefill controller buffers
     for (auto& controller : controller_data) {
         auto& npad = controller.shared_memory_entry;
+        npad.fullkey_color = {
+            .attribute = ColorAttribute::NoController,
+        };
+        npad.joycon_color = {
+            .attribute = ColorAttribute::NoController,
+        };
+        // HW seems to initialize the first 19 entries
         for (std::size_t i = 0; i < 19; ++i) {
             WriteEmptyEntry(npad);
         }
     }
+
+    // Connect controllers
+    for (auto& controller : controller_data) {
+        const auto& device = controller.device;
+        if (device->IsConnected()) {
+            const std::size_t index = Core::HID::NpadIdTypeToIndex(device->GetNpadIdType());
+            AddNewControllerAt(device->GetNpadType(), index);
+        }
+    }
 }
 
 void Controller_NPad::WriteEmptyEntry(NpadInternalState& npad) {
@@ -618,8 +631,14 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
         sixaxis_right_lifo_state.sampling_number =
             npad.sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
 
-        npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
-        npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
+        if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
+            // This buffer only is updated on handheld on HW
+            npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
+        } else {
+            // Hanheld doesn't update this buffer on HW
+            npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
+        }
+
         npad.sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
         npad.sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
         npad.sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
@@ -864,7 +883,6 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t n
     }
 
     controller.device->SetNpadType(type);
-    controller.device->Connect();
     InitNewlyAddedController(npad_index);
 }
 
@@ -874,7 +892,7 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) {
 
 void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
     auto& controller = controller_data[npad_index];
-    LOG_ERROR(Service_HID, "Disconnect {} {}", npad_index, controller.is_connected);
+    LOG_WARNING(Service_HID, "Disconnect {} {}", npad_index, controller.is_connected);
     for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
         // Send an empty vibration to stop any vibrations.
         VibrateControllerAtIndex(npad_index, device_idx, {});
@@ -889,8 +907,12 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
     shared_memory_entry.battery_level_dual = 0;
     shared_memory_entry.battery_level_left = 0;
     shared_memory_entry.battery_level_right = 0;
-    shared_memory_entry.fullkey_color = {};
-    shared_memory_entry.joycon_color = {};
+    shared_memory_entry.fullkey_color = {
+        .attribute = ColorAttribute::NoController,
+    };
+    shared_memory_entry.joycon_color = {
+        .attribute = ColorAttribute::NoController,
+    };
     shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual;
     shared_memory_entry.footer_type = AppletFooterUiType::None;
 
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 1c6ea6f888..7c534a32f9 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -334,10 +334,7 @@ private:
         };
     };
 
-    struct NfcXcdHandle {
-        INSERT_PADDING_BYTES(0x60);
-    };
-
+    // This is nn::hid::system::AppletFooterUiAttributesSet
     struct AppletFooterUiAttributes {
         INSERT_PADDING_BYTES(0x4);
     };
@@ -368,6 +365,31 @@ private:
         Lagon = 21,
     };
 
+    // This is nn::hid::NpadLarkType
+    enum class NpadLarkType : u32 {
+        Invalid,
+        H1,
+        H2,
+        NL,
+        NR,
+    };
+
+    // This is nn::hid::NpadLuciaType
+    enum class NpadLuciaType : u32 {
+        Invalid,
+        J,
+        E,
+        U,
+    };
+
+    // This is nn::hid::NpadLagerType
+    enum class NpadLagerType : u32 {
+        Invalid,
+        J,
+        E,
+        U,
+    };
+
     // This is nn::hid::detail::NpadInternalState
     struct NpadInternalState {
         Core::HID::NpadStyleTag style_set;
@@ -396,11 +418,16 @@ private:
         Core::HID::BatteryLevel battery_level_right;
         AppletFooterUiAttributes footer_attributes;
         AppletFooterUiType footer_type;
-        // nfc_states needs to be checked switchbrew doesn't match with HW
-        NfcXcdHandle nfc_states;
-        INSERT_PADDING_BYTES(0x18); // Unknown
+        // GetXcdHandleForNpadWithNfc needs to be checked switchbrew doesn't match with HW
+        INSERT_PADDING_BYTES(0x78); // Unknown
         Lifo<NpadGcTriggerState> gc_trigger_lifo;
-        INSERT_PADDING_BYTES(0xc1f); // Unknown
+        NpadLarkType lark_type_l;
+        NpadLarkType lark_type_r;
+        NpadLuciaType lucia_type;
+        NpadLagerType lager_type;
+        INSERT_PADDING_BYTES(
+            0x8); // FW 13.x Investigate there is some sort of bitflag related to joycons
+        INSERT_PADDING_BYTES(0xc08); // Unknown
     };
     static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
 

From b564f024f0be5023cf13fb2fca953ea6c1feeeb6 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Fri, 22 Oct 2021 23:04:06 -0500
Subject: [PATCH 48/88] Morph review first wave

---
 src/core/core.h                               |  2 +-
 src/core/frontend/applets/controller.cpp      |  5 +-
 src/core/hid/emulated_console.cpp             |  4 +-
 src/core/hid/emulated_console.h               | 10 ++--
 src/core/hid/emulated_controller.cpp          |  6 +--
 src/core/hid/emulated_controller.h            | 22 ++++-----
 src/core/hid/emulated_devices.cpp             |  4 +-
 src/core/hid/hid_core.cpp                     |  8 ++--
 src/core/hid/hid_types.h                      | 48 +++++++++----------
 src/core/hid/input_converter.cpp              | 12 ++---
 .../service/hid/controllers/console_sixaxis.h | 14 +++---
 .../hle/service/hid/controllers/debug_pad.h   |  4 +-
 .../hle/service/hid/controllers/gesture.cpp   |  9 ++--
 .../hle/service/hid/controllers/gesture.h     | 33 ++++++-------
 .../hle/service/hid/controllers/keyboard.h    |  2 +-
 src/core/hle/service/hid/controllers/npad.cpp |  4 +-
 src/core/hle/service/hid/controllers/npad.h   | 22 ++++-----
 .../hle/service/hid/controllers/stubbed.h     |  8 ++--
 .../service/hid/controllers/touchscreen.cpp   |  4 +-
 .../hle/service/hid/controllers/touchscreen.h | 14 ++----
 src/core/hle/service/hid/controllers/xpad.h   |  6 +--
 src/core/hle/service/hid/ring_lifo.h          | 10 ++--
 .../configure_input_player_widget.cpp         |  2 +-
 23 files changed, 117 insertions(+), 136 deletions(-)

diff --git a/src/core/core.h b/src/core/core.h
index 5a031efb0b..645e5c241c 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -289,7 +289,7 @@ public:
     /// Provides a constant reference to the kernel instance.
     [[nodiscard]] const Kernel::KernelCore& Kernel() const;
 
-    /// Gets a mutable reference to the HID interface
+    /// Gets a mutable reference to the HID interface.
     [[nodiscard]] HID::HIDCore& HIDCore();
 
     /// Gets an immutable reference to the HID interface.
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp
index 30500ef1ef..212ace8924 100644
--- a/src/core/frontend/applets/controller.cpp
+++ b/src/core/frontend/applets/controller.cpp
@@ -13,8 +13,7 @@ namespace Core::Frontend {
 
 ControllerApplet::~ControllerApplet() = default;
 
-DefaultControllerApplet::DefaultControllerApplet(HID::HIDCore& hid_core_)
-    : hid_core{hid_core_} {}
+DefaultControllerApplet::DefaultControllerApplet(HID::HIDCore& hid_core_) : hid_core{hid_core_} {}
 
 DefaultControllerApplet::~DefaultControllerApplet() = default;
 
@@ -26,7 +25,7 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
         parameters.enable_single_mode ? 1 : parameters.min_players;
 
     // Disconnect Handheld first.
-    auto* handheld =hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
+    auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
     handheld->Disconnect();
 
     // Deduce the best configuration based on the input parameters.
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index 540fd107be..d1d4a5355c 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -6,7 +6,7 @@
 #include "core/hid/input_converter.h"
 
 namespace Core::HID {
-EmulatedConsole::EmulatedConsole() {}
+EmulatedConsole::EmulatedConsole() = default;
 
 EmulatedConsole::~EmulatedConsole() = default;
 
@@ -191,7 +191,7 @@ TouchFingerState EmulatedConsole::GetTouch() const {
 }
 
 void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) {
-    for (const std::pair<int, ConsoleUpdateCallback> poller_pair : callback_list) {
+    for (const auto& poller_pair : callback_list) {
         const ConsoleUpdateCallback& poller = poller_pair.second;
         if (poller.on_change) {
             poller.on_change(type);
diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h
index c48d25794f..f26f24f2ec 100644
--- a/src/core/hid/emulated_console.h
+++ b/src/core/hid/emulated_console.h
@@ -20,7 +20,7 @@
 namespace Core::HID {
 
 struct ConsoleMotionInfo {
-    Input::MotionStatus raw_status;
+    Input::MotionStatus raw_status{};
     MotionInput emulated{};
 };
 
@@ -34,21 +34,21 @@ using ConsoleMotionValues = ConsoleMotionInfo;
 using TouchValues = std::array<Input::TouchStatus, 16>;
 
 struct TouchFinger {
-    u64_le last_touch{};
+    u64 last_touch{};
     Common::Point<float> position{};
-    u32_le id{};
-    bool pressed{};
+    u32 id{};
     TouchAttribute attribute{};
+    bool pressed{};
 };
 
 // Contains all motion related data that is used on the services
 struct ConsoleMotion {
-    bool is_at_rest{};
     Common::Vec3f accel{};
     Common::Vec3f gyro{};
     Common::Vec3f rotation{};
     std::array<Common::Vec3f, 3> orientation{};
     Common::Quaternion<f32> quaternion{};
+    bool is_at_rest{};
 };
 
 using TouchFingerState = std::array<TouchFinger, 16>;
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index d59758e999..228f801833 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -865,10 +865,10 @@ BatteryLevelState EmulatedController::GetBattery() const {
     return controller.battery_state;
 }
 
-void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_service_update) {
-    for (const std::pair<int, ControllerUpdateCallback> poller_pair : callback_list) {
+void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) {
+    for (const auto& poller_pair : callback_list) {
         const ControllerUpdateCallback& poller = poller_pair.second;
-        if (!is_service_update && poller.is_service) {
+        if (!is_npad_service_update && poller.is_npad_service) {
             continue;
         }
         if (poller.on_change) {
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 50f21ccd9c..d667685493 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -20,7 +20,7 @@
 namespace Core::HID {
 
 struct ControllerMotionInfo {
-    Input::MotionStatus raw_status;
+    Input::MotionStatus raw_status{};
     MotionInput emulated{};
 };
 
@@ -51,28 +51,28 @@ using BatteryValues = std::array<Input::BatteryStatus, 3>;
 using VibrationValues = std::array<Input::VibrationStatus, 2>;
 
 struct AnalogSticks {
-    AnalogStickState left;
-    AnalogStickState right;
+    AnalogStickState left{};
+    AnalogStickState right{};
 };
 
 struct ControllerColors {
-    NpadControllerColor fullkey;
-    NpadControllerColor left;
-    NpadControllerColor right;
+    NpadControllerColor fullkey{};
+    NpadControllerColor left{};
+    NpadControllerColor right{};
 };
 
 struct BatteryLevelState {
-    NpadPowerInfo dual;
-    NpadPowerInfo left;
-    NpadPowerInfo right;
+    NpadPowerInfo dual{};
+    NpadPowerInfo left{};
+    NpadPowerInfo right{};
 };
 
 struct ControllerMotion {
-    bool is_at_rest;
     Common::Vec3f accel{};
     Common::Vec3f gyro{};
     Common::Vec3f rotation{};
     std::array<Common::Vec3f, 3> orientation{};
+    bool is_at_rest{};
 };
 
 using MotionState = std::array<ControllerMotion, 2>;
@@ -113,7 +113,7 @@ enum class ControllerTriggerType {
 
 struct ControllerUpdateCallback {
     std::function<void(ControllerTriggerType)> on_change;
-    bool is_service;
+    bool is_npad_service;
 };
 
 class EmulatedController {
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
index 54a753d8a5..1c4065cd85 100644
--- a/src/core/hid/emulated_devices.cpp
+++ b/src/core/hid/emulated_devices.cpp
@@ -9,7 +9,7 @@
 
 namespace Core::HID {
 
-EmulatedDevices::EmulatedDevices() {}
+EmulatedDevices::EmulatedDevices() = default;
 
 EmulatedDevices::~EmulatedDevices() = default;
 
@@ -332,7 +332,7 @@ MousePosition EmulatedDevices::GetMousePosition() const {
 }
 
 void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) {
-    for (const std::pair<int, InterfaceUpdateCallback> poller_pair : callback_list) {
+    for (const auto& poller_pair : callback_list) {
         const InterfaceUpdateCallback& poller = poller_pair.second;
         if (poller.on_change) {
             poller.on_change(type);
diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp
index cc1b3c2950..3cb26e1e71 100644
--- a/src/core/hid/hid_core.cpp
+++ b/src/core/hid/hid_core.cpp
@@ -113,8 +113,8 @@ NpadStyleTag HIDCore::GetSupportedStyleTag() const {
 
 s8 HIDCore::GetPlayerCount() const {
     s8 active_players = 0;
-    for (std::size_t player_index = 0; player_index < available_controllers -2; player_index++) {
-        const auto* controller = GetEmulatedControllerByIndex(player_index);
+    for (std::size_t player_index = 0; player_index < available_controllers - 2; ++player_index) {
+        const auto* const controller = GetEmulatedControllerByIndex(player_index);
         if (controller->IsConnected()) {
             active_players++;
         }
@@ -123,8 +123,8 @@ s8 HIDCore::GetPlayerCount() const {
 }
 
 NpadIdType HIDCore::GetFirstNpadId() const {
-    for (std::size_t player_index = 0; player_index < available_controllers; player_index++) {
-        const auto* controller = GetEmulatedControllerByIndex(player_index);
+    for (std::size_t player_index = 0; player_index < available_controllers; ++player_index) {
+        const auto* const controller = GetEmulatedControllerByIndex(player_index);
         if (controller->IsConnected()) {
             return controller->GetNpadIdType();
         }
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 539436283d..59ec593b84 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -100,7 +100,7 @@ enum class NpadType : u8 {
 // This is nn::hid::NpadStyleTag
 struct NpadStyleTag {
     union {
-        u32_le raw{};
+        u32 raw{};
 
         BitField<0, 1, u32> fullkey;
         BitField<1, 1, u32> handheld;
@@ -132,35 +132,35 @@ static_assert(sizeof(TouchAttribute) == 0x4, "TouchAttribute is an invalid size"
 
 // This is nn::hid::TouchState
 struct TouchState {
-    u64_le delta_time;
+    u64 delta_time;
     TouchAttribute attribute;
-    u32_le finger;
-    Common::Point<u32_le> position;
-    u32_le diameter_x;
-    u32_le diameter_y;
-    u32_le rotation_angle;
+    u32 finger;
+    Common::Point<u32> position;
+    u32 diameter_x;
+    u32 diameter_y;
+    u32 rotation_angle;
 };
 static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
 
 // This is nn::hid::NpadControllerColor
 struct NpadControllerColor {
-    u32_le body;
-    u32_le button;
+    u32 body;
+    u32 button;
 };
 static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size");
 
 // This is nn::hid::AnalogStickState
 struct AnalogStickState {
-    s32_le x;
-    s32_le y;
+    s32 x;
+    s32 y;
 };
 static_assert(sizeof(AnalogStickState) == 8, "AnalogStickState is an invalid size");
 
 // This is nn::hid::server::NpadGcTriggerState
 struct NpadGcTriggerState {
-    s64_le sampling_number{};
-    s32_le left{};
-    s32_le right{};
+    s64 sampling_number{};
+    s32 left{};
+    s32 right{};
 };
 static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
 
@@ -286,7 +286,7 @@ static_assert(sizeof(NpadButtonState) == 0x8, "NpadButtonState has incorrect siz
 // This is nn::hid::DebugPadButton
 struct DebugPadButton {
     union {
-        u32_le raw{};
+        u32 raw{};
         BitField<0, 1, u32> a;
         BitField<1, 1, u32> b;
         BitField<2, 1, u32> x;
@@ -345,7 +345,7 @@ static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incor
 // This is nn::hid::KeyboardModifier
 struct KeyboardModifier {
     union {
-        u32_le raw{};
+        u32 raw{};
         BitField<0, 1, u32> control;
         BitField<1, 1, u32> shift;
         BitField<2, 1, u32> left_alt;
@@ -383,7 +383,7 @@ static_assert(sizeof(MouseButton) == 0x4, "MouseButton is an invalid size");
 // This is nn::hid::MouseAttribute
 struct MouseAttribute {
     union {
-        u32_le raw{};
+        u32 raw{};
         BitField<0, 1, u32> transferable;
         BitField<1, 1, u32> is_connected;
     };
@@ -392,13 +392,13 @@ static_assert(sizeof(MouseAttribute) == 0x4, "MouseAttribute is an invalid size"
 
 // This is nn::hid::detail::MouseState
 struct MouseState {
-    s64_le sampling_number;
-    s32_le x;
-    s32_le y;
-    s32_le delta_x;
-    s32_le delta_y;
-    s32_le delta_wheel_x;
-    s32_le delta_wheel_y;
+    s64 sampling_number;
+    s32 x;
+    s32 y;
+    s32 delta_x;
+    s32 delta_y;
+    s32 delta_wheel_x;
+    s32 delta_wheel_y;
     MouseButton button;
     MouseAttribute attribute;
 };
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index 128a48ec91..b3c8913cea 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -142,8 +142,8 @@ Input::StickStatus TransformToStick(const Input::CallbackStatus& callback) {
     }
 
     SanitizeStick(status.x, status.y, true);
-    const Input::AnalogProperties& properties_x = status.x.properties;
-    const Input::AnalogProperties& properties_y = status.y.properties;
+    const auto& properties_x = status.x.properties;
+    const auto& properties_y = status.y.properties;
     const float x = status.x.value;
     const float y = status.y.value;
 
@@ -213,7 +213,7 @@ Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback) {
     }
 
     SanitizeAnalog(status.analog, true);
-    const Input::AnalogProperties& properties = status.analog.properties;
+    const auto& properties = status.analog.properties;
     float& value = status.analog.value;
 
     // Set button status
@@ -231,7 +231,7 @@ Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback) {
 }
 
 void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value) {
-    const Input::AnalogProperties& properties = analog.properties;
+    const auto& properties = analog.properties;
     float& raw_value = analog.raw_value;
     float& value = analog.value;
 
@@ -271,8 +271,8 @@ void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value) {
 }
 
 void SanitizeStick(Input::AnalogStatus& analog_x, Input::AnalogStatus& analog_y, bool clamp_value) {
-    const Input::AnalogProperties& properties_x = analog_x.properties;
-    const Input::AnalogProperties& properties_y = analog_y.properties;
+    const auto& properties_x = analog_x.properties;
+    const auto& properties_y = analog_y.properties;
     float& raw_x = analog_x.raw_value;
     float& raw_y = analog_y.raw_value;
     float& x = analog_x.value;
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h
index 6d18d2ce07..95729e6b23 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.h
@@ -35,8 +35,8 @@ public:
 private:
     struct SevenSixAxisState {
         INSERT_PADDING_WORDS(4); // unused
-        s64_le sampling_number{};
-        s64_le sampling_number2{};
+        s64 sampling_number{};
+        s64 sampling_number2{};
         u64 unknown{};
         Common::Vec3f accel{};
         Common::Vec3f gyro{};
@@ -45,10 +45,10 @@ private:
     static_assert(sizeof(SevenSixAxisState) == 0x50, "SevenSixAxisState is an invalid size");
 
     struct CommonHeader {
-        s64_le timestamp;
-        s64_le total_entry_count;
-        s64_le last_entry_index;
-        s64_le entry_count;
+        s64 timestamp;
+        s64 total_entry_count;
+        s64 last_entry_index;
+        s64 entry_count;
     };
     static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
 
@@ -61,7 +61,7 @@ private:
 
     // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
     struct ConsoleSharedMemory {
-        u64_le sampling_number{};
+        u64 sampling_number{};
         bool is_seven_six_axis_sensor_at_rest{};
         f32 verticalization_error{};
         Common::Vec3f gyro_bias{};
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 11b6c669b4..bd0f15eaa6 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -38,7 +38,7 @@ private:
     // This is nn::hid::DebugPadAttribute
     struct DebugPadAttribute {
         union {
-            u32_le raw{};
+            u32 raw{};
             BitField<0, 1, u32> connected;
         };
     };
@@ -46,7 +46,7 @@ private:
 
     // This is nn::hid::DebugPadState
     struct DebugPadState {
-        s64_le sampling_number;
+        s64 sampling_number;
         DebugPadAttribute attribute;
         Core::HID::DebugPadButton pad_state;
         Core::HID::AnalogStickState r_stick;
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index a82d04b3b9..7a7bc68a2a 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -65,10 +65,7 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
 void Controller_Gesture::ReadTouchInput() {
     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;
+        fingers[id] = touch_status[id];
     }
 }
 
@@ -315,14 +312,14 @@ const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry(
 
 Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() {
     GestureProperties gesture;
-    std::array<Finger, MAX_POINTS> active_fingers;
+    std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers;
     const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
                                        [](const auto& finger) { return finger.pressed; });
     gesture.active_points =
         static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
 
     for (size_t id = 0; id < gesture.active_points; ++id) {
-        const auto& [active_x, active_y] = active_fingers[id].pos;
+        const auto& [active_x, active_y] = active_fingers[id].position;
         gesture.points[id] = {
             .x = static_cast<s32>(active_x * Layout::ScreenUndocked::Width),
             .y = static_cast<s32>(active_y * Layout::ScreenUndocked::Height),
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 6f5abaa4fa..58139a5cf9 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -60,7 +60,7 @@ private:
     // This is nn::hid::GestureAttribute
     struct GestureAttribute {
         union {
-            u32_le raw{};
+            u32 raw{};
 
             BitField<4, 1, u32> is_new_touch;
             BitField<8, 1, u32> is_double_tap;
@@ -70,33 +70,28 @@ private:
 
     // This is nn::hid::GestureState
     struct GestureState {
-        s64_le sampling_number;
-        s64_le detection_count;
+        s64 sampling_number;
+        s64 detection_count;
         GestureType type;
         GestureDirection direction;
-        Common::Point<s32_le> pos;
-        Common::Point<s32_le> delta;
+        Common::Point<s32> pos;
+        Common::Point<s32> delta;
         f32 vel_x;
         f32 vel_y;
         GestureAttribute attributes;
         f32 scale;
         f32 rotation_angle;
-        s32_le point_count;
-        std::array<Common::Point<s32_le>, 4> points;
+        s32 point_count;
+        std::array<Common::Point<s32>, 4> points;
     };
     static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
 
-    struct Finger {
-        Common::Point<f32> pos{};
-        bool pressed{};
-    };
-
     struct GestureProperties {
-        std::array<Common::Point<s32_le>, MAX_POINTS> points{};
+        std::array<Common::Point<s32>, MAX_POINTS> points{};
         std::size_t active_points{};
-        Common::Point<s32_le> mid_point{};
-        s64_le detection_count{};
-        u64_le delta_time{};
+        Common::Point<s32> mid_point{};
+        s64 detection_count{};
+        u64 delta_time{};
         f32 average_distance{};
         f32 angle{};
     };
@@ -150,10 +145,10 @@ private:
 
     Core::HID::EmulatedConsole* console;
 
-    std::array<Finger, MAX_POINTS> fingers{};
+    std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{};
     GestureProperties last_gesture{};
-    s64_le last_update_timestamp{};
-    s64_le last_tap_timestamp{};
+    s64 last_update_timestamp{};
+    s64 last_tap_timestamp{};
     f32 last_pan_time_difference{};
     bool force_update{false};
     bool enable_press_and_tap{false};
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index 6919e092a2..aba4f123ec 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -37,7 +37,7 @@ public:
 private:
     // This is nn::hid::detail::KeyboardState
     struct KeyboardState {
-        s64_le sampling_number;
+        s64 sampling_number;
         Core::HID::KeyboardModifier modifier;
         Core::HID::KeyboardKey key;
     };
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index aad298364c..7bf31f63a8 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -106,7 +106,7 @@ Controller_NPad::Controller_NPad(Core::System& system_,
         Core::HID::ControllerUpdateCallback engine_callback{
             .on_change = [this,
                           i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
-            .is_service = true,
+            .is_npad_service = true,
         };
         controller.callback_key = controller.device->SetCallback(engine_callback);
     }
@@ -157,7 +157,6 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
 
 void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
     auto& controller = controller_data[controller_idx];
-    LOG_WARNING(Service_HID, "Connect {} {}", controller_idx, controller.is_connected);
     const auto controller_type = controller.device->GetNpadType();
     auto& shared_memory = controller.shared_memory_entry;
     if (controller_type == Core::HID::NpadType::None) {
@@ -892,7 +891,6 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) {
 
 void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
     auto& controller = controller_data[npad_index];
-    LOG_WARNING(Service_HID, "Disconnect {} {}", npad_index, controller.is_connected);
     for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
         // Send an empty vibration to stop any vibrations.
         VibrateControllerAtIndex(npad_index, device_idx, {});
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 7c534a32f9..0a2dc69920 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -195,7 +195,7 @@ public:
 
 private:
     // This is nn::hid::detail::ColorAttribute
-    enum class ColorAttribute : u32_le {
+    enum class ColorAttribute : u32 {
         Ok = 0,
         ReadError = 1,
         NoController = 2,
@@ -220,7 +220,7 @@ private:
     // This is nn::hid::NpadAttribute
     struct NpadAttribute {
         union {
-            u32_le raw{};
+            u32 raw{};
             BitField<0, 1, u32> is_connected;
             BitField<1, 1, u32> is_wired;
             BitField<2, 1, u32> is_left_connected;
@@ -251,7 +251,7 @@ private:
     // This is nn::hid::SixAxisSensorAttribute
     struct SixAxisSensorAttribute {
         union {
-            u32_le raw{};
+            u32 raw{};
             BitField<0, 1, u32> is_connected;
             BitField<1, 1, u32> is_interpolated;
         };
@@ -260,8 +260,8 @@ private:
 
     // This is nn::hid::SixAxisSensorState
     struct SixAxisSensorState {
-        s64_le delta_time{};
-        s64_le sampling_number{};
+        s64 delta_time{};
+        s64 sampling_number{};
         Common::Vec3f accel{};
         Common::Vec3f gyro{};
         Common::Vec3f rotation{};
@@ -273,16 +273,16 @@ private:
 
     // This is nn::hid::server::NpadGcTriggerState
     struct NpadGcTriggerState {
-        s64_le sampling_number{};
-        s32_le l_analog{};
-        s32_le r_analog{};
+        s64 sampling_number{};
+        s32 l_analog{};
+        s32 r_analog{};
     };
     static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
 
     // This is nn::hid::NpadSystemProperties
     struct NPadSystemProperties {
         union {
-            s64_le raw{};
+            s64 raw{};
             BitField<0, 1, s64> is_charging_joy_dual;
             BitField<1, 1, s64> is_charging_joy_left;
             BitField<2, 1, s64> is_charging_joy_right;
@@ -303,7 +303,7 @@ private:
     // This is nn::hid::NpadSystemButtonProperties
     struct NpadSystemButtonProperties {
         union {
-            s32_le raw{};
+            s32 raw{};
             BitField<0, 1, s32> is_home_button_protection_enabled;
         };
     };
@@ -313,7 +313,7 @@ private:
     // This is nn::hid::system::DeviceType
     struct DeviceType {
         union {
-            u32_le raw{};
+            u32 raw{};
             BitField<0, 1, s32> fullkey;
             BitField<1, 1, s32> debug_pad;
             BitField<2, 1, s32> handheld_left;
diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h
index 29f95a1006..10aecad4ca 100644
--- a/src/core/hle/service/hid/controllers/stubbed.h
+++ b/src/core/hle/service/hid/controllers/stubbed.h
@@ -26,10 +26,10 @@ public:
 
 private:
     struct CommonHeader {
-        s64_le timestamp;
-        s64_le total_entry_count;
-        s64_le last_entry_index;
-        s64_le entry_count;
+        s64 timestamp;
+        s64 total_entry_count;
+        s64 last_entry_index;
+        s64 entry_count;
     };
     static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
 
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index e0a44d06b2..5ba8d96a83 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -66,7 +66,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
         }
     }
 
-    std::array<Finger, MAX_FINGERS> active_fingers;
+    std::array<Core::HID::TouchFinger, MAX_FINGERS> active_fingers;
     const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
                                        [](const auto& finger) { return finger.pressed; });
     const auto active_fingers_count =
@@ -76,7 +76,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
     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);
+    next_state.entry_count = static_cast<s32>(active_fingers_count);
 
     for (std::size_t id = 0; id < MAX_FINGERS; ++id) {
         auto& touch_entry = next_state.states[id];
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index bcf79237dd..fa4dfa1a20 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -50,27 +50,19 @@ private:
 
     // This is nn::hid::TouchScreenState
     struct TouchScreenState {
-        s64_le sampling_number;
-        s32_le entry_count;
+        s64 sampling_number;
+        s32 entry_count;
         INSERT_PADDING_BYTES(4); // Reserved
         std::array<Core::HID::TouchState, MAX_FINGERS> states;
     };
     static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
 
-    struct Finger {
-        u64_le last_touch{};
-        Common::Point<float> position;
-        u32_le id{};
-        bool pressed{};
-        Core::HID::TouchAttribute attribute;
-    };
-
     // 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<Core::HID::TouchFinger, MAX_FINGERS> fingers;
     Core::HID::EmulatedConsole* console;
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index a5421f93b6..75e0d29116 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -31,7 +31,7 @@ private:
     // This is nn::hid::BasicXpadAttributeSet
     struct BasicXpadAttributeSet {
         union {
-            u32_le raw{};
+            u32 raw{};
             BitField<0, 1, u32> is_connected;
             BitField<1, 1, u32> is_wired;
             BitField<2, 1, u32> is_left_connected;
@@ -45,7 +45,7 @@ private:
     // This is nn::hid::BasicXpadButtonSet
     struct BasicXpadButtonSet {
         union {
-            u32_le raw{};
+            u32 raw{};
             // Button states
             BitField<0, 1, u32> a;
             BitField<1, 1, u32> b;
@@ -93,7 +93,7 @@ private:
 
     // This is nn::hid::detail::BasicXpadState
     struct BasicXpadState {
-        s64_le sampling_number;
+        s64 sampling_number;
         BasicXpadAttributeSet attributes;
         BasicXpadButtonSet pad_states;
         Core::HID::AnalogStickState l_stick;
diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h
index 1cc2a194f0..f68d827622 100644
--- a/src/core/hle/service/hid/ring_lifo.h
+++ b/src/core/hle/service/hid/ring_lifo.h
@@ -12,16 +12,16 @@ constexpr std::size_t max_entry_size = 17;
 
 template <typename State>
 struct AtomicStorage {
-    s64_le sampling_number;
+    s64 sampling_number;
     State state;
 };
 
 template <typename State>
 struct Lifo {
-    s64_le timestamp{};
-    s64_le total_entry_count = max_entry_size;
-    s64_le last_entry_index{};
-    s64_le entry_count{};
+    s64 timestamp{};
+    s64 total_entry_count = max_entry_size;
+    s64 last_entry_index{};
+    s64 entry_count{};
     std::array<AtomicStorage<State>, max_entry_size> entries{};
 
     const AtomicStorage<State>& ReadCurrentEntry() const {
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index be87204fc3..3f179150dc 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -28,7 +28,7 @@ void PlayerControlPreview::SetController(Core::HID::EmulatedController* controll
     controller = controller_;
     Core::HID::ControllerUpdateCallback engine_callback{
         .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); },
-        .is_service = false,
+        .is_npad_service = false,
     };
     callback_key = controller->SetCallback(engine_callback);
     ControllerUpdate(Core::HID::ControllerTriggerType::All);

From cc651c7c99f04c60f1c3422fb9edc8b11e82cd51 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 24 Oct 2021 01:02:56 -0500
Subject: [PATCH 49/88] web_applet: Replace HIDButton with NpadButton

---
 src/yuzu/applets/qt_controller.cpp  |  3 +-
 src/yuzu/applets/qt_web_browser.cpp | 61 ++++++++++++++++-------------
 src/yuzu/applets/qt_web_browser.h   | 12 +++---
 3 files changed, 42 insertions(+), 34 deletions(-)

diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 32cb5b5fff..59289c6a5f 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -28,7 +28,8 @@ namespace {
 
 constexpr std::size_t HANDHELD_INDEX = 8;
 
-void UpdateController(Core::HID::EmulatedController* controller, Core::HID::NpadType controller_type, bool connected) {
+void UpdateController(Core::HID::EmulatedController* controller,
+                      Core::HID::NpadType controller_type, bool connected) {
     if (controller->IsConnected()) {
         controller->Disconnect();
     }
diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp
index 8e190f9fef..cb3c5d8268 100644
--- a/src/yuzu/applets/qt_web_browser.cpp
+++ b/src/yuzu/applets/qt_web_browser.cpp
@@ -16,6 +16,7 @@
 #include "common/fs/path_util.h"
 #include "common/param_package.h"
 #include "core/core.h"
+#include "core/hid/hid_types.h"
 #include "core/hid/input_interpreter.h"
 #include "input_common/drivers/keyboard.h"
 #include "input_common/main.h"
@@ -28,19 +29,19 @@
 
 namespace {
 
-constexpr int HIDButtonToKey(HIDButton button) {
+constexpr int HIDButtonToKey(Core::HID::NpadButton button) {
     switch (button) {
-    case HIDButton::DLeft:
-    case HIDButton::LStickLeft:
+    case Core::HID::NpadButton::Left:
+    case Core::HID::NpadButton::StickLLeft:
         return Qt::Key_Left;
-    case HIDButton::DUp:
-    case HIDButton::LStickUp:
+    case Core::HID::NpadButton::Up:
+    case Core::HID::NpadButton::StickLUp:
         return Qt::Key_Up;
-    case HIDButton::DRight:
-    case HIDButton::LStickRight:
+    case Core::HID::NpadButton::Right:
+    case Core::HID::NpadButton::StickLRight:
         return Qt::Key_Right;
-    case HIDButton::DDown:
-    case HIDButton::LStickDown:
+    case Core::HID::NpadButton::Down:
+    case Core::HID::NpadButton::StickLDown:
         return Qt::Key_Down;
     default:
         return 0;
@@ -209,25 +210,25 @@ void QtNXWebEngineView::keyReleaseEvent(QKeyEvent* event) {
     }
 }
 
-template <HIDButton... T>
+template <Core::HID::NpadButton... T>
 void QtNXWebEngineView::HandleWindowFooterButtonPressedOnce() {
-    const auto f = [this](HIDButton button) {
+    const auto f = [this](Core::HID::NpadButton button) {
         if (input_interpreter->IsButtonPressedOnce(button)) {
             page()->runJavaScript(
                 QStringLiteral("yuzu_key_callbacks[%1] == null;").arg(static_cast<u8>(button)),
                 [this, button](const QVariant& variant) {
                     if (variant.toBool()) {
                         switch (button) {
-                        case HIDButton::A:
+                        case Core::HID::NpadButton::A:
                             SendMultipleKeyPressEvents<Qt::Key_A, Qt::Key_Space, Qt::Key_Return>();
                             break;
-                        case HIDButton::B:
+                        case Core::HID::NpadButton::B:
                             SendKeyPressEvent(Qt::Key_B);
                             break;
-                        case HIDButton::X:
+                        case Core::HID::NpadButton::X:
                             SendKeyPressEvent(Qt::Key_X);
                             break;
-                        case HIDButton::Y:
+                        case Core::HID::NpadButton::Y:
                             SendKeyPressEvent(Qt::Key_Y);
                             break;
                         default:
@@ -245,9 +246,9 @@ void QtNXWebEngineView::HandleWindowFooterButtonPressedOnce() {
     (f(T), ...);
 }
 
-template <HIDButton... T>
+template <Core::HID::NpadButton... T>
 void QtNXWebEngineView::HandleWindowKeyButtonPressedOnce() {
-    const auto f = [this](HIDButton button) {
+    const auto f = [this](Core::HID::NpadButton button) {
         if (input_interpreter->IsButtonPressedOnce(button)) {
             SendKeyPressEvent(HIDButtonToKey(button));
         }
@@ -256,9 +257,9 @@ void QtNXWebEngineView::HandleWindowKeyButtonPressedOnce() {
     (f(T), ...);
 }
 
-template <HIDButton... T>
+template <Core::HID::NpadButton... T>
 void QtNXWebEngineView::HandleWindowKeyButtonHold() {
-    const auto f = [this](HIDButton button) {
+    const auto f = [this](Core::HID::NpadButton button) {
         if (input_interpreter->IsButtonHeld(button)) {
             SendKeyPressEvent(HIDButtonToKey(button));
         }
@@ -309,17 +310,21 @@ void QtNXWebEngineView::InputThread() {
     while (input_thread_running) {
         input_interpreter->PollInput();
 
-        HandleWindowFooterButtonPressedOnce<HIDButton::A, HIDButton::B, HIDButton::X, HIDButton::Y,
-                                            HIDButton::L, HIDButton::R>();
+        HandleWindowFooterButtonPressedOnce<Core::HID::NpadButton::A, Core::HID::NpadButton::B,
+                                            Core::HID::NpadButton::X, Core::HID::NpadButton::Y,
+                                            Core::HID::NpadButton::L, Core::HID::NpadButton::R>();
 
-        HandleWindowKeyButtonPressedOnce<HIDButton::DLeft, HIDButton::DUp, HIDButton::DRight,
-                                         HIDButton::DDown, HIDButton::LStickLeft,
-                                         HIDButton::LStickUp, HIDButton::LStickRight,
-                                         HIDButton::LStickDown>();
+        HandleWindowKeyButtonPressedOnce<
+            Core::HID::NpadButton::Left, Core::HID::NpadButton::Up, Core::HID::NpadButton::Right,
+            Core::HID::NpadButton::Down, Core::HID::NpadButton::StickLLeft,
+            Core::HID::NpadButton::StickLUp, Core::HID::NpadButton::StickLRight,
+            Core::HID::NpadButton::StickLDown>();
 
-        HandleWindowKeyButtonHold<HIDButton::DLeft, HIDButton::DUp, HIDButton::DRight,
-                                  HIDButton::DDown, HIDButton::LStickLeft, HIDButton::LStickUp,
-                                  HIDButton::LStickRight, HIDButton::LStickDown>();
+        HandleWindowKeyButtonHold<
+            Core::HID::NpadButton::Left, Core::HID::NpadButton::Up, Core::HID::NpadButton::Right,
+            Core::HID::NpadButton::Down, Core::HID::NpadButton::StickLLeft,
+            Core::HID::NpadButton::StickLUp, Core::HID::NpadButton::StickLRight,
+            Core::HID::NpadButton::StickLDown>();
 
         std::this_thread::sleep_for(std::chrono::milliseconds(50));
     }
diff --git a/src/yuzu/applets/qt_web_browser.h b/src/yuzu/applets/qt_web_browser.h
index 7e9f703fcc..fa18aecac8 100644
--- a/src/yuzu/applets/qt_web_browser.h
+++ b/src/yuzu/applets/qt_web_browser.h
@@ -16,8 +16,6 @@
 
 #include "core/frontend/applets/web_browser.h"
 
-enum class HIDButton : u8;
-
 class GMainWindow;
 class InputInterpreter;
 class UrlRequestInterceptor;
@@ -26,6 +24,10 @@ namespace Core {
 class System;
 }
 
+namespace Core::HID {
+enum class NpadButton : u64;
+}
+
 namespace InputCommon {
 class InputSubsystem;
 }
@@ -114,7 +116,7 @@ private:
      *
      * @tparam HIDButton The list of buttons contained in yuzu_key_callbacks
      */
-    template <HIDButton... T>
+    template <Core::HID::NpadButton... T>
     void HandleWindowFooterButtonPressedOnce();
 
     /**
@@ -123,7 +125,7 @@ private:
      *
      * @tparam HIDButton The list of buttons that can be converted into keyboard input.
      */
-    template <HIDButton... T>
+    template <Core::HID::NpadButton... T>
     void HandleWindowKeyButtonPressedOnce();
 
     /**
@@ -132,7 +134,7 @@ private:
      *
      * @tparam HIDButton The list of buttons that can be converted into keyboard input.
      */
-    template <HIDButton... T>
+    template <Core::HID::NpadButton... T>
     void HandleWindowKeyButtonHold();
 
     /**

From 464c4d26ac8e7af6302390684445b357e5cda4e4 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 24 Oct 2021 11:22:20 -0500
Subject: [PATCH 50/88] settings: Fix mouse and keyboard mappings

---
 src/core/hid/emulated_controller.cpp          |   8 +-
 src/core/hid/emulated_devices.cpp             |  19 ++-
 src/core/hid/emulated_devices.h               |   3 +
 src/input_common/drivers/mouse.cpp            |  17 ++-
 src/input_common/drivers/mouse.h              |   1 +
 src/input_common/input_engine.cpp             |   2 +
 src/input_common/main.cpp                     |   3 +
 .../configuration/configure_input_player.cpp  | 143 +++++++-----------
 .../configuration/configure_vibration.cpp     |   4 +-
 src/yuzu/debugger/controller.cpp              |   3 +-
 10 files changed, 100 insertions(+), 103 deletions(-)

diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 228f801833..bd0b89c056 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -246,7 +246,7 @@ std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices() const {
             devices.begin(), devices.end(), [param](const Common::ParamPackage param_) {
                 return param.Get("engine", "") == param_.Get("engine", "") &&
                        param.Get("guid", "") == param_.Get("guid", "") &&
-                       param.Get("port", "") == param_.Get("port", "");
+                       param.Get("port", 0) == param_.Get("port", 0);
             });
         if (devices_it != devices.end()) {
             continue;
@@ -254,7 +254,7 @@ std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices() const {
         Common::ParamPackage device{};
         device.Set("engine", param.Get("engine", ""));
         device.Set("guid", param.Get("guid", ""));
-        device.Set("port", param.Get("port", ""));
+        device.Set("port", param.Get("port", 0));
         devices.push_back(device);
     }
 
@@ -269,7 +269,7 @@ std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices() const {
             devices.begin(), devices.end(), [param](const Common::ParamPackage param_) {
                 return param.Get("engine", "") == param_.Get("engine", "") &&
                        param.Get("guid", "") == param_.Get("guid", "") &&
-                       param.Get("port", "") == param_.Get("port", "");
+                       param.Get("port", 0) == param_.Get("port", 0);
             });
         if (devices_it != devices.end()) {
             continue;
@@ -277,7 +277,7 @@ std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices() const {
         Common::ParamPackage device{};
         device.Set("engine", param.Get("engine", ""));
         device.Set("guid", param.Get("guid", ""));
-        device.Set("port", param.Get("port", ""));
+        device.Set("port", param.Get("port", 0));
         devices.push_back(device);
     }
     return devices;
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
index 1c4065cd85..5afd83f62c 100644
--- a/src/core/hid/emulated_devices.cpp
+++ b/src/core/hid/emulated_devices.cpp
@@ -162,17 +162,22 @@ void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::siz
         return;
     }
 
-    // TODO(german77): Do this properly
-    // switch (index) {
-    // case Settings::NativeKeyboard::A:
-    //    interface_status.keyboard_state.a.Assign(current_status.value);
-    //    break;
-    //    ....
-    // }
+    UpdateKey(index, current_status.value);
 
     TriggerOnChange(DeviceTriggerType::Keyboard);
 }
 
+void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) {
+    constexpr u8 KEYS_PER_BYTE = 8;
+    auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE];
+    const u8 mask = 1 << (key_index % KEYS_PER_BYTE);
+    if (status) {
+        entry = entry | mask;
+    } else {
+        entry = entry & ~mask;
+    }
+}
+
 void EmulatedDevices::SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index) {
     if (index >= device_status.keyboard_moddifier_values.size()) {
         return;
diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h
index c6c19fae4e..7ed95eac6b 100644
--- a/src/core/hid/emulated_devices.h
+++ b/src/core/hid/emulated_devices.h
@@ -143,6 +143,9 @@ public:
     void DeleteCallback(int key);
 
 private:
+    /// Helps assigning a value to keyboard_state
+    void UpdateKey(std::size_t key_index, bool status);
+
     /**
      * Updates the touch status of the console
      * @param callback: A CallbackStatus containing the key status
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
index 2c2432fb72..1c32b54bea 100644
--- a/src/input_common/drivers/mouse.cpp
+++ b/src/input_common/drivers/mouse.cpp
@@ -121,12 +121,27 @@ void Mouse::StopPanning() {
 std::vector<Common::ParamPackage> Mouse::GetInputDevices() const {
     std::vector<Common::ParamPackage> devices;
     devices.emplace_back(Common::ParamPackage{
-        {"engine", "keyboard"},
+        {"engine", GetEngineName()},
         {"display", "Keyboard/Mouse"},
     });
     return devices;
 }
 
+AnalogMapping Mouse::GetAnalogMappingForDevice(
+    [[maybe_unused]] const Common::ParamPackage& params) {
+    // Only overwrite different buttons from default
+    AnalogMapping mapping = {};
+    Common::ParamPackage right_analog_params;
+    right_analog_params.Set("engine", GetEngineName());
+    right_analog_params.Set("axis_x", 0);
+    right_analog_params.Set("axis_y", 1);
+    right_analog_params.Set("threshold", 0.5f);
+    right_analog_params.Set("range", 1.0f);
+    right_analog_params.Set("deadzone", 0.0f);
+    mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params));
+    return mapping;
+}
+
 std::string Mouse::GetUIName(const Common::ParamPackage& params) const {
     if (params.Has("button")) {
         return fmt::format("Mouse {}", params.Get("button", 0));
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index e8355751a4..d3178b1a9b 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -55,6 +55,7 @@ public:
     void ReleaseAllButtons();
 
     std::vector<Common::ParamPackage> GetInputDevices() const override;
+    AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
     std::string GetUIName(const Common::ParamPackage& params) const override;
 
 private:
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp
index 1534f24b04..9cfe0f2323 100644
--- a/src/input_common/input_engine.cpp
+++ b/src/input_common/input_engine.cpp
@@ -202,6 +202,8 @@ void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int but
     if (!configuring || !mapping_callback.on_data) {
         return;
     }
+
+    PreSetButton(identifier, button);
     if (value == GetButton(identifier, button)) {
         return;
     }
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 8f7ce59b78..07d514ad73 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -143,6 +143,9 @@ struct InputSubsystem::Impl {
             return {};
         }
         const std::string engine = params.Get("engine", "");
+        if (engine == mouse->GetEngineName()) {
+            return mouse->GetAnalogMappingForDevice(params);
+        }
         if (engine == gcadapter->GetEngineName()) {
             return gcadapter->GetAnalogMappingForDevice(params);
         }
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index cd33b57118..4160963333 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -478,37 +478,39 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
     UpdateControllerEnabledButtons();
     UpdateControllerButtonNames();
     UpdateMotionButtons();
-    connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this, player_index](int) {
-        UpdateControllerAvailableButtons();
-        UpdateControllerEnabledButtons();
-        UpdateControllerButtonNames();
-        UpdateMotionButtons();
-        const Core::HID::NpadType type = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
+    connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged),
+            [this, player_index](int) {
+                UpdateControllerAvailableButtons();
+                UpdateControllerEnabledButtons();
+                UpdateControllerButtonNames();
+                UpdateMotionButtons();
+                const Core::HID::NpadType type =
+                    GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
 
-        if (player_index == 0) {
-            auto* emulated_controller_p1 =
-                system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
-            auto* emulated_controller_hanheld =
-                system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
-            bool is_connected = emulated_controller->IsConnected(true);
+                if (player_index == 0) {
+                    auto* emulated_controller_p1 =
+                        system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+                    auto* emulated_controller_hanheld =
+                        system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+                    bool is_connected = emulated_controller->IsConnected(true);
 
-            emulated_controller_p1->SetNpadType(type);
-            emulated_controller_hanheld->SetNpadType(type);
-            if (is_connected) {
-                if (type == Core::HID::NpadType::Handheld) {
-                    emulated_controller_p1->Disconnect();
-                    emulated_controller_hanheld->Connect();
-                    emulated_controller = emulated_controller_hanheld;
-                } else {
-                    emulated_controller_hanheld->Disconnect();
-                    emulated_controller_p1->Connect();
-                    emulated_controller = emulated_controller_p1;
+                    emulated_controller_p1->SetNpadType(type);
+                    emulated_controller_hanheld->SetNpadType(type);
+                    if (is_connected) {
+                        if (type == Core::HID::NpadType::Handheld) {
+                            emulated_controller_p1->Disconnect();
+                            emulated_controller_hanheld->Connect();
+                            emulated_controller = emulated_controller_hanheld;
+                        } else {
+                            emulated_controller_hanheld->Disconnect();
+                            emulated_controller_p1->Connect();
+                            emulated_controller = emulated_controller_p1;
+                        }
+                    }
+                    ui->controllerFrame->SetController(emulated_controller);
                 }
-            }
-            ui->controllerFrame->SetController(emulated_controller);
-        }
-        emulated_controller->SetNpadType(type);
-    });
+                emulated_controller->SetNpadType(type);
+            });
 
     connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
             &ConfigureInputPlayer::UpdateMappingWithDefaults);
@@ -555,7 +557,7 @@ ConfigureInputPlayer::~ConfigureInputPlayer() {
     } else {
         emulated_controller->DisableConfiguration();
     }
-};
+}
 
 void ConfigureInputPlayer::ApplyConfiguration() {
     if (player_index == 0) {
@@ -642,7 +644,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
 
     const auto first_engine = devices[0].Get("engine", "");
     const auto first_guid = devices[0].Get("guid", "");
-    const auto first_port = devices[0].Get("port", "");
+    const auto first_port = devices[0].Get("port", 0);
 
     if (devices.size() == 1) {
         const auto devices_it =
@@ -650,7 +652,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
                          [first_engine, first_guid, first_port](const Common::ParamPackage param) {
                              return param.Get("engine", "") == first_engine &&
                                     param.Get("guid", "") == first_guid &&
-                                    param.Get("port", "") == first_port;
+                                    param.Get("port", 0) == first_port;
                          });
         const int device_index =
             devices_it != input_devices.end()
@@ -662,7 +664,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
 
     const auto second_engine = devices[1].Get("engine", "");
     const auto second_guid = devices[1].Get("guid", "");
-    const auto second_port = devices[1].Get("port", "");
+    const auto second_port = devices[1].Get("port", 0);
 
     const bool is_keyboard_mouse = (first_engine == "keyboard" || first_engine == "mouse") &&
                                    (second_engine == "keyboard" || second_engine == "mouse");
@@ -684,7 +686,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
                      param.Get("guid2", "") == second_guid) ||
                     (param.Get("guid", "") == second_guid && param.Get("guid2", "") == first_guid);
                 return param.Get("engine", "") == first_engine && is_guid_valid &&
-                       param.Get("port", "") == first_port;
+                       param.Get("port", 0) == first_port;
             });
         const int device_index =
             devices_it != input_devices.end()
@@ -1096,8 +1098,8 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
         emulated_controller->SetMotionParam(motion_id, {});
     }
 
-    // Reset keyboard bindings
-    if (ui->comboDevices->currentIndex() == 1) {
+    // Reset keyboard or mouse bindings
+    if (ui->comboDevices->currentIndex() == 1 || ui->comboDevices->currentIndex() == 2) {
         for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
             emulated_controller->SetButtonParam(
                 button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
@@ -1122,63 +1124,30 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
                                Config::default_motions[motion_id])});
         }
 
-        UpdateUI();
-        return;
-    }
-
-    // Reset keyboard with mouse bindings
-    if (ui->comboDevices->currentIndex() == 2) {
-        for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
-            emulated_controller->SetButtonParam(
-                button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
-                               Config::default_buttons[button_id])});
+        // If mouse is selected we want to override with mappings from the driver
+        if (ui->comboDevices->currentIndex() == 1) {
+            UpdateUI();
+            return;
         }
-
-        Common::ParamPackage left_analog_param{};
-        for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
-            Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
-                Config::default_analogs[Settings::NativeAnalog::LStick][sub_button_id])};
-            SetAnalogParam(params, left_analog_param, analog_sub_buttons[sub_button_id]);
-        }
-        left_analog_param.Set("modifier",
-                              InputCommon::GenerateKeyboardParam(
-                                  Config::default_stick_mod[Settings::NativeAnalog::LStick]));
-        emulated_controller->SetStickParam(Settings::NativeAnalog::LStick, left_analog_param);
-
-        Common::ParamPackage right_analog_param{};
-        right_analog_param.Set("engine", "mouse");
-        right_analog_param.Set("port", 0);
-        right_analog_param.Set("axis_x", 0);
-        right_analog_param.Set("axis_y", 1);
-        emulated_controller->SetStickParam(Settings::NativeAnalog::RStick,
-                                           std::move(right_analog_param));
-
-        for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
-            emulated_controller->SetMotionParam(
-                motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
-                               Config::default_motions[motion_id])});
-        }
-
-        UpdateUI();
-        return;
     }
 
     // Reset controller bindings
     const auto& device = input_devices[ui->comboDevices->currentIndex()];
-    auto button_mapping = input_subsystem->GetButtonMappingForDevice(device);
-    auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device);
-    auto motion_mapping = input_subsystem->GetMotionMappingForDevice(device);
-    for (std::size_t i = 0; i < button_mapping.size(); ++i) {
-        emulated_controller->SetButtonParam(
-            i, button_mapping[static_cast<Settings::NativeButton::Values>(i)]);
+    auto button_mappings = input_subsystem->GetButtonMappingForDevice(device);
+    auto analog_mappings = input_subsystem->GetAnalogMappingForDevice(device);
+    auto motion_mappings = input_subsystem->GetMotionMappingForDevice(device);
+
+    for (const auto& button_mapping : button_mappings) {
+        const std::size_t index = button_mapping.first;
+        emulated_controller->SetButtonParam(index, button_mapping.second);
     }
-    for (std::size_t i = 0; i < analog_mapping.size(); ++i) {
-        emulated_controller->SetStickParam(
-            i, analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]);
+    for (const auto& analog_mapping : analog_mappings) {
+        const std::size_t index = analog_mapping.first;
+        emulated_controller->SetStickParam(index, analog_mapping.second);
     }
-    for (std::size_t i = 0; i < motion_mapping.size(); ++i) {
-        emulated_controller->SetMotionParam(
-            i, motion_mapping[static_cast<Settings::NativeMotion::Values>(i)]);
+    for (const auto& motion_mapping : motion_mappings) {
+        const std::size_t index = motion_mapping.first;
+        emulated_controller->SetMotionParam(index, motion_mapping.second);
     }
 
     UpdateUI();
@@ -1237,7 +1206,7 @@ bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params)
     }
 
     // Keyboard/Mouse
-    if (ui->comboDevices->currentIndex() == 2) {
+    if (ui->comboDevices->currentIndex() == 1 || ui->comboDevices->currentIndex() == 2) {
         return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse";
     }
 
@@ -1245,7 +1214,7 @@ bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params)
     return params.Get("engine", "") == current_input_device.Get("engine", "") &&
            (params.Get("guid", "") == current_input_device.Get("guid", "") ||
             params.Get("guid", "") == current_input_device.Get("guid2", "")) &&
-           params.Get("port", "") == current_input_device.Get("port", "");
+           params.Get("port", 0) == current_input_device.Get("port", 0);
 }
 
 void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp
index 46a0f30258..f1ce7205d5 100644
--- a/src/yuzu/configuration/configure_vibration.cpp
+++ b/src/yuzu/configuration/configure_vibration.cpp
@@ -97,7 +97,7 @@ void ConfigureVibration::SetVibrationDevices(std::size_t player_index) {
 
         const auto engine = param.Get("engine", "");
         const auto guid = param.Get("guid", "");
-        const auto port = param.Get("port", "");
+        const auto port = param.Get("port", 0);
 
         if (engine.empty() || engine == "keyboard" || engine == "mouse" || engine == "tas") {
             continue;
@@ -105,7 +105,7 @@ void ConfigureVibration::SetVibrationDevices(std::size_t player_index) {
 
         vibration_param_str += fmt::format("engine:{}", engine);
 
-        if (!port.empty()) {
+        if (port != 0) {
             vibration_param_str += fmt::format(",port:{}", port);
         }
         if (!guid.empty()) {
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
index 3619aed260..f93a46421b 100644
--- a/src/yuzu/debugger/controller.cpp
+++ b/src/yuzu/debugger/controller.cpp
@@ -21,8 +21,7 @@ ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent)
                    Qt::WindowMaximizeButtonHint);
 
     widget = new PlayerControlPreview(this);
-    widget->SetController(system.HIDCore().GetEmulatedController(
-        Core::HID::NpadIdType::Player1));
+    widget->SetController(system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1));
     QLayout* layout = new QVBoxLayout(this);
     layout->setContentsMargins(0, 0, 0, 0);
     layout->addWidget(widget);

From f01dac3bf934657059b77bae3630201110f83e3d Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 24 Oct 2021 20:27:00 -0500
Subject: [PATCH 51/88] service/hid: Fix memory allocated incorrectly

---
 src/core/hle/service/hid/controllers/debug_pad.cpp | 6 +++---
 src/core/hle/service/hid/controllers/gesture.cpp   | 2 +-
 src/core/hle/service/hid/controllers/keyboard.cpp  | 2 +-
 src/core/hle/service/hid/controllers/mouse.cpp     | 2 +-
 src/core/hle/service/hid/controllers/xpad.cpp      | 2 +-
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index b2b4edf51e..5b1946f134 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -12,7 +12,7 @@
 #include "core/hle/service/hid/controllers/debug_pad.h"
 
 namespace Service::HID {
-
+constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
 constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
 [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
 enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right };
@@ -32,7 +32,7 @@ void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing,
     if (!IsControllerActivated()) {
         debug_pad_lifo.entry_count = 0;
         debug_pad_lifo.last_entry_index = 0;
-        std::memcpy(data, &debug_pad_lifo, sizeof(debug_pad_lifo));
+        std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo));
         return;
     }
 
@@ -51,7 +51,7 @@ void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing,
     }
 
     debug_pad_lifo.WriteNextEntry(next_state);
-    std::memcpy(data, &debug_pad_lifo, sizeof(debug_pad_lifo));
+    std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo));
 }
 
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 7a7bc68a2a..47760b4f8c 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -43,7 +43,7 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
     if (!IsControllerActivated()) {
         gesture_lifo.entry_count = 0;
         gesture_lifo.last_entry_index = 0;
-        std::memcpy(data, &gesture_lifo, sizeof(gesture_lifo));
+        std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo));
         return;
     }
 
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index db0f56b927..632679a171 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -29,7 +29,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
     if (!IsControllerActivated()) {
         keyboard_lifo.entry_count = 0;
         keyboard_lifo.last_entry_index = 0;
-        std::memcpy(data, &keyboard_lifo, sizeof(keyboard_lifo));
+        std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo));
         return;
     }
 
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 2f607bfe9d..6d3bd0a2b2 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -29,7 +29,7 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
     if (!IsControllerActivated()) {
         mouse_lifo.entry_count = 0;
         mouse_lifo.last_entry_index = 0;
-        std::memcpy(data, &mouse_lifo, sizeof(mouse_lifo));
+        std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo));
         return;
     }
 
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp
index 29a412ff9e..aa9f044f19 100644
--- a/src/core/hle/service/hid/controllers/xpad.cpp
+++ b/src/core/hle/service/hid/controllers/xpad.cpp
@@ -22,7 +22,7 @@ void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
     if (!IsControllerActivated()) {
         basic_xpad_lifo.entry_count = 0;
         basic_xpad_lifo.last_entry_index = 0;
-        std::memcpy(data, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
+        std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
         return;
     }
 

From c6c32daf40ae1c720f0a2897c538bb1117371ea5 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 24 Oct 2021 20:28:54 -0500
Subject: [PATCH 52/88] input_common: Add manual update options to input
 devices

---
 src/common/input.h                            | 10 ++++++++++
 src/core/hid/emulated_controller.cpp          |  9 +++++++++
 .../helpers/stick_from_buttons.cpp            | 16 +++++++++++++++
 .../helpers/touch_from_buttons.cpp            |  1 +
 src/input_common/input_poller.cpp             | 20 +++++++++++++++++++
 5 files changed, 56 insertions(+)

diff --git a/src/common/input.h b/src/common/input.h
index cdacd46897..cb84f1005a 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -164,6 +164,16 @@ class InputDevice {
 public:
     virtual ~InputDevice() = default;
 
+    // Request input device to update if necessary
+    virtual void SoftUpdate() {
+        return;
+    }
+
+    // Force input device to update data regarless of the current state
+    virtual void ForceUpdate() {
+        return;
+    }
+
     void SetCallback(InputCallback callback_) {
         callback = std::move(callback_);
     }
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index bd0b89c056..48add394b4 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -122,6 +122,7 @@ void EmulatedController::ReloadInput() {
         Input::InputCallback button_callback{
             [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }};
         button_devices[index]->SetCallback(button_callback);
+        button_devices[index]->ForceUpdate();
     }
 
     for (std::size_t index = 0; index < stick_devices.size(); ++index) {
@@ -131,6 +132,7 @@ void EmulatedController::ReloadInput() {
         Input::InputCallback stick_callback{
             [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }};
         stick_devices[index]->SetCallback(stick_callback);
+        stick_devices[index]->ForceUpdate();
     }
 
     for (std::size_t index = 0; index < trigger_devices.size(); ++index) {
@@ -140,6 +142,7 @@ void EmulatedController::ReloadInput() {
         Input::InputCallback trigger_callback{
             [this, index](Input::CallbackStatus callback) { SetTrigger(callback, index); }};
         trigger_devices[index]->SetCallback(trigger_callback);
+        trigger_devices[index]->ForceUpdate();
     }
 
     for (std::size_t index = 0; index < battery_devices.size(); ++index) {
@@ -149,6 +152,7 @@ void EmulatedController::ReloadInput() {
         Input::InputCallback battery_callback{
             [this, index](Input::CallbackStatus callback) { SetBattery(callback, index); }};
         battery_devices[index]->SetCallback(battery_callback);
+        battery_devices[index]->ForceUpdate();
     }
 
     for (std::size_t index = 0; index < motion_devices.size(); ++index) {
@@ -158,6 +162,7 @@ void EmulatedController::ReloadInput() {
         Input::InputCallback motion_callback{
             [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }};
         motion_devices[index]->SetCallback(motion_callback);
+        motion_devices[index]->ForceUpdate();
     }
 }
 
@@ -843,6 +848,10 @@ AnalogSticks EmulatedController::GetSticks() const {
     if (is_configuring) {
         return {};
     }
+    // Some drivers like stick from buttons need constant refreshing
+    for (auto& device : stick_devices) {
+        device->SoftUpdate();
+    }
     return controller.analog_stick_state;
 }
 
diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp
index 38f1507462..9101f11cee 100644
--- a/src/input_common/helpers/stick_from_buttons.cpp
+++ b/src/input_common/helpers/stick_from_buttons.cpp
@@ -200,6 +200,22 @@ public:
         TriggerOnChange(status);
     }
 
+    void ForceUpdate() override{
+        up->ForceUpdate();
+        down->ForceUpdate();
+        left->ForceUpdate();
+        right->ForceUpdate();
+        modifier->ForceUpdate();
+    }
+
+    void SoftUpdate() override {
+        Input::CallbackStatus status{
+            .type = Input::InputType::Stick,
+            .stick_status = GetStatus(),
+        };
+        TriggerOnChange(status);
+    }
+
     Input::StickStatus GetStatus() const {
         Input::StickStatus status{};
         status.x.properties = properties;
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp
index 2abfaf841d..bb2bad5b11 100644
--- a/src/input_common/helpers/touch_from_buttons.cpp
+++ b/src/input_common/helpers/touch_from_buttons.cpp
@@ -17,6 +17,7 @@ public:
         Input::InputCallback button_up_callback{
             [this](Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }};
         button->SetCallback(button_up_callback);
+        button->ForceUpdate();
     }
 
     Input::TouchStatus GetStatus(bool pressed) const {
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 62ade951c9..024bd28ef1 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -45,6 +45,16 @@ public:
         };
     }
 
+    void ForceUpdate() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Button,
+            .button_status = GetStatus(),
+        };
+
+        last_button_value = status.button_status.value;
+        TriggerOnChange(status);
+    }
+
     void OnChange() {
         const Input::CallbackStatus status{
             .type = Input::InputType::Button,
@@ -96,6 +106,16 @@ public:
         };
     }
 
+    void ForceUpdate() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Button,
+            .button_status = GetStatus(),
+        };
+
+        last_button_value = status.button_status.value;
+        TriggerOnChange(status);
+    }
+
     void OnChange() {
         const Input::CallbackStatus status{
             .type = Input::InputType::Button,

From 064ddacf49aa7155e26add55983b81fdda997077 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 24 Oct 2021 23:23:54 -0500
Subject: [PATCH 53/88] core/hid: Rework battery mappings

---
 src/core/hid/emulated_controller.cpp          | 50 +++++++++++--------
 src/core/hid/emulated_controller.h            | 28 +++++++----
 src/core/hid/emulated_devices.cpp             |  2 +-
 src/core/hid/input_converter.cpp              |  4 ++
 src/core/hle/service/hid/controllers/npad.cpp | 11 +++-
 .../helpers/stick_from_buttons.cpp            |  2 +-
 src/input_common/input_poller.cpp             | 39 +++++++++++++--
 .../configuration/configure_input_player.cpp  |  2 +-
 .../configure_input_player_widget.cpp         | 17 +++----
 9 files changed, 109 insertions(+), 46 deletions(-)

diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 48add394b4..83ced56351 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -87,11 +87,23 @@ void EmulatedController::ReloadFromSettings() {
 
     ReloadInput();
 }
+void EmulatedController::LoadDevices() {
+    const auto left_joycon = button_params[Settings::NativeButton::ZL];
+    const auto right_joycon = button_params[Settings::NativeButton::ZR];
 
-void EmulatedController::ReloadInput() {
-    // If you load any device here add the equivalent to the UnloadInput() function
-    const auto left_side = button_params[Settings::NativeButton::ZL];
-    const auto right_side = button_params[Settings::NativeButton::ZR];
+    // Triggers for GC controllers
+    trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL];
+    trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR];
+
+    battery_params[LeftIndex] = left_joycon;
+    battery_params[RightIndex] = right_joycon;
+    battery_params[LeftIndex].Set("battery", true);
+    battery_params[RightIndex].Set("battery", true);
+
+    output_params[LeftIndex] = left_joycon;
+    output_params[RightIndex] = right_joycon;
+    output_params[LeftIndex].Set("output", true);
+    output_params[RightIndex].Set("output", true);
 
     std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
                    button_params.begin() + Settings::NativeButton::BUTTON_NS_END,
@@ -102,19 +114,17 @@ void EmulatedController::ReloadInput() {
     std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
                    motion_params.begin() + Settings::NativeMotion::MOTION_HID_END,
                    motion_devices.begin(), Input::CreateDevice<Input::InputDevice>);
+    std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(),
+                   Input::CreateDevice<Input::InputDevice>);
+    std::transform(battery_params.begin(), battery_params.begin(), battery_devices.end(),
+                   Input::CreateDevice<Input::InputDevice>);
+    std::transform(output_params.begin(), output_params.end(), output_devices.begin(),
+                   Input::CreateDevice<Input::OutputDevice>);
+}
 
-    trigger_devices[0] =
-        Input::CreateDevice<Input::InputDevice>(button_params[Settings::NativeButton::ZL]);
-    trigger_devices[1] =
-        Input::CreateDevice<Input::InputDevice>(button_params[Settings::NativeButton::ZR]);
-
-    battery_devices[0] = Input::CreateDevice<Input::InputDevice>(left_side);
-    battery_devices[1] = Input::CreateDevice<Input::InputDevice>(right_side);
-
-    button_params[Settings::NativeButton::ZL].Set("output", true);
-    output_devices[0] =
-        Input::CreateDevice<Input::OutputDevice>(button_params[Settings::NativeButton::ZL]);
-
+void EmulatedController::ReloadInput() {
+    // If you load any device here add the equivalent to the UnloadInput() function
+    LoadDevices();
     for (std::size_t index = 0; index < button_devices.size(); ++index) {
         if (!button_devices[index]) {
             continue;
@@ -241,7 +251,7 @@ void EmulatedController::RestoreConfig() {
     ReloadFromSettings();
 }
 
-std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices() const {
+std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices(DeviceIndex device_index) const {
     std::vector<Common::ParamPackage> devices;
     for (const auto& param : button_params) {
         if (!param.Has("engine")) {
@@ -612,21 +622,21 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t
     }
 
     switch (index) {
-    case 0:
+    case LeftIndex:
         controller.battery_state.left = {
             .is_powered = is_powered,
             .is_charging = is_charging,
             .battery_level = battery_level,
         };
         break;
-    case 1:
+    case RightIndex:
         controller.battery_state.right = {
             .is_powered = is_powered,
             .is_charging = is_charging,
             .battery_level = battery_level,
         };
         break;
-    case 2:
+    case DualIndex:
         controller.battery_state.dual = {
             .is_powered = is_powered,
             .is_charging = is_charging,
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index d667685493..eb705a2412 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -18,7 +18,7 @@
 #include "core/hid/motion_input.h"
 
 namespace Core::HID {
-
+const std::size_t max_emulated_controllers = 2;
 struct ControllerMotionInfo {
     Input::MotionStatus raw_status{};
     MotionInput emulated{};
@@ -32,23 +32,23 @@ using ControllerMotionDevices =
     std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeMotion::NumMotions>;
 using TriggerDevices =
     std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
-using BatteryDevices = std::array<std::unique_ptr<Input::InputDevice>, 2>;
-using OutputDevices = std::array<std::unique_ptr<Input::OutputDevice>, 2>;
+using BatteryDevices = std::array<std::unique_ptr<Input::InputDevice>, max_emulated_controllers>;
+using OutputDevices = std::array<std::unique_ptr<Input::OutputDevice>, max_emulated_controllers>;
 
 using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
 using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
 using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>;
 using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>;
-using BatteryParams = std::array<Common::ParamPackage, 2>;
-using OutputParams = std::array<Common::ParamPackage, 2>;
+using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>;
+using OutputParams = std::array<Common::ParamPackage, max_emulated_controllers>;
 
 using ButtonValues = std::array<Input::ButtonStatus, Settings::NativeButton::NumButtons>;
 using SticksValues = std::array<Input::StickStatus, Settings::NativeAnalog::NumAnalogs>;
 using TriggerValues = std::array<Input::TriggerStatus, Settings::NativeTrigger::NumTriggers>;
 using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>;
-using ColorValues = std::array<Input::BodyColorStatus, 3>;
-using BatteryValues = std::array<Input::BatteryStatus, 3>;
-using VibrationValues = std::array<Input::VibrationStatus, 2>;
+using ColorValues = std::array<Input::BodyColorStatus, max_emulated_controllers>;
+using BatteryValues = std::array<Input::BatteryStatus, max_emulated_controllers>;
+using VibrationValues = std::array<Input::VibrationStatus, max_emulated_controllers>;
 
 struct AnalogSticks {
     AnalogStickState left{};
@@ -75,6 +75,13 @@ struct ControllerMotion {
     bool is_at_rest{};
 };
 
+enum DeviceIndex : u8 {
+    LeftIndex,
+    RightIndex,
+    DualIndex,
+    AllDevices,
+};
+
 using MotionState = std::array<ControllerMotion, 2>;
 
 struct ControllerStatus {
@@ -189,7 +196,7 @@ public:
     void RestoreConfig();
 
     /// Returns a vector of mapped devices from the mapped button and stick parameters
-    std::vector<Common::ParamPackage> GetMappedDevices() const;
+    std::vector<Common::ParamPackage> GetMappedDevices(DeviceIndex device_index) const;
 
     // Returns the current mapped button device
     Common::ParamPackage GetButtonParam(std::size_t index) const;
@@ -289,6 +296,9 @@ public:
     void DeleteCallback(int key);
 
 private:
+    /// creates input devices from params
+    void LoadDevices();
+
     /**
      * Updates the button status of the controller
      * @param callback: A CallbackStatus containing the button status
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
index 5afd83f62c..eb59c310c7 100644
--- a/src/core/hid/emulated_devices.cpp
+++ b/src/core/hid/emulated_devices.cpp
@@ -174,7 +174,7 @@ void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) {
     if (status) {
         entry = entry | mask;
     } else {
-        entry = entry & ~mask;
+        entry = static_cast<u8>(entry & ~mask);
     }
 }
 
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index b3c8913cea..e2598f367c 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -33,6 +33,10 @@ Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback) {
         }
         break;
     }
+    case Input::InputType::Button:
+        battery = callback.button_status.value ? Input::BatteryLevel::Charging
+                                               : Input::BatteryLevel::Critical;
+        break;
     case Input::InputType::Battery:
         battery = callback.battery_status;
         break;
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 7bf31f63a8..9f84e20c24 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -101,8 +101,9 @@ Controller_NPad::Controller_NPad(Core::System& system_,
     for (std::size_t i = 0; i < controller_data.size(); ++i) {
         auto& controller = controller_data[i];
         controller.device = system.HIDCore().GetEmulatedControllerByIndex(i);
-        controller.vibration[0].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
-        controller.vibration[1].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
+        controller.vibration[Core::HID::DeviceIndex::LeftIndex].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
+        controller.vibration[Core::HID::DeviceIndex::RightIndex].latest_vibration_value =
+            DEFAULT_VIBRATION_VALUE;
         Core::HID::ControllerUpdateCallback engine_callback{
             .on_change = [this,
                           i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
@@ -285,9 +286,12 @@ void Controller_NPad::OnInit() {
         auto& npad = controller.shared_memory_entry;
         npad.fullkey_color = {
             .attribute = ColorAttribute::NoController,
+            .fullkey = {},
         };
         npad.joycon_color = {
             .attribute = ColorAttribute::NoController,
+            .left = {},
+            .right = {},
         };
         // HW seems to initialize the first 19 entries
         for (std::size_t i = 0; i < 19; ++i) {
@@ -907,9 +911,12 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
     shared_memory_entry.battery_level_right = 0;
     shared_memory_entry.fullkey_color = {
         .attribute = ColorAttribute::NoController,
+        .fullkey = {},
     };
     shared_memory_entry.joycon_color = {
         .attribute = ColorAttribute::NoController,
+        .left = {},
+        .right = {},
     };
     shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual;
     shared_memory_entry.footer_type = AppletFooterUiType::None;
diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp
index 9101f11cee..806a0e8bba 100644
--- a/src/input_common/helpers/stick_from_buttons.cpp
+++ b/src/input_common/helpers/stick_from_buttons.cpp
@@ -200,7 +200,7 @@ public:
         TriggerOnChange(status);
     }
 
-    void ForceUpdate() override{
+    void ForceUpdate() override {
         up->ForceUpdate();
         down->ForceUpdate();
         left->ForceUpdate();
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 024bd28ef1..6edb8d9005 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -183,6 +183,17 @@ public:
         return status;
     }
 
+    void ForceUpdate() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Stick,
+            .stick_status = GetStatus(),
+        };
+
+        last_axis_x_value = status.stick_status.x.raw_value;
+        last_axis_y_value = status.stick_status.y.raw_value;
+        TriggerOnChange(status);
+    }
+
     void OnChange() {
         const Input::CallbackStatus status{
             .type = Input::InputType::Stick,
@@ -448,6 +459,16 @@ public:
         return static_cast<Input::BatteryLevel>(input_engine->GetBattery(identifier));
     }
 
+    void ForceUpdate() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Battery,
+            .battery_status = GetStatus(),
+        };
+
+        last_battery_value = status.battery_status;
+        TriggerOnChange(status);
+    }
+
     void OnChange() {
         const Input::CallbackStatus status{
             .type = Input::InputType::Battery,
@@ -579,6 +600,18 @@ public:
         return status;
     }
 
+    void ForceUpdate() {
+        const Input::CallbackStatus status{
+            .type = Input::InputType::Motion,
+            .motion_status = GetStatus(),
+        };
+
+        last_axis_x_value = status.motion_status.gyro.x.raw_value;
+        last_axis_y_value = status.motion_status.gyro.y.raw_value;
+        last_axis_z_value = status.motion_status.gyro.z.raw_value;
+        TriggerOnChange(status);
+    }
+
     void OnChange() {
         const Input::CallbackStatus status{
             .type = Input::InputType::Motion,
@@ -868,6 +901,9 @@ InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_)
     : input_engine(std::move(input_engine_)) {}
 
 std::unique_ptr<Input::InputDevice> InputFactory::Create(const Common::ParamPackage& params) {
+    if (params.Has("battery")) {
+        return CreateBatteryDevice(params);
+    }
     if (params.Has("button") && params.Has("axis")) {
         return CreateTriggerDevice(params);
     }
@@ -892,9 +928,6 @@ std::unique_ptr<Input::InputDevice> InputFactory::Create(const Common::ParamPack
     if (params.Has("axis")) {
         return CreateAnalogDevice(params);
     }
-    if (params.Has("battery")) {
-        return CreateBatteryDevice(params);
-    }
     LOG_ERROR(Input, "Invalid parameters given");
     return std::make_unique<DummyInput>();
 }
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 4160963333..acb29a6b42 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -630,7 +630,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
         return;
     }
 
-    const auto devices = emulated_controller->GetMappedDevices();
+    const auto devices = emulated_controller->GetMappedDevices(Core::HID::DeviceIndex::AllDevices);
     UpdateInputDevices();
 
     if (devices.empty()) {
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 3f179150dc..67e56ed3ab 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -356,7 +356,7 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
     DrawCircle(p, center + QPoint(26, 71), 5);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(-170, -140), battery_values[0]);
+    DrawBattery(p, center + QPoint(-170, -140), battery_values[Core::HID::DeviceIndex::LeftIndex]);
 }
 
 void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) {
@@ -482,7 +482,7 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
     DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(110, -140), battery_values[1]);
+    DrawBattery(p, center + QPoint(110, -140), battery_values[Core::HID::DeviceIndex::RightIndex]);
 }
 
 void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) {
@@ -618,8 +618,8 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
     DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(-100, -160), battery_values[0]);
-    DrawBattery(p, center + QPoint(40, -160), battery_values[1]);
+    DrawBattery(p, center + QPoint(-100, -160), battery_values[Core::HID::DeviceIndex::LeftIndex]);
+    DrawBattery(p, center + QPoint(40, -160), battery_values[Core::HID::DeviceIndex::RightIndex]);
 }
 
 void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) {
@@ -720,9 +720,8 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
     DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(-200, 110), battery_values[0]);
-    DrawBattery(p, center + QPoint(-30, 110), battery_values[1]);
-    DrawBattery(p, center + QPoint(130, 110), battery_values[2]);
+    DrawBattery(p, center + QPoint(-200, 110), battery_values[Core::HID::DeviceIndex::LeftIndex]);
+    DrawBattery(p, center + QPoint(130, 110), battery_values[Core::HID::DeviceIndex::RightIndex]);
 }
 
 void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) {
@@ -812,7 +811,7 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
     DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(-30, -160), battery_values[0]);
+    DrawBattery(p, center + QPoint(-30, -160), battery_values[Core::HID::DeviceIndex::LeftIndex]);
 }
 
 void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
@@ -868,7 +867,7 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
     DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(-30, -165), battery_values[0]);
+    DrawBattery(p, center + QPoint(-30, -165), battery_values[Core::HID::DeviceIndex::LeftIndex]);
 }
 
 constexpr std::array<float, 13 * 2> symbol_a = {

From 7348e205d94e2fff777781498a2ef7931163703a Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Tue, 26 Oct 2021 23:37:46 -0500
Subject: [PATCH 54/88] input_common: Add multiple vibration curves

---
 src/core/hid/emulated_controller.cpp    | 10 +++++++-
 src/input_common/drivers/sdl_driver.cpp | 33 ++++++++++++++-----------
 2 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 83ced56351..916368c687 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -251,7 +251,8 @@ void EmulatedController::RestoreConfig() {
     ReloadFromSettings();
 }
 
-std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices(DeviceIndex device_index) const {
+std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices(
+    DeviceIndex device_index) const {
     std::vector<Common::ParamPackage> devices;
     for (const auto& param : button_params) {
         if (!param.Has("engine")) {
@@ -658,6 +659,10 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
     const auto& player = Settings::values.players.GetValue()[player_index];
     const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f;
 
+    if (!player.vibration_enabled) {
+        return false;
+    }
+
     // Exponential amplification is too strong at low amplitudes. Switch to a linear
     // amplification if strength is set below 0.7f
     const Input::VibrationAmplificationType type =
@@ -860,6 +865,9 @@ AnalogSticks EmulatedController::GetSticks() const {
     }
     // Some drivers like stick from buttons need constant refreshing
     for (auto& device : stick_devices) {
+        if (!device) {
+            continue;
+        }
         device->SoftUpdate();
     }
     return controller.analog_stick_state;
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index d56351815c..53e282ef3c 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -94,7 +94,6 @@ public:
 
     bool RumblePlay(const Input::VibrationStatus vibration) {
         constexpr u32 rumble_max_duration_ms = 1000;
-
         if (sdl_controller) {
             return SDL_GameControllerRumble(
                        sdl_controller.get(), static_cast<u16>(vibration.low_amplitude),
@@ -520,25 +519,31 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier,
                                            const Input::VibrationStatus vibration) {
     const auto joystick =
         GetSDLJoystickByGUID(identifier.guid.Format(), static_cast<int>(identifier.port));
-    const auto process_amplitude = [](f32 amplitude) {
-        return (amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF;
+    const auto process_amplitude_exp = [](f32 amplitude, f32 factor) {
+        return (amplitude + std::pow(amplitude, factor)) * 0.5f * 0xFFFF;
     };
-    const Input::VibrationStatus exponential_vibration{
-        .low_amplitude = process_amplitude(vibration.low_amplitude),
+
+    // Default exponential curve for rumble
+    f32 factor = 0.35f;
+
+    // If vibration is set as a linear output use a flatter value
+    if (vibration.type == Input::VibrationAmplificationType::Linear) {
+        factor = 0.5f;
+    }
+
+    // Amplitude for HD rumble needs no modification
+    if (joystick->HasHDRumble()) {
+        factor = 1.0f;
+    }
+
+    const Input::VibrationStatus new_vibration{
+        .low_amplitude = process_amplitude_exp(vibration.low_amplitude, factor),
         .low_frequency = vibration.low_frequency,
-        .high_amplitude = process_amplitude(vibration.high_amplitude),
+        .high_amplitude = process_amplitude_exp(vibration.high_amplitude, factor),
         .high_frequency = vibration.high_frequency,
         .type = Input::VibrationAmplificationType::Exponential,
     };
 
-    Input::VibrationStatus new_vibration{};
-
-    if (vibration.type == Input::VibrationAmplificationType::Linear || joystick->HasHDRumble()) {
-        new_vibration = vibration;
-    } else {
-        new_vibration = exponential_vibration;
-    }
-
     if (!joystick->RumblePlay(new_vibration)) {
         return Input::VibrationError::Unknown;
     }

From 1d71d4b87415b2581e6757f07d29275e02671b7a Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 25 Oct 2021 12:53:14 -0500
Subject: [PATCH 55/88] input_common: Fix UDP uuid

---
 src/input_common/drivers/udp_client.cpp           | 10 +++++++++-
 src/input_common/drivers/udp_client.h             |  2 ++
 src/yuzu/configuration/configure_input_player.cpp |  6 +++++-
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp
index 192ab336b9..7cab707da5 100644
--- a/src/input_common/drivers/udp_client.cpp
+++ b/src/input_common/drivers/udp_client.cpp
@@ -4,6 +4,7 @@
 
 #include <random>
 #include <boost/asio.hpp>
+#include <fmt/format.h>
 
 #include "common/logging/log.h"
 #include "common/param_package.h"
@@ -279,6 +280,7 @@ void UDPClient::StartCommunication(std::size_t client, const std::string& host,
                             [this](Response::PortInfo info) { OnPortInfo(info); },
                             [this, client](Response::PadData data) { OnPadData(data, client); }};
     LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port);
+    clients[client].uuid = GetHostUUID(host);
     clients[client].host = host;
     clients[client].port = port;
     clients[client].active = 0;
@@ -293,12 +295,18 @@ void UDPClient::StartCommunication(std::size_t client, const std::string& host,
 const PadIdentifier UDPClient::GetPadIdentifier(std::size_t pad_index) const {
     const std::size_t client = pad_index / PADS_PER_CLIENT;
     return {
-        .guid = Common::UUID{clients[client].host},
+        .guid = clients[client].uuid,
         .port = static_cast<std::size_t>(clients[client].port),
         .pad = pad_index,
     };
 }
 
+const Common::UUID UDPClient::GetHostUUID(const std::string host) const {
+    const auto ip = boost::asio::ip::address_v4::from_string(host);
+    const auto hex_host = fmt::format("{:06x}", ip.to_ulong());
+    return Common::UUID{hex_host};
+}
+
 void UDPClient::Reset() {
     for (auto& client : clients) {
         if (client.thread.joinable()) {
diff --git a/src/input_common/drivers/udp_client.h b/src/input_common/drivers/udp_client.h
index 639325b177..1f02adba58 100644
--- a/src/input_common/drivers/udp_client.h
+++ b/src/input_common/drivers/udp_client.h
@@ -69,6 +69,7 @@ private:
     struct ClientConnection {
         ClientConnection();
         ~ClientConnection();
+        Common::UUID uuid{"7F000001"};
         std::string host{"127.0.0.1"};
         u16 port{26760};
         s8 active{-1};
@@ -87,6 +88,7 @@ private:
     void OnPadData(Response::PadData, std::size_t client);
     void StartCommunication(std::size_t client, const std::string& host, u16 port);
     const PadIdentifier GetPadIdentifier(std::size_t pad_index) const;
+    const Common::UUID GetHostUUID(const std::string host) const;
 
     // Allocate clients for 8 udp servers
     static constexpr std::size_t MAX_UDP_CLIENTS = 8;
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index acb29a6b42..9a1b3575e2 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -1178,7 +1178,7 @@ void ConfigureInputPlayer::HandleClick(
     }
 
     timeout_timer->start(2500); // Cancel after 2.5 seconds
-    poll_timer->start(50);      // Check for new inputs every 50ms
+    poll_timer->start(25);      // Check for new inputs every 25ms
 }
 
 void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) {
@@ -1205,6 +1205,10 @@ bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params)
         return true;
     }
 
+    if (params.Has("motion")) {
+        return true;
+    }
+
     // Keyboard/Mouse
     if (ui->comboDevices->currentIndex() == 1 || ui->comboDevices->currentIndex() == 2) {
         return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse";

From c085e54316c5520ed7d58a92a7faa9e896bb6c71 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Wed, 27 Oct 2021 00:20:28 -0500
Subject: [PATCH 56/88] core/hid: Add TAS input

---
 src/common/settings.h                    |  1 -
 src/core/hid/emulated_controller.cpp     | 72 ++++++++++++++++++++++++
 src/core/hid/emulated_controller.h       |  9 +++
 src/yuzu/configuration/config.cpp        |  2 -
 src/yuzu/configuration/configure_tas.cpp |  2 -
 src/yuzu/configuration/configure_tas.ui  |  9 +--
 6 files changed, 82 insertions(+), 13 deletions(-)

diff --git a/src/common/settings.h b/src/common/settings.h
index 4cf28617c6..dac44d0006 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -567,7 +567,6 @@ struct Values {
     BasicSetting<bool> pause_tas_on_load{true, "pause_tas_on_load"};
     BasicSetting<bool> tas_enable{false, "tas_enable"};
     BasicSetting<bool> tas_loop{false, "tas_loop"};
-    BasicSetting<bool> tas_swap_controllers{true, "tas_swap_controllers"};
 
     BasicSetting<bool> mouse_panning{false, "mouse_panning"};
     BasicRangedSetting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 916368c687..2b051ccaf2 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -105,6 +105,8 @@ void EmulatedController::LoadDevices() {
     output_params[LeftIndex].Set("output", true);
     output_params[RightIndex].Set("output", true);
 
+    LoadTASParams();
+
     std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
                    button_params.begin() + Settings::NativeButton::BUTTON_NS_END,
                    button_devices.begin(), Input::CreateDevice<Input::InputDevice>);
@@ -120,6 +122,51 @@ void EmulatedController::LoadDevices() {
                    Input::CreateDevice<Input::InputDevice>);
     std::transform(output_params.begin(), output_params.end(), output_devices.begin(),
                    Input::CreateDevice<Input::OutputDevice>);
+
+    // Initialize TAS devices
+    std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(),
+                   Input::CreateDevice<Input::InputDevice>);
+    std::transform(tas_stick_params.begin(), tas_stick_params.begin(), tas_stick_devices.begin(),
+                   Input::CreateDevice<Input::InputDevice>);
+}
+
+void EmulatedController::LoadTASParams() {
+    const auto player_index = NpadIdTypeToIndex(npad_id_type);
+    Common::ParamPackage common_params{};
+    common_params.Set("engine", "tas");
+    common_params.Set("pad", static_cast<int>(player_index));
+    for (auto& param : tas_button_params) {
+        param = common_params;
+    }
+    for (auto& param : tas_stick_params) {
+        param = common_params;
+    }
+
+    tas_button_params[Settings::NativeButton::A].Set("button", 1 << 0);
+    tas_button_params[Settings::NativeButton::B].Set("button", 1 << 1);
+    tas_button_params[Settings::NativeButton::X].Set("button", 1 << 2);
+    tas_button_params[Settings::NativeButton::Y].Set("button", 1 << 3);
+    tas_button_params[Settings::NativeButton::LStick].Set("button", 1 << 4);
+    tas_button_params[Settings::NativeButton::RStick].Set("button", 1 << 5);
+    tas_button_params[Settings::NativeButton::L].Set("button", 1 << 6);
+    tas_button_params[Settings::NativeButton::R].Set("button", 1 << 7);
+    tas_button_params[Settings::NativeButton::ZL].Set("button", 1 << 8);
+    tas_button_params[Settings::NativeButton::ZR].Set("button", 1 << 9);
+    tas_button_params[Settings::NativeButton::Plus].Set("button", 1 << 10);
+    tas_button_params[Settings::NativeButton::Minus].Set("button", 1 << 11);
+    tas_button_params[Settings::NativeButton::DLeft].Set("button", 1 << 12);
+    tas_button_params[Settings::NativeButton::DUp].Set("button", 1 << 13);
+    tas_button_params[Settings::NativeButton::DRight].Set("button", 1 << 14);
+    tas_button_params[Settings::NativeButton::DDown].Set("button", 1 << 15);
+    tas_button_params[Settings::NativeButton::SL].Set("button", 1 << 16);
+    tas_button_params[Settings::NativeButton::SR].Set("button", 1 << 17);
+    tas_button_params[Settings::NativeButton::Home].Set("button", 1 << 18);
+    tas_button_params[Settings::NativeButton::Screenshot].Set("button", 1 << 19);
+
+    tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
+    tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
+    tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2);
+    tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3);
 }
 
 void EmulatedController::ReloadInput() {
@@ -174,6 +221,25 @@ void EmulatedController::ReloadInput() {
         motion_devices[index]->SetCallback(motion_callback);
         motion_devices[index]->ForceUpdate();
     }
+
+    // Register TAS devices. No need to force update
+    for (std::size_t index = 0; index < tas_button_devices.size(); ++index) {
+        if (!tas_button_devices[index]) {
+            continue;
+        }
+        Input::InputCallback button_callback{
+            [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }};
+        tas_button_devices[index]->SetCallback(button_callback);
+    }
+
+    for (std::size_t index = 0; index < tas_stick_devices.size(); ++index) {
+        if (!tas_stick_devices[index]) {
+            continue;
+        }
+        Input::InputCallback stick_callback{
+            [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }};
+        tas_stick_devices[index]->SetCallback(stick_callback);
+    }
 }
 
 void EmulatedController::UnloadInput() {
@@ -195,6 +261,12 @@ void EmulatedController::UnloadInput() {
     for (auto& output : output_devices) {
         output.reset();
     }
+    for (auto& button : tas_button_devices) {
+        button.reset();
+    }
+    for (auto& stick : tas_stick_devices) {
+        stick.reset();
+    }
 }
 
 void EmulatedController::EnableConfiguration() {
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index eb705a2412..eec51e34a6 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -299,6 +299,9 @@ private:
     /// creates input devices from params
     void LoadDevices();
 
+    /// Set the params for TAS devices
+    void LoadTASParams();
+
     /**
      * Updates the button status of the controller
      * @param callback: A CallbackStatus containing the button status
@@ -363,6 +366,12 @@ private:
     BatteryDevices battery_devices;
     OutputDevices output_devices;
 
+    // TAS related variables
+    ButtonParams tas_button_params;
+    StickParams tas_stick_params;
+    ButtonDevices tas_button_devices;
+    StickDevices tas_stick_devices;
+
     mutable std::mutex mutex;
     std::unordered_map<int, ControllerUpdateCallback> callback_list;
     int last_callback_key = 0;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 56af075072..7a748d9c83 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -573,7 +573,6 @@ void Config::ReadControlValues() {
 
     ReadBasicSetting(Settings::values.tas_enable);
     ReadBasicSetting(Settings::values.tas_loop);
-    ReadBasicSetting(Settings::values.tas_swap_controllers);
     ReadBasicSetting(Settings::values.pause_tas_on_load);
 
     ReadGlobalSetting(Settings::values.use_docked_mode);
@@ -1209,7 +1208,6 @@ void Config::SaveControlValues() {
 
     WriteBasicSetting(Settings::values.tas_enable);
     WriteBasicSetting(Settings::values.tas_loop);
-    WriteBasicSetting(Settings::values.tas_swap_controllers);
     WriteBasicSetting(Settings::values.pause_tas_on_load);
 
     qt_config->endGroup();
diff --git a/src/yuzu/configuration/configure_tas.cpp b/src/yuzu/configuration/configure_tas.cpp
index 8e5a4c72d1..979a8db61e 100644
--- a/src/yuzu/configuration/configure_tas.cpp
+++ b/src/yuzu/configuration/configure_tas.cpp
@@ -32,7 +32,6 @@ void ConfigureTasDialog::LoadConfiguration() {
     ui->tas_path_edit->setText(
         QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASDir)));
     ui->tas_enable->setChecked(Settings::values.tas_enable.GetValue());
-    ui->tas_control_swap->setChecked(Settings::values.tas_swap_controllers.GetValue());
     ui->tas_loop_script->setChecked(Settings::values.tas_loop.GetValue());
     ui->tas_pause_on_load->setChecked(Settings::values.pause_tas_on_load.GetValue());
 }
@@ -40,7 +39,6 @@ void ConfigureTasDialog::LoadConfiguration() {
 void ConfigureTasDialog::ApplyConfiguration() {
     Common::FS::SetYuzuPath(Common::FS::YuzuPath::TASDir, ui->tas_path_edit->text().toStdString());
     Settings::values.tas_enable.SetValue(ui->tas_enable->isChecked());
-    Settings::values.tas_swap_controllers.SetValue(ui->tas_control_swap->isChecked());
     Settings::values.tas_loop.SetValue(ui->tas_loop_script->isChecked());
     Settings::values.pause_tas_on_load.SetValue(ui->tas_pause_on_load->isChecked());
 }
diff --git a/src/yuzu/configuration/configure_tas.ui b/src/yuzu/configuration/configure_tas.ui
index 7d44895c40..cf88a5bf08 100644
--- a/src/yuzu/configuration/configure_tas.ui
+++ b/src/yuzu/configuration/configure_tas.ui
@@ -59,20 +59,13 @@
          </widget>
         </item>
         <item row="1" column="0" colspan="4">
-         <widget class="QCheckBox" name="tas_control_swap">
-          <property name="text">
-           <string>Automatic controller profile swapping</string>
-          </property>
-         </widget>
-        </item>
-        <item row="2" column="0" colspan="4">
          <widget class="QCheckBox" name="tas_loop_script">
           <property name="text">
            <string>Loop script</string>
           </property>
          </widget>
         </item>
-        <item row="3" column="0" colspan="4">
+        <item row="2" column="0" colspan="4">
          <widget class="QCheckBox" name="tas_pause_on_load">
           <property name="enabled">
            <bool>false</bool>

From 2d3a63b28969089746e43ed232dc74630fbfc3b2 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Wed, 27 Oct 2021 18:06:13 -0500
Subject: [PATCH 57/88] core/hid: Update structs to 13.1.0

---
 src/core/hid/hid_types.h                      | 10 ++++
 src/core/hid/input_interpreter.cpp            | 14 ++---
 src/core/hid/input_interpreter.h              |  2 +-
 .../hle/service/hid/controllers/debug_pad.cpp |  4 +-
 .../hle/service/hid/controllers/gesture.cpp   |  8 +--
 .../hle/service/hid/controllers/keyboard.cpp  |  4 +-
 .../hle/service/hid/controllers/mouse.cpp     |  6 +-
 src/core/hle/service/hid/controllers/npad.cpp | 15 ++---
 src/core/hle/service/hid/controllers/npad.h   | 60 +++++++++++++++++--
 .../service/hid/controllers/touchscreen.cpp   |  4 +-
 src/core/hle/service/hid/controllers/xpad.cpp |  4 +-
 src/core/hle/service/hid/ring_lifo.h          | 26 ++++----
 12 files changed, 107 insertions(+), 50 deletions(-)

diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 59ec593b84..f8a0d5edd0 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -231,7 +231,12 @@ enum class NpadButton : u64 {
     RightSR = 1U << 27,
 
     Palma = 1U << 28,
+    Verification = 1U << 29,
     HandheldLeftB = 1U << 30,
+    LagonCLeft = 1U << 31,
+    LagonCUp = 1ULL << 32,
+    LagonCRight = 1ULL << 33,
+    LagonCDown = 1ULL << 34,
 };
 DECLARE_ENUM_FLAG_OPERATORS(NpadButton);
 
@@ -278,7 +283,12 @@ struct NpadButtonState {
         BitField<27, 1, u64> right_sr;
 
         BitField<28, 1, u64> palma;
+        BitField<29, 1, u64> verification;
         BitField<30, 1, u64> handheld_left_b;
+        BitField<31, 1, u64> lagon_c_left;
+        BitField<32, 1, u64> lagon_c_up;
+        BitField<33, 1, u64> lagon_c_right;
+        BitField<34, 1, u64> lagon_c_down;
     };
 };
 static_assert(sizeof(NpadButtonState) == 0x8, "NpadButtonState has incorrect size.");
diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp
index 7e7c1816fd..870422d820 100644
--- a/src/core/hid/input_interpreter.cpp
+++ b/src/core/hid/input_interpreter.cpp
@@ -20,7 +20,7 @@ InputInterpreter::InputInterpreter(Core::System& system)
 InputInterpreter::~InputInterpreter() = default;
 
 void InputInterpreter::PollInput() {
-    const u32 button_state = npad.GetAndResetPressState();
+    const u64 button_state = npad.GetAndResetPressState();
 
     previous_index = current_index;
     current_index = (current_index + 1) % button_states.size();
@@ -32,7 +32,7 @@ void InputInterpreter::ResetButtonStates() {
     previous_index = 0;
     current_index = 0;
 
-    button_states[0] = 0xFFFFFFFF;
+    button_states[0] = 0xFFFFFFFFFFFFFFFF;
 
     for (std::size_t i = 1; i < button_states.size(); ++i) {
         button_states[i] = 0;
@@ -40,22 +40,22 @@ void InputInterpreter::ResetButtonStates() {
 }
 
 bool InputInterpreter::IsButtonPressed(Core::HID::NpadButton button) const {
-    return (button_states[current_index] & static_cast<u32>(button)) != 0;
+    return (button_states[current_index] & static_cast<u64>(button)) != 0;
 }
 
 bool InputInterpreter::IsButtonPressedOnce(Core::HID::NpadButton button) const {
-    const bool current_press = (button_states[current_index] & static_cast<u32>(button)) != 0;
-    const bool previous_press = (button_states[previous_index] & static_cast<u32>(button)) != 0;
+    const bool current_press = (button_states[current_index] & static_cast<u64>(button)) != 0;
+    const bool previous_press = (button_states[previous_index] & static_cast<u64>(button)) != 0;
 
     return current_press && !previous_press;
 }
 
 bool InputInterpreter::IsButtonHeld(Core::HID::NpadButton button) const {
-    u32 held_buttons{button_states[0]};
+    u64 held_buttons{button_states[0]};
 
     for (std::size_t i = 1; i < button_states.size(); ++i) {
         held_buttons &= button_states[i];
     }
 
-    return (held_buttons & static_cast<u32>(button)) != 0;
+    return (held_buttons & static_cast<u64>(button)) != 0;
 }
diff --git a/src/core/hid/input_interpreter.h b/src/core/hid/input_interpreter.h
index 1791cf9b72..1c2e02142d 100644
--- a/src/core/hid/input_interpreter.h
+++ b/src/core/hid/input_interpreter.h
@@ -105,7 +105,7 @@ private:
     Service::HID::Controller_NPad& npad;
 
     /// Stores 9 consecutive button states polled from HID.
-    std::array<u32, 9> button_states{};
+    std::array<u64, 9> button_states{};
 
     std::size_t previous_index{};
     std::size_t current_index{};
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index 5b1946f134..345134357d 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -30,8 +30,8 @@ void Controller_DebugPad::OnRelease() {}
 void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                    std::size_t size) {
     if (!IsControllerActivated()) {
-        debug_pad_lifo.entry_count = 0;
-        debug_pad_lifo.last_entry_index = 0;
+        debug_pad_lifo.buffer_count = 0;
+        debug_pad_lifo.buffer_tail = 0;
         std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo));
         return;
     }
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 47760b4f8c..00df50f323 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -31,8 +31,8 @@ Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(s
 Controller_Gesture::~Controller_Gesture() = default;
 
 void Controller_Gesture::OnInit() {
-    gesture_lifo.entry_count = 0;
-    gesture_lifo.last_entry_index = 0;
+    gesture_lifo.buffer_count = 0;
+    gesture_lifo.buffer_tail = 0;
     force_update = true;
 }
 
@@ -41,8 +41,8 @@ void Controller_Gesture::OnRelease() {}
 void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                   std::size_t size) {
     if (!IsControllerActivated()) {
-        gesture_lifo.entry_count = 0;
-        gesture_lifo.last_entry_index = 0;
+        gesture_lifo.buffer_count = 0;
+        gesture_lifo.buffer_tail = 0;
         std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo));
         return;
     }
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 632679a171..f4d49965ff 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -27,8 +27,8 @@ void Controller_Keyboard::OnRelease() {}
 void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                    std::size_t size) {
     if (!IsControllerActivated()) {
-        keyboard_lifo.entry_count = 0;
-        keyboard_lifo.last_entry_index = 0;
+        keyboard_lifo.buffer_count = 0;
+        keyboard_lifo.buffer_tail = 0;
         std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo));
         return;
     }
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 6d3bd0a2b2..7ec75e8c87 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -24,11 +24,9 @@ void Controller_Mouse::OnRelease() {}
 
 void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                 std::size_t size) {
-    mouse_lifo.timestamp = core_timing.GetCPUTicks();
-
     if (!IsControllerActivated()) {
-        mouse_lifo.entry_count = 0;
-        mouse_lifo.last_entry_index = 0;
+        mouse_lifo.buffer_count = 0;
+        mouse_lifo.buffer_tail = 0;
         std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo));
         return;
     }
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 9f84e20c24..9f82f872ae 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -101,7 +101,8 @@ Controller_NPad::Controller_NPad(Core::System& system_,
     for (std::size_t i = 0; i < controller_data.size(); ++i) {
         auto& controller = controller_data[i];
         controller.device = system.HIDCore().GetEmulatedControllerByIndex(i);
-        controller.vibration[Core::HID::DeviceIndex::LeftIndex].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
+        controller.vibration[Core::HID::DeviceIndex::LeftIndex].latest_vibration_value =
+            DEFAULT_VIBRATION_VALUE;
         controller.vibration[Core::HID::DeviceIndex::RightIndex].latest_vibration_value =
             DEFAULT_VIBRATION_VALUE;
         Core::HID::ControllerUpdateCallback engine_callback{
@@ -178,7 +179,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.system_properties.use_plus.Assign(1);
         shared_memory.system_properties.use_minus.Assign(1);
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
-        shared_memory.footer_type = AppletFooterUiType::SwitchProController;
+        shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController;
         break;
     case Core::HID::NpadType::Handheld:
         shared_memory.style_set.handheld.Assign(1);
@@ -188,7 +189,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.system_properties.use_plus.Assign(1);
         shared_memory.system_properties.use_minus.Assign(1);
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
-        shared_memory.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
+        shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
         break;
     case Core::HID::NpadType::JoyconDual:
         shared_memory.style_set.joycon_dual.Assign(1);
@@ -198,7 +199,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.system_properties.use_plus.Assign(1);
         shared_memory.system_properties.use_minus.Assign(1);
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
-        shared_memory.footer_type = AppletFooterUiType::JoyDual;
+        shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
         break;
     case Core::HID::NpadType::JoyconLeft:
         shared_memory.style_set.joycon_left.Assign(1);
@@ -206,7 +207,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.system_properties.is_horizontal.Assign(1);
         shared_memory.system_properties.use_minus.Assign(1);
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
-        shared_memory.footer_type = AppletFooterUiType::JoyLeftHorizontal;
+        shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
         break;
     case Core::HID::NpadType::JoyconRight:
         shared_memory.style_set.joycon_right.Assign(1);
@@ -214,7 +215,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.system_properties.is_horizontal.Assign(1);
         shared_memory.system_properties.use_plus.Assign(1);
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
-        shared_memory.footer_type = AppletFooterUiType::JoyRightHorizontal;
+        shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
         break;
     case Core::HID::NpadType::GameCube:
         shared_memory.style_set.gamecube.Assign(1);
@@ -919,7 +920,7 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
         .right = {},
     };
     shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual;
-    shared_memory_entry.footer_type = AppletFooterUiType::None;
+    shared_memory_entry.applet_footer.type = AppletFooterUiType::None;
 
     controller.is_connected = false;
     controller.device->Disconnect();
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 0a2dc69920..af4934c558 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -330,10 +330,43 @@ private:
             BitField<13, 1, s32> handheld_lark_nes_left;
             BitField<14, 1, s32> handheld_lark_nes_right;
             BitField<15, 1, s32> lucia;
+            BitField<16, 1, s32> lagon;
+            BitField<17, 1, s32> lager;
             BitField<31, 1, s32> system;
         };
     };
 
+    // This is nn::hid::detail::NfcXcdDeviceHandleStateImpl
+    struct NfcXcdDeviceHandleStateImpl {
+        u64 handle;
+        bool is_available;
+        bool is_activated;
+        INSERT_PADDING_BYTES(0x6); // Reserved
+        u64 sampling_number;
+    };
+    static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
+                  "NfcXcdDeviceHandleStateImpl is an invalid size");
+
+    // nn::hid::detail::NfcXcdDeviceHandleStateImplAtomicStorage
+    struct NfcXcdDeviceHandleStateImplAtomicStorage {
+        u64 sampling_number;
+        NfcXcdDeviceHandleStateImpl nfc_xcd_device_handle_state;
+    };
+    static_assert(sizeof(NfcXcdDeviceHandleStateImplAtomicStorage) == 0x20,
+                  "NfcXcdDeviceHandleStateImplAtomicStorage is an invalid size");
+
+    // This is nn::hid::detail::NfcXcdDeviceHandleState
+    struct NfcXcdDeviceHandleState {
+        // TODO(german77): Make this struct a ring lifo object
+        INSERT_PADDING_BYTES(0x8); // Unused
+        s64 total_buffer_count = max_buffer_size;
+        s64 buffer_tail{};
+        s64 buffer_count{};
+        std::array<NfcXcdDeviceHandleStateImplAtomicStorage, 2> nfc_xcd_device_handle_storage;
+    };
+    static_assert(sizeof(NfcXcdDeviceHandleState) == 0x60,
+                  "NfcXcdDeviceHandleState is an invalid size");
+
     // This is nn::hid::system::AppletFooterUiAttributesSet
     struct AppletFooterUiAttributes {
         INSERT_PADDING_BYTES(0x4);
@@ -365,6 +398,14 @@ private:
         Lagon = 21,
     };
 
+    struct AppletFooterUi {
+        AppletFooterUiAttributes attributes;
+        AppletFooterUiType type;
+        INSERT_PADDING_BYTES(0x5B); // Reserved
+    };
+    static_assert(sizeof(AppletFooterUi) == 0x60,
+                  "AppletFooterUi is an invalid size");
+
     // This is nn::hid::NpadLarkType
     enum class NpadLarkType : u32 {
         Invalid,
@@ -382,6 +423,11 @@ private:
         U,
     };
 
+    // This is nn::hid::NpadLagonType
+    enum class NpadLagonType : u32 {
+        Invalid,
+    };
+
     // This is nn::hid::NpadLagerType
     enum class NpadLagerType : u32 {
         Invalid,
@@ -416,17 +462,19 @@ private:
         Core::HID::BatteryLevel battery_level_dual;
         Core::HID::BatteryLevel battery_level_left;
         Core::HID::BatteryLevel battery_level_right;
-        AppletFooterUiAttributes footer_attributes;
-        AppletFooterUiType footer_type;
-        // GetXcdHandleForNpadWithNfc needs to be checked switchbrew doesn't match with HW
-        INSERT_PADDING_BYTES(0x78); // Unknown
+        union {
+            NfcXcdDeviceHandleState nfc_xcd_device_handle;
+            AppletFooterUi applet_footer;
+        };
+        INSERT_PADDING_BYTES(0x20); // Unknown
         Lifo<NpadGcTriggerState> gc_trigger_lifo;
-        NpadLarkType lark_type_l;
+        NpadLarkType lark_type_l_and_main;
         NpadLarkType lark_type_r;
         NpadLuciaType lucia_type;
+        NpadLagonType lagon_type;
         NpadLagerType lager_type;
         INSERT_PADDING_BYTES(
-            0x8); // FW 13.x Investigate there is some sort of bitflag related to joycons
+            0x4); // FW 13.x Investigate there is some sort of bitflag related to joycons
         INSERT_PADDING_BYTES(0xc08); // Unknown
     };
     static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index 5ba8d96a83..9ae2bf2b15 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -30,8 +30,8 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
     touch_screen_lifo.timestamp = core_timing.GetCPUTicks();
 
     if (!IsControllerActivated()) {
-        touch_screen_lifo.entry_count = 0;
-        touch_screen_lifo.last_entry_index = 0;
+        touch_screen_lifo.buffer_count = 0;
+        touch_screen_lifo.buffer_tail = 0;
         std::memcpy(data, &touch_screen_lifo, sizeof(touch_screen_lifo));
         return;
     }
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp
index aa9f044f19..a2ed1e7c2c 100644
--- a/src/core/hle/service/hid/controllers/xpad.cpp
+++ b/src/core/hle/service/hid/controllers/xpad.cpp
@@ -20,8 +20,8 @@ void Controller_XPad::OnRelease() {}
 void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                std::size_t size) {
     if (!IsControllerActivated()) {
-        basic_xpad_lifo.entry_count = 0;
-        basic_xpad_lifo.last_entry_index = 0;
+        basic_xpad_lifo.buffer_count = 0;
+        basic_xpad_lifo.buffer_tail = 0;
         std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
         return;
     }
diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h
index f68d827622..382350a2d2 100644
--- a/src/core/hle/service/hid/ring_lifo.h
+++ b/src/core/hle/service/hid/ring_lifo.h
@@ -8,7 +8,7 @@
 #include "common/swap.h"
 
 namespace Service::HID {
-constexpr std::size_t max_entry_size = 17;
+constexpr std::size_t max_buffer_size = 17;
 
 template <typename State>
 struct AtomicStorage {
@@ -19,13 +19,13 @@ struct AtomicStorage {
 template <typename State>
 struct Lifo {
     s64 timestamp{};
-    s64 total_entry_count = max_entry_size;
-    s64 last_entry_index{};
-    s64 entry_count{};
-    std::array<AtomicStorage<State>, max_entry_size> entries{};
+    s64 total_buffer_count = max_buffer_size;
+    s64 buffer_tail{};
+    s64 buffer_count{};
+    std::array<AtomicStorage<State>, max_buffer_size> entries{};
 
     const AtomicStorage<State>& ReadCurrentEntry() const {
-        return entries[last_entry_index];
+        return entries[buffer_tail];
     }
 
     const AtomicStorage<State>& ReadPreviousEntry() const {
@@ -33,21 +33,21 @@ struct Lifo {
     }
 
     std::size_t GetPreviuousEntryIndex() const {
-        return (last_entry_index + total_entry_count - 1) % total_entry_count;
+        return (buffer_tail + total_buffer_count - 1) % total_buffer_count;
     }
 
     std::size_t GetNextEntryIndex() const {
-        return (last_entry_index + 1) % total_entry_count;
+        return (buffer_tail + 1) % total_buffer_count;
     }
 
     void WriteNextEntry(const State& new_state) {
-        if (entry_count < total_entry_count - 1) {
-            entry_count++;
+        if (buffer_count < total_buffer_count - 1) {
+            buffer_count++;
         }
-        last_entry_index = GetNextEntryIndex();
+        buffer_tail = GetNextEntryIndex();
         const auto& previous_entry = ReadPreviousEntry();
-        entries[last_entry_index].sampling_number = previous_entry.sampling_number + 1;
-        entries[last_entry_index].state = new_state;
+        entries[buffer_tail].sampling_number = previous_entry.sampling_number + 1;
+        entries[buffer_tail].state = new_state;
     }
 };
 

From d8e3f2b10bad7e4a0ae09c90c76e8a1927c3d1ab Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sat, 30 Oct 2021 11:20:47 -0500
Subject: [PATCH 58/88] input_common: Fix GC adapter initialization

Fix GC controller
---
 src/input_common/drivers/gc_adapter.cpp | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp
index 25b66f528b..62dc287119 100644
--- a/src/input_common/drivers/gc_adapter.cpp
+++ b/src/input_common/drivers/gc_adapter.cpp
@@ -73,7 +73,7 @@ GCAdapter::GCAdapter(const std::string input_engine_) : InputEngine(input_engine
     if (usb_adapter_handle) {
         return;
     }
-    LOG_INFO(Input, "GC Adapter Initialization started");
+    LOG_DEBUG(Input, "Initialization started");
 
     libusb_ctx = std::make_unique<LibUSBContext>();
     const int init_res = libusb_ctx->InitResult();
@@ -90,7 +90,7 @@ GCAdapter::~GCAdapter() {
 }
 
 void GCAdapter::AdapterInputThread(std::stop_token stop_token) {
-    LOG_DEBUG(Input, "GC Adapter input thread started");
+    LOG_DEBUG(Input, "Input thread started");
     Common::SetCurrentThreadName("yuzu:input:GCAdapter");
     s32 payload_size{};
     AdapterPayload adapter_payload{};
@@ -120,7 +120,7 @@ bool GCAdapter::IsPayloadCorrect(const AdapterPayload& adapter_payload, s32 payl
         LOG_DEBUG(Input, "Error reading payload (size: {}, type: {:02x})", payload_size,
                   adapter_payload[0]);
         if (input_error_counter++ > 20) {
-            LOG_ERROR(Input, "GC adapter timeout, Is the adapter connected?");
+            LOG_ERROR(Input, "Timeout, Is the adapter connected?");
             adapter_input_thread.request_stop();
             restart_scan_thread = true;
         }
@@ -263,13 +263,6 @@ bool GCAdapter::Setup() {
 }
 
 bool GCAdapter::CheckDeviceAccess() {
-    // This fixes payload problems from offbrand GCAdapters
-    const s32 control_transfer_error =
-        libusb_control_transfer(usb_adapter_handle->get(), 0x21, 11, 0x0001, 0, nullptr, 0, 1000);
-    if (control_transfer_error < 0) {
-        LOG_ERROR(Input, "libusb_control_transfer failed with error= {}", control_transfer_error);
-    }
-
     s32 kernel_driver_error = libusb_kernel_driver_active(usb_adapter_handle->get(), 0);
     if (kernel_driver_error == 1) {
         kernel_driver_error = libusb_detach_kernel_driver(usb_adapter_handle->get(), 0);
@@ -291,6 +284,13 @@ bool GCAdapter::CheckDeviceAccess() {
         return false;
     }
 
+    // This fixes payload problems from offbrand GCAdapters
+    const s32 control_transfer_error =
+        libusb_control_transfer(usb_adapter_handle->get(), 0x21, 11, 0x0001, 0, nullptr, 0, 1000);
+    if (control_transfer_error < 0) {
+        LOG_ERROR(Input, "libusb_control_transfer failed with error= {}", control_transfer_error);
+    }
+
     return true;
 }
 
@@ -370,9 +370,9 @@ void GCAdapter::SendVibrations() {
         libusb_interrupt_transfer(usb_adapter_handle->get(), output_endpoint, payload.data(),
                                   static_cast<s32>(payload.size()), &size, 16);
     if (err) {
-        LOG_DEBUG(Input, "Adapter libusb write failed: {}", libusb_error_name(err));
+        LOG_DEBUG(Input, "Libusb write failed: {}", libusb_error_name(err));
         if (output_error_counter++ > 5) {
-            LOG_ERROR(Input, "GC adapter output timeout, Rumble disabled");
+            LOG_ERROR(Input, "Output timeout, Rumble disabled");
             rumble_enabled = false;
         }
         return;

From 5f69fdbfccdf68ddb5bb22de32321fa352b22c0a Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sat, 30 Oct 2021 12:12:52 -0500
Subject: [PATCH 59/88] core/hid: Explain better what a temporary value does

---
 src/core/hid/emulated_controller.cpp | 38 +++++++++++++++-------------
 src/core/hid/emulated_controller.h   | 14 +++++-----
 2 files changed, 28 insertions(+), 24 deletions(-)

diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 2b051ccaf2..3c3fa16d60 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -88,8 +88,9 @@ void EmulatedController::ReloadFromSettings() {
     ReloadInput();
 }
 void EmulatedController::LoadDevices() {
-    const auto left_joycon = button_params[Settings::NativeButton::ZL];
-    const auto right_joycon = button_params[Settings::NativeButton::ZR];
+    // TODO(german77): Use more buttons to detect the correct device
+    const auto left_joycon = button_params[Settings::NativeButton::A];
+    const auto right_joycon = button_params[Settings::NativeButton::DRight];
 
     // Triggers for GC controllers
     trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL];
@@ -142,6 +143,7 @@ void EmulatedController::LoadTASParams() {
         param = common_params;
     }
 
+    // TODO(german77): Replace this with an input profile or something better
     tas_button_params[Settings::NativeButton::A].Set("button", 1 << 0);
     tas_button_params[Settings::NativeButton::B].Set("button", 1 << 1);
     tas_button_params[Settings::NativeButton::X].Set("button", 1 << 2);
@@ -271,24 +273,24 @@ void EmulatedController::UnloadInput() {
 
 void EmulatedController::EnableConfiguration() {
     is_configuring = true;
-    temporary_is_connected = is_connected;
-    temporary_npad_type = npad_type;
+    tmp_is_connected = is_connected;
+    tmp_npad_type = npad_type;
 }
 
 void EmulatedController::DisableConfiguration() {
     is_configuring = false;
 
     // Apply temporary npad type to the real controller
-    if (temporary_npad_type != npad_type) {
+    if (tmp_npad_type != npad_type) {
         if (is_connected) {
             Disconnect();
         }
-        SetNpadType(temporary_npad_type);
+        SetNpadType(tmp_npad_type);
     }
 
     // Apply temporary connected status to the real controller
-    if (temporary_is_connected != is_connected) {
-        if (temporary_is_connected) {
+    if (tmp_is_connected != is_connected) {
+        if (tmp_is_connected) {
             Connect();
             return;
         }
@@ -791,7 +793,7 @@ void EmulatedController::Connect() {
     {
         std::lock_guard lock{mutex};
         if (is_configuring) {
-            temporary_is_connected = true;
+            tmp_is_connected = true;
             TriggerOnChange(ControllerTriggerType::Connected, false);
             return;
         }
@@ -808,7 +810,7 @@ void EmulatedController::Disconnect() {
     {
         std::lock_guard lock{mutex};
         if (is_configuring) {
-            temporary_is_connected = false;
+            tmp_is_connected = false;
             TriggerOnChange(ControllerTriggerType::Disconnected, false);
             return;
         }
@@ -821,9 +823,9 @@ void EmulatedController::Disconnect() {
     TriggerOnChange(ControllerTriggerType::Disconnected, true);
 }
 
-bool EmulatedController::IsConnected(bool temporary) const {
-    if (temporary) {
-        return temporary_is_connected;
+bool EmulatedController::IsConnected(bool get_temporary_value) const {
+    if (get_temporary_value) {
+        return tmp_is_connected;
     }
     return is_connected;
 }
@@ -838,9 +840,9 @@ NpadIdType EmulatedController::GetNpadIdType() const {
     return npad_id_type;
 }
 
-NpadType EmulatedController::GetNpadType(bool temporary) const {
-    if (temporary) {
-        return temporary_npad_type;
+NpadType EmulatedController::GetNpadType(bool get_temporary_value) const {
+    if (get_temporary_value) {
+        return tmp_npad_type;
     }
     return npad_type;
 }
@@ -850,10 +852,10 @@ void EmulatedController::SetNpadType(NpadType npad_type_) {
         std::lock_guard lock{mutex};
 
         if (is_configuring) {
-            if (temporary_npad_type == npad_type_) {
+            if (tmp_npad_type == npad_type_) {
                 return;
             }
-            temporary_npad_type = npad_type_;
+            tmp_npad_type = npad_type_;
             TriggerOnChange(ControllerTriggerType::Type, false);
             return;
         }
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index eec51e34a6..fea401365a 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -149,10 +149,10 @@ public:
 
     /**
      * Gets the NpadType for this controller
-     * @param Returns the temporary value if true
+     * @param If true tmp_npad_type will be returned
      * @return NpadType set on the controller
      */
-    NpadType GetNpadType(bool temporary = false) const;
+    NpadType GetNpadType(bool get_temporary_value = false) const;
 
     /// Sets the connected status to true
     void Connect();
@@ -162,10 +162,10 @@ public:
 
     /**
      * Is the emulated connected
-     * @param Returns the temporary value if true
+     * @param If true tmp_is_connected will be returned
      * @return true if the controller has the connected status
      */
-    bool IsConnected(bool temporary = false) const;
+    bool IsConnected(bool get_temporary_value = false) const;
 
     /// Returns true if vibration is enabled
     bool IsVibrationEnabled() const;
@@ -346,12 +346,14 @@ private:
 
     NpadIdType npad_id_type;
     NpadType npad_type{NpadType::None};
-    NpadType temporary_npad_type{NpadType::None};
     bool is_connected{false};
-    bool temporary_is_connected{false};
     bool is_configuring{false};
     f32 motion_sensitivity{0.01f};
 
+    // Temporary values to avoid doing changes while the controller is on configuration mode
+    NpadType tmp_npad_type{NpadType::None};
+    bool tmp_is_connected{false};
+
     ButtonParams button_params;
     StickParams stick_params;
     ControllerMotionParams motion_params;

From 61d9eb9f690d6afe141f24ba75c99b54e122dfa3 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sat, 30 Oct 2021 20:16:10 -0500
Subject: [PATCH 60/88] input_common: Revert deleted TAS functions

---
 src/core/hid/emulated_controller.cpp   | 44 +++++++++----------
 src/input_common/drivers/tas_input.cpp | 23 +++++-----
 src/input_common/drivers/tas_input.h   | 14 +++---
 src/yuzu/bootmanager.cpp               |  1 +
 src/yuzu/debugger/controller.cpp       | 60 ++++++++++++++++++++++++--
 src/yuzu/debugger/controller.h         | 26 +++++++++--
 src/yuzu/main.cpp                      |  2 +-
 7 files changed, 122 insertions(+), 48 deletions(-)

diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 3c3fa16d60..69568f4e92 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -127,7 +127,7 @@ void EmulatedController::LoadDevices() {
     // Initialize TAS devices
     std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(),
                    Input::CreateDevice<Input::InputDevice>);
-    std::transform(tas_stick_params.begin(), tas_stick_params.begin(), tas_stick_devices.begin(),
+    std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(),
                    Input::CreateDevice<Input::InputDevice>);
 }
 
@@ -135,7 +135,7 @@ void EmulatedController::LoadTASParams() {
     const auto player_index = NpadIdTypeToIndex(npad_id_type);
     Common::ParamPackage common_params{};
     common_params.Set("engine", "tas");
-    common_params.Set("pad", static_cast<int>(player_index));
+    common_params.Set("port", static_cast<int>(player_index));
     for (auto& param : tas_button_params) {
         param = common_params;
     }
@@ -144,26 +144,26 @@ void EmulatedController::LoadTASParams() {
     }
 
     // TODO(german77): Replace this with an input profile or something better
-    tas_button_params[Settings::NativeButton::A].Set("button", 1 << 0);
-    tas_button_params[Settings::NativeButton::B].Set("button", 1 << 1);
-    tas_button_params[Settings::NativeButton::X].Set("button", 1 << 2);
-    tas_button_params[Settings::NativeButton::Y].Set("button", 1 << 3);
-    tas_button_params[Settings::NativeButton::LStick].Set("button", 1 << 4);
-    tas_button_params[Settings::NativeButton::RStick].Set("button", 1 << 5);
-    tas_button_params[Settings::NativeButton::L].Set("button", 1 << 6);
-    tas_button_params[Settings::NativeButton::R].Set("button", 1 << 7);
-    tas_button_params[Settings::NativeButton::ZL].Set("button", 1 << 8);
-    tas_button_params[Settings::NativeButton::ZR].Set("button", 1 << 9);
-    tas_button_params[Settings::NativeButton::Plus].Set("button", 1 << 10);
-    tas_button_params[Settings::NativeButton::Minus].Set("button", 1 << 11);
-    tas_button_params[Settings::NativeButton::DLeft].Set("button", 1 << 12);
-    tas_button_params[Settings::NativeButton::DUp].Set("button", 1 << 13);
-    tas_button_params[Settings::NativeButton::DRight].Set("button", 1 << 14);
-    tas_button_params[Settings::NativeButton::DDown].Set("button", 1 << 15);
-    tas_button_params[Settings::NativeButton::SL].Set("button", 1 << 16);
-    tas_button_params[Settings::NativeButton::SR].Set("button", 1 << 17);
-    tas_button_params[Settings::NativeButton::Home].Set("button", 1 << 18);
-    tas_button_params[Settings::NativeButton::Screenshot].Set("button", 1 << 19);
+    tas_button_params[Settings::NativeButton::A].Set("button", 0);
+    tas_button_params[Settings::NativeButton::B].Set("button", 1);
+    tas_button_params[Settings::NativeButton::X].Set("button", 2);
+    tas_button_params[Settings::NativeButton::Y].Set("button", 3);
+    tas_button_params[Settings::NativeButton::LStick].Set("button", 4);
+    tas_button_params[Settings::NativeButton::RStick].Set("button", 5);
+    tas_button_params[Settings::NativeButton::L].Set("button", 6);
+    tas_button_params[Settings::NativeButton::R].Set("button", 7);
+    tas_button_params[Settings::NativeButton::ZL].Set("button", 8);
+    tas_button_params[Settings::NativeButton::ZR].Set("button", 9);
+    tas_button_params[Settings::NativeButton::Plus].Set("button", 10);
+    tas_button_params[Settings::NativeButton::Minus].Set("button", 11);
+    tas_button_params[Settings::NativeButton::DLeft].Set("button", 12);
+    tas_button_params[Settings::NativeButton::DUp].Set("button", 13);
+    tas_button_params[Settings::NativeButton::DRight].Set("button", 14);
+    tas_button_params[Settings::NativeButton::DDown].Set("button", 15);
+    tas_button_params[Settings::NativeButton::SL].Set("button", 16);
+    tas_button_params[Settings::NativeButton::SR].Set("button", 17);
+    tas_button_params[Settings::NativeButton::Home].Set("button", 18);
+    tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
 
     tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
     tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp
index 7e7a1d58f9..d2748b2407 100644
--- a/src/input_common/drivers/tas_input.cpp
+++ b/src/input_common/drivers/tas_input.cpp
@@ -141,7 +141,7 @@ void Tas::WriteTasFile(std::u8string file_name) {
     }
 }
 
-void Tas::RecordInput(u32 buttons, TasAnalog left_axis, TasAnalog right_axis) {
+void Tas::RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis) {
     last_input = {
         .buttons = buttons,
         .l_axis = FlipAxisY(left_axis),
@@ -195,7 +195,7 @@ void Tas::UpdateThread() {
     }
     if (current_command < script_length) {
         LOG_DEBUG(Input, "Playing TAS {}/{}", current_command, script_length);
-        size_t frame = current_command++;
+        const size_t frame = current_command++;
         for (size_t player_index = 0; player_index < commands.size(); player_index++) {
             TASCommand command{};
             if (frame < commands[player_index].size()) {
@@ -207,8 +207,8 @@ void Tas::UpdateThread() {
                 .port = player_index,
                 .pad = 0,
             };
-            for (std::size_t i = 0; i < sizeof(command.buttons); ++i) {
-                const bool button_status = (command.buttons & (1U << i)) != 0;
+            for (std::size_t i = 0; i < sizeof(command.buttons) * 8; ++i) {
+                const bool button_status = (command.buttons & (1LLU << i)) != 0;
                 const int button = static_cast<int>(i);
                 SetButton(identifier, button, button_status);
             }
@@ -244,14 +244,14 @@ TasAnalog Tas::ReadCommandAxis(const std::string& line) const {
     return {x, y};
 }
 
-u32 Tas::ReadCommandButtons(const std::string& data) const {
+u64 Tas::ReadCommandButtons(const std::string& data) const {
     std::stringstream button_text(data);
     std::string line;
-    u32 buttons = 0;
+    u64 buttons = 0;
     while (std::getline(button_text, line, ';')) {
         for (auto [text, tas_button] : text_to_tas_button) {
             if (text == line) {
-                buttons |= static_cast<u32>(tas_button);
+                buttons |= static_cast<u64>(tas_button);
                 break;
             }
         }
@@ -259,13 +259,14 @@ u32 Tas::ReadCommandButtons(const std::string& data) const {
     return buttons;
 }
 
-std::string Tas::WriteCommandButtons(u32 buttons) const {
+std::string Tas::WriteCommandButtons(u64 buttons) const {
     std::string returns = "";
     for (auto [text_button, tas_button] : text_to_tas_button) {
-        if ((buttons & static_cast<u32>(tas_button)) != 0)
-            returns += fmt::format("{};", text_button.substr(4));
+        if ((buttons & static_cast<u64>(tas_button)) != 0) {
+            returns += fmt::format("{};", text_button);
+        }
     }
-    return returns.empty() ? "NONE" : returns.substr(2);
+    return returns.empty() ? "NONE" : returns;
 }
 
 std::string Tas::WriteCommandAxis(TasAnalog analog) const {
diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h
index 9fadc118b7..5f5c3267c3 100644
--- a/src/input_common/drivers/tas_input.h
+++ b/src/input_common/drivers/tas_input.h
@@ -47,7 +47,7 @@ namespace InputCommon::TasInput {
 
 constexpr size_t PLAYER_NUMBER = 10;
 
-enum class TasButton : u32 {
+enum class TasButton : u64 {
     BUTTON_A = 1U << 0,
     BUTTON_B = 1U << 1,
     BUTTON_X = 1U << 2,
@@ -92,7 +92,7 @@ public:
      * @param left_axis: value of the left axis
      * @param right_axis: value of the right axis
      */
-    void RecordInput(u32 buttons, TasAnalog left_axis, TasAnalog right_axis);
+    void RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis);
 
     // Main loop that records or executes input
     void UpdateThread();
@@ -129,7 +129,7 @@ public:
 
 private:
     struct TASCommand {
-        u32 buttons{};
+        u64 buttons{};
         TasAnalog l_axis{};
         TasAnalog r_axis{};
     };
@@ -164,9 +164,9 @@ private:
      * Parses a string containing the button values. Each button is represented by it's text format
      * specified in text_to_tas_button array
      * @param line: string containing button name with the following format "a;b;c;d..."
-     * @return Returns a u32 with each bit representing the status of a button
+     * @return Returns a u64 with each bit representing the status of a button
      */
-    u32 ReadCommandButtons(const std::string& line) const;
+    u64 ReadCommandButtons(const std::string& line) const;
 
     /**
      * Reset state of all players
@@ -174,11 +174,11 @@ private:
     void ClearInput();
 
     /**
-     * Converts an u32 containing the button status into the text equivalent
+     * Converts an u64 containing the button status into the text equivalent
      * @param buttons: bitfield with the status of the buttons
      * @return Returns a string with the name of the buttons to be written to the file
      */
-    std::string WriteCommandButtons(u32 buttons) const;
+    std::string WriteCommandButtons(u64 buttons) const;
 
     /**
      * Converts an TAS analog object containing the axis status into the text equivalent
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 726f789b7f..4b3cd9f3e4 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -35,6 +35,7 @@
 #include "core/frontend/framebuffer_layout.h"
 #include "input_common/drivers/keyboard.h"
 #include "input_common/drivers/mouse.h"
+#include "input_common/drivers/tas_input.h"
 #include "input_common/drivers/touch_screen.h"
 #include "input_common/main.h"
 #include "video_core/renderer_base.h"
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
index f93a46421b..aaca494b8d 100644
--- a/src/yuzu/debugger/controller.cpp
+++ b/src/yuzu/debugger/controller.cpp
@@ -7,11 +7,16 @@
 #include <QString>
 #include "common/settings.h"
 #include "core/core.h"
+#include "core/hid/emulated_controller.h"
+#include "input_common/drivers/tas_input.h"
+#include "input_common/main.h"
 #include "yuzu/configuration/configure_input_player_widget.h"
 #include "yuzu/debugger/controller.h"
 
-ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent)
-    : QWidget(parent, Qt::Dialog) {
+ControllerDialog::ControllerDialog(Core::System& system_,
+                                   std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
+                                   QWidget* parent)
+    : QWidget(parent, Qt::Dialog), system{system_}, input_subsystem{input_subsystem_} {
     setObjectName(QStringLiteral("Controller"));
     setWindowTitle(tr("Controller P1"));
     resize(500, 350);
@@ -21,7 +26,7 @@ ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent)
                    Qt::WindowMaximizeButtonHint);
 
     widget = new PlayerControlPreview(this);
-    widget->SetController(system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1));
+    refreshConfiguration();
     QLayout* layout = new QVBoxLayout(this);
     layout->setContentsMargins(0, 0, 0, 0);
     layout->addWidget(widget);
@@ -34,6 +39,22 @@ ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent)
     widget->setFocus();
 }
 
+void ControllerDialog::refreshConfiguration() {
+    UnloadController();
+    auto* player_1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+    auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+    // Display the correct controller
+    controller = handheld->IsConnected() ? handheld : player_1;
+
+    Core::HID::ControllerUpdateCallback engine_callback{
+        .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); },
+        .is_npad_service = true,
+    };
+    callback_key = controller->SetCallback(engine_callback);
+    widget->SetController(controller);
+    is_controller_set = true;
+}
+
 QAction* ControllerDialog::toggleViewAction() {
     if (toggle_view_action == nullptr) {
         toggle_view_action = new QAction(tr("&Controller P1"), this);
@@ -47,6 +68,10 @@ QAction* ControllerDialog::toggleViewAction() {
 
 void ControllerDialog::UnloadController() {
     widget->UnloadController();
+    if (is_controller_set) {
+        controller->DeleteCallback(callback_key);
+        is_controller_set = false;
+    }
 }
 
 void ControllerDialog::showEvent(QShowEvent* ev) {
@@ -62,3 +87,32 @@ void ControllerDialog::hideEvent(QHideEvent* ev) {
     }
     QWidget::hideEvent(ev);
 }
+
+void ControllerDialog::ControllerUpdate(Core::HID::ControllerTriggerType type) {
+    // TODO(german77): Remove TAS from here
+    switch (type) {
+    case Core::HID::ControllerTriggerType::Button:
+    case Core::HID::ControllerTriggerType::Stick: {
+        const auto buttons_values = controller->GetButtonsValues();
+        const auto stick_values = controller->GetSticksValues();
+        u64 buttons = 0;
+        std::size_t index = 0;
+        for (const auto& button : buttons_values) {
+            buttons |= button.value ? 1LLU << index : 0;
+            index++;
+        }
+        const InputCommon::TasInput::TasAnalog left_axis = {
+            .x = stick_values[Settings::NativeAnalog::LStick].x.value,
+            .y = stick_values[Settings::NativeAnalog::LStick].y.value,
+        };
+        const InputCommon::TasInput::TasAnalog right_axis = {
+            .x = stick_values[Settings::NativeAnalog::RStick].x.value,
+            .y = stick_values[Settings::NativeAnalog::RStick].y.value,
+        };
+        input_subsystem->GetTas()->RecordInput(buttons, left_axis, right_axis);
+        break;
+    }
+    default:
+        break;
+    }
+}
diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h
index 33f617b9b9..ba4185a4bb 100644
--- a/src/yuzu/debugger/controller.h
+++ b/src/yuzu/debugger/controller.h
@@ -11,24 +11,33 @@ class QHideEvent;
 class QShowEvent;
 class PlayerControlPreview;
 
+namespace InputCommon {
+class InputSubsystem;
+}
+
 namespace Core {
 class System;
 }
 
-namespace InputCommon {
-class InputSubsystem;
+namespace Core::HID {
+class EmulatedController;
 }
 
 class ControllerDialog : public QWidget {
     Q_OBJECT
 
 public:
-    explicit ControllerDialog(Core::System& system, QWidget* parent = nullptr);
+    explicit ControllerDialog(Core::System& system_,
+                              std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
+                              QWidget* parent = nullptr);
 
     /// Returns a QAction that can be used to toggle visibility of this dialog.
     QAction* toggleViewAction();
 
-    // Disables events from the emulated controller
+    /// Reloads the widget to apply any changes in the configuration
+    void refreshConfiguration();
+
+    /// Disables events from the emulated controller
     void UnloadController();
 
 protected:
@@ -36,6 +45,15 @@ protected:
     void hideEvent(QHideEvent* ev) override;
 
 private:
+    /// Redirects input from the widget to the TAS driver
+    void ControllerUpdate(Core::HID::ControllerTriggerType type);
+
+    int callback_key;
+    bool is_controller_set{};
+    Core::HID::EmulatedController* controller;
+
     QAction* toggle_view_action = nullptr;
     PlayerControlPreview* widget;
+    Core::System& system;
+    std::shared_ptr<InputCommon::InputSubsystem> input_subsystem;
 };
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 022d11cc49..56db337a4e 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -925,7 +925,7 @@ void GMainWindow::InitializeDebugWidgets() {
     waitTreeWidget->hide();
     debug_menu->addAction(waitTreeWidget->toggleViewAction());
 
-    controller_dialog = new ControllerDialog(*system, this);
+    controller_dialog = new ControllerDialog(*system, input_subsystem, this);
     controller_dialog->hide();
     debug_menu->addAction(controller_dialog->toggleViewAction());
 

From 2b1b0c2a30e242b08ec120e09803ec54d5445703 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sat, 30 Oct 2021 22:23:10 -0500
Subject: [PATCH 61/88] kraken: Address comments from review

start lion review
---
 src/common/input.h                            |   4 +-
 src/common/settings.h                         |   1 -
 src/core/hid/emulated_console.cpp             |  17 +-
 src/core/hid/emulated_console.h               |  15 +-
 src/core/hid/emulated_controller.cpp          |  88 ++++----
 src/core/hid/emulated_controller.h            |  42 ++--
 src/core/hid/emulated_devices.cpp             |  37 ++--
 src/core/hid/emulated_devices.h               |  28 +--
 src/core/hid/input_converter.cpp              |  75 +++----
 src/core/hid/input_converter.h                |  17 +-
 .../hle/service/hid/controllers/debug_pad.cpp |   3 -
 .../hle/service/hid/controllers/keyboard.cpp  |   1 -
 src/core/hle/service/hid/controllers/npad.h   |   3 +-
 src/core/hle/service/hid/ring_lifo.h          |   6 +-
 src/input_common/drivers/gc_adapter.cpp       |  10 +-
 src/input_common/drivers/gc_adapter.h         |   7 +-
 src/input_common/drivers/keyboard.h           |   2 +-
 src/input_common/drivers/mouse.h              |   2 +-
 src/input_common/drivers/sdl_driver.cpp       |  16 +-
 src/input_common/drivers/sdl_driver.h         |   7 +-
 src/input_common/drivers/touch_screen.h       |   2 +-
 .../helpers/stick_from_buttons.cpp            |  70 +++---
 src/input_common/helpers/stick_from_buttons.h |   4 +-
 .../helpers/touch_from_buttons.cpp            |  29 +--
 src/input_common/helpers/touch_from_buttons.h |   4 +-
 src/input_common/input_engine.h               |  14 +-
 src/input_common/input_poller.cpp             | 202 +++++++++---------
 src/input_common/input_poller.h               |  32 +--
 src/input_common/main.cpp                     |  76 ++++---
 .../configure_input_player_widget.cpp         | 105 ++++-----
 .../configure_input_player_widget.h           |  81 +++----
 31 files changed, 534 insertions(+), 466 deletions(-)

diff --git a/src/common/input.h b/src/common/input.h
index cb84f1005a..6d3227f5e2 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -12,7 +12,7 @@
 #include "common/logging/log.h"
 #include "common/param_package.h"
 
-namespace Input {
+namespace Common::Input {
 
 enum class InputType {
     None,
@@ -296,4 +296,4 @@ std::unique_ptr<InputDeviceType> CreateDevice(const Common::ParamPackage package
     return pair->second->Create(package);
 }
 
-} // namespace Input
+} // namespace Common::Input
diff --git a/src/common/settings.h b/src/common/settings.h
index dac44d0006..95225fba7e 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -6,7 +6,6 @@
 
 #include <algorithm>
 #include <array>
-#include <atomic>
 #include <map>
 #include <optional>
 #include <string>
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index d1d4a5355c..c259de0f17 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -55,21 +55,21 @@ void EmulatedConsole::SetTouchParams() {
 
 void EmulatedConsole::ReloadInput() {
     SetTouchParams();
-    motion_devices = Input::CreateDevice<Input::InputDevice>(motion_params);
+    motion_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(motion_params);
     if (motion_devices) {
-        Input::InputCallback motion_callback{
-            [this](Input::CallbackStatus callback) { SetMotion(callback); }};
+        Common::Input::InputCallback motion_callback{
+            [this](Common::Input::CallbackStatus callback) { SetMotion(callback); }};
         motion_devices->SetCallback(motion_callback);
     }
 
     std::size_t index = 0;
     for (auto& touch_device : touch_devices) {
-        touch_device = Input::CreateDevice<Input::InputDevice>(touch_params[index]);
+        touch_device = Common::Input::CreateDevice<Common::Input::InputDevice>(touch_params[index]);
         if (!touch_device) {
             continue;
         }
-        Input::InputCallback touch_callback{
-            [this, index](Input::CallbackStatus callback) { SetTouch(callback, index); }};
+        Common::Input::InputCallback touch_callback{
+            [this, index](Common::Input::CallbackStatus callback) { SetTouch(callback, index); }};
         touch_device->SetCallback(touch_callback);
         index++;
     }
@@ -117,7 +117,7 @@ void EmulatedConsole::SetMotionParam(Common::ParamPackage param) {
     ReloadInput();
 }
 
-void EmulatedConsole::SetMotion(Input::CallbackStatus callback) {
+void EmulatedConsole::SetMotion(Common::Input::CallbackStatus callback) {
     std::lock_guard lock{mutex};
     auto& raw_status = console.motion_values.raw_status;
     auto& emulated = console.motion_values.emulated;
@@ -152,7 +152,8 @@ void EmulatedConsole::SetMotion(Input::CallbackStatus callback) {
     TriggerOnChange(ConsoleTriggerType::Motion);
 }
 
-void EmulatedConsole::SetTouch(Input::CallbackStatus callback, [[maybe_unused]] std::size_t index) {
+void EmulatedConsole::SetTouch(Common::Input::CallbackStatus callback,
+                               [[maybe_unused]] std::size_t index) {
     if (index >= console.touch_values.size()) {
         return;
     }
diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h
index f26f24f2ec..9aec482a6d 100644
--- a/src/core/hid/emulated_console.h
+++ b/src/core/hid/emulated_console.h
@@ -4,10 +4,13 @@
 
 #pragma once
 
+#include <array>
 #include <functional>
+#include <memory>
 #include <mutex>
 #include <unordered_map>
 
+#include "common/common_types.h"
 #include "common/input.h"
 #include "common/param_package.h"
 #include "common/point.h"
@@ -20,18 +23,18 @@
 namespace Core::HID {
 
 struct ConsoleMotionInfo {
-    Input::MotionStatus raw_status{};
+    Common::Input::MotionStatus raw_status{};
     MotionInput emulated{};
 };
 
-using ConsoleMotionDevices = std::unique_ptr<Input::InputDevice>;
-using TouchDevices = std::array<std::unique_ptr<Input::InputDevice>, 16>;
+using ConsoleMotionDevices = std::unique_ptr<Common::Input::InputDevice>;
+using TouchDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, 16>;
 
 using ConsoleMotionParams = Common::ParamPackage;
 using TouchParams = std::array<Common::ParamPackage, 16>;
 
 using ConsoleMotionValues = ConsoleMotionInfo;
-using TouchValues = std::array<Input::TouchStatus, 16>;
+using TouchValues = std::array<Common::Input::TouchStatus, 16>;
 
 struct TouchFinger {
     u64 last_touch{};
@@ -151,14 +154,14 @@ private:
      * Updates the motion status of the console
      * @param A CallbackStatus containing gyro and accelerometer data
      */
-    void SetMotion(Input::CallbackStatus callback);
+    void SetMotion(Common::Input::CallbackStatus callback);
 
     /**
      * Updates the touch status of the console
      * @param callback: A CallbackStatus containing the touch position
      * @param index: Finger ID to be updated
      */
-    void SetTouch(Input::CallbackStatus callback, std::size_t index);
+    void SetTouch(Common::Input::CallbackStatus callback, std::size_t index);
 
     /**
      * Triggers a callback that something has changed on the console status
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 69568f4e92..49893cdbda 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -110,25 +110,25 @@ void EmulatedController::LoadDevices() {
 
     std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
                    button_params.begin() + Settings::NativeButton::BUTTON_NS_END,
-                   button_devices.begin(), Input::CreateDevice<Input::InputDevice>);
+                   button_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>);
     std::transform(stick_params.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
                    stick_params.begin() + Settings::NativeAnalog::STICK_HID_END,
-                   stick_devices.begin(), Input::CreateDevice<Input::InputDevice>);
+                   stick_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>);
     std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
                    motion_params.begin() + Settings::NativeMotion::MOTION_HID_END,
-                   motion_devices.begin(), Input::CreateDevice<Input::InputDevice>);
+                   motion_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>);
     std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(),
-                   Input::CreateDevice<Input::InputDevice>);
+                   Common::Input::CreateDevice<Common::Input::InputDevice>);
     std::transform(battery_params.begin(), battery_params.begin(), battery_devices.end(),
-                   Input::CreateDevice<Input::InputDevice>);
+                   Common::Input::CreateDevice<Common::Input::InputDevice>);
     std::transform(output_params.begin(), output_params.end(), output_devices.begin(),
-                   Input::CreateDevice<Input::OutputDevice>);
+                   Common::Input::CreateDevice<Common::Input::OutputDevice>);
 
     // Initialize TAS devices
     std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(),
-                   Input::CreateDevice<Input::InputDevice>);
+                   Common::Input::CreateDevice<Common::Input::InputDevice>);
     std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(),
-                   Input::CreateDevice<Input::InputDevice>);
+                   Common::Input::CreateDevice<Common::Input::InputDevice>);
 }
 
 void EmulatedController::LoadTASParams() {
@@ -178,8 +178,8 @@ void EmulatedController::ReloadInput() {
         if (!button_devices[index]) {
             continue;
         }
-        Input::InputCallback button_callback{
-            [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }};
+        Common::Input::InputCallback button_callback{
+            [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }};
         button_devices[index]->SetCallback(button_callback);
         button_devices[index]->ForceUpdate();
     }
@@ -188,8 +188,8 @@ void EmulatedController::ReloadInput() {
         if (!stick_devices[index]) {
             continue;
         }
-        Input::InputCallback stick_callback{
-            [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }};
+        Common::Input::InputCallback stick_callback{
+            [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }};
         stick_devices[index]->SetCallback(stick_callback);
         stick_devices[index]->ForceUpdate();
     }
@@ -198,8 +198,8 @@ void EmulatedController::ReloadInput() {
         if (!trigger_devices[index]) {
             continue;
         }
-        Input::InputCallback trigger_callback{
-            [this, index](Input::CallbackStatus callback) { SetTrigger(callback, index); }};
+        Common::Input::InputCallback trigger_callback{
+            [this, index](Common::Input::CallbackStatus callback) { SetTrigger(callback, index); }};
         trigger_devices[index]->SetCallback(trigger_callback);
         trigger_devices[index]->ForceUpdate();
     }
@@ -208,8 +208,8 @@ void EmulatedController::ReloadInput() {
         if (!battery_devices[index]) {
             continue;
         }
-        Input::InputCallback battery_callback{
-            [this, index](Input::CallbackStatus callback) { SetBattery(callback, index); }};
+        Common::Input::InputCallback battery_callback{
+            [this, index](Common::Input::CallbackStatus callback) { SetBattery(callback, index); }};
         battery_devices[index]->SetCallback(battery_callback);
         battery_devices[index]->ForceUpdate();
     }
@@ -218,8 +218,8 @@ void EmulatedController::ReloadInput() {
         if (!motion_devices[index]) {
             continue;
         }
-        Input::InputCallback motion_callback{
-            [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }};
+        Common::Input::InputCallback motion_callback{
+            [this, index](Common::Input::CallbackStatus callback) { SetMotion(callback, index); }};
         motion_devices[index]->SetCallback(motion_callback);
         motion_devices[index]->ForceUpdate();
     }
@@ -229,8 +229,8 @@ void EmulatedController::ReloadInput() {
         if (!tas_button_devices[index]) {
             continue;
         }
-        Input::InputCallback button_callback{
-            [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }};
+        Common::Input::InputCallback button_callback{
+            [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }};
         tas_button_devices[index]->SetCallback(button_callback);
     }
 
@@ -238,8 +238,8 @@ void EmulatedController::ReloadInput() {
         if (!tas_stick_devices[index]) {
             continue;
         }
-        Input::InputCallback stick_callback{
-            [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }};
+        Common::Input::InputCallback stick_callback{
+            [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }};
         tas_stick_devices[index]->SetCallback(stick_callback);
     }
 }
@@ -418,7 +418,7 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage
     ReloadInput();
 }
 
-void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t index) {
+void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index) {
     if (index >= controller.button_values.size()) {
         return;
     }
@@ -548,7 +548,7 @@ void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t i
     TriggerOnChange(ControllerTriggerType::Button, true);
 }
 
-void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t index) {
+void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index) {
     if (index >= controller.stick_values.size()) {
         return;
     }
@@ -587,7 +587,7 @@ void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t in
     TriggerOnChange(ControllerTriggerType::Stick, true);
 }
 
-void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t index) {
+void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index) {
     if (index >= controller.trigger_values.size()) {
         return;
     }
@@ -618,7 +618,7 @@ void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t
     TriggerOnChange(ControllerTriggerType::Trigger, true);
 }
 
-void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t index) {
+void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std::size_t index) {
     if (index >= controller.motion_values.size()) {
         return;
     }
@@ -655,7 +655,7 @@ void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t i
     TriggerOnChange(ControllerTriggerType::Motion, true);
 }
 
-void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t index) {
+void EmulatedController::SetBattery(Common::Input::CallbackStatus callback, std::size_t index) {
     if (index >= controller.battery_values.size()) {
         return;
     }
@@ -671,25 +671,25 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t
     bool is_powered = false;
     BatteryLevel battery_level = 0;
     switch (controller.battery_values[index]) {
-    case Input::BatteryLevel::Charging:
+    case Common::Input::BatteryLevel::Charging:
         is_charging = true;
         is_powered = true;
         battery_level = 6;
         break;
-    case Input::BatteryLevel::Medium:
+    case Common::Input::BatteryLevel::Medium:
         battery_level = 6;
         break;
-    case Input::BatteryLevel::Low:
+    case Common::Input::BatteryLevel::Low:
         battery_level = 4;
         break;
-    case Input::BatteryLevel::Critical:
+    case Common::Input::BatteryLevel::Critical:
         battery_level = 2;
         break;
-    case Input::BatteryLevel::Empty:
+    case Common::Input::BatteryLevel::Empty:
         battery_level = 0;
         break;
-    case Input::BatteryLevel::None:
-    case Input::BatteryLevel::Full:
+    case Common::Input::BatteryLevel::None:
+    case Common::Input::BatteryLevel::Full:
     default:
         is_powered = true;
         battery_level = 8;
@@ -739,18 +739,19 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
 
     // Exponential amplification is too strong at low amplitudes. Switch to a linear
     // amplification if strength is set below 0.7f
-    const Input::VibrationAmplificationType type =
-        strength > 0.7f ? Input::VibrationAmplificationType::Exponential
-                        : Input::VibrationAmplificationType::Linear;
+    const Common::Input::VibrationAmplificationType type =
+        strength > 0.7f ? Common::Input::VibrationAmplificationType::Exponential
+                        : Common::Input::VibrationAmplificationType::Linear;
 
-    const Input::VibrationStatus status = {
+    const Common::Input::VibrationStatus status = {
         .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f),
         .low_frequency = vibration.low_frequency,
         .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f),
         .high_frequency = vibration.high_frequency,
         .type = type,
     };
-    return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None;
+    return output_devices[device_index]->SetVibration(status) ==
+           Common::Input::VibrationError::None;
 }
 
 bool EmulatedController::TestVibration(std::size_t device_index) {
@@ -762,14 +763,15 @@ bool EmulatedController::TestVibration(std::size_t device_index) {
     }
 
     // Send a slight vibration to test for rumble support
-    constexpr Input::VibrationStatus status = {
+    constexpr Common::Input::VibrationStatus status = {
         .low_amplitude = 0.001f,
         .low_frequency = 160.0f,
         .high_amplitude = 0.001f,
         .high_frequency = 320.0f,
-        .type = Input::VibrationAmplificationType::Linear,
+        .type = Common::Input::VibrationAmplificationType::Linear,
     };
-    return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None;
+    return output_devices[device_index]->SetVibration(status) ==
+           Common::Input::VibrationError::None;
 }
 
 void EmulatedController::SetLedPattern() {
@@ -779,7 +781,7 @@ void EmulatedController::SetLedPattern() {
         }
 
         const LedPattern pattern = GetLedPattern();
-        const Input::LedStatus status = {
+        const Common::Input::LedStatus status = {
             .led_1 = pattern.position1 != 0,
             .led_2 = pattern.position2 != 0,
             .led_3 = pattern.position3 != 0,
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index fea401365a..dd9a93364a 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -4,10 +4,13 @@
 
 #pragma once
 
+#include <array>
 #include <functional>
+#include <memory>
 #include <mutex>
 #include <unordered_map>
 
+#include "common/common_types.h"
 #include "common/input.h"
 #include "common/param_package.h"
 #include "common/point.h"
@@ -20,20 +23,22 @@
 namespace Core::HID {
 const std::size_t max_emulated_controllers = 2;
 struct ControllerMotionInfo {
-    Input::MotionStatus raw_status{};
+    Common::Input::MotionStatus raw_status{};
     MotionInput emulated{};
 };
 
 using ButtonDevices =
-    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeButton::NumButtons>;
+    std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeButton::NumButtons>;
 using StickDevices =
-    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeAnalog::NumAnalogs>;
+    std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeAnalog::NumAnalogs>;
 using ControllerMotionDevices =
-    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeMotion::NumMotions>;
+    std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeMotion::NumMotions>;
 using TriggerDevices =
-    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
-using BatteryDevices = std::array<std::unique_ptr<Input::InputDevice>, max_emulated_controllers>;
-using OutputDevices = std::array<std::unique_ptr<Input::OutputDevice>, max_emulated_controllers>;
+    std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
+using BatteryDevices =
+    std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>;
+using OutputDevices =
+    std::array<std::unique_ptr<Common::Input::OutputDevice>, max_emulated_controllers>;
 
 using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
 using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
@@ -42,13 +47,14 @@ using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::
 using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>;
 using OutputParams = std::array<Common::ParamPackage, max_emulated_controllers>;
 
-using ButtonValues = std::array<Input::ButtonStatus, Settings::NativeButton::NumButtons>;
-using SticksValues = std::array<Input::StickStatus, Settings::NativeAnalog::NumAnalogs>;
-using TriggerValues = std::array<Input::TriggerStatus, Settings::NativeTrigger::NumTriggers>;
+using ButtonValues = std::array<Common::Input::ButtonStatus, Settings::NativeButton::NumButtons>;
+using SticksValues = std::array<Common::Input::StickStatus, Settings::NativeAnalog::NumAnalogs>;
+using TriggerValues =
+    std::array<Common::Input::TriggerStatus, Settings::NativeTrigger::NumTriggers>;
 using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>;
-using ColorValues = std::array<Input::BodyColorStatus, max_emulated_controllers>;
-using BatteryValues = std::array<Input::BatteryStatus, max_emulated_controllers>;
-using VibrationValues = std::array<Input::VibrationStatus, max_emulated_controllers>;
+using ColorValues = std::array<Common::Input::BodyColorStatus, max_emulated_controllers>;
+using BatteryValues = std::array<Common::Input::BatteryStatus, max_emulated_controllers>;
+using VibrationValues = std::array<Common::Input::VibrationStatus, max_emulated_controllers>;
 
 struct AnalogSticks {
     AnalogStickState left{};
@@ -307,35 +313,35 @@ private:
      * @param callback: A CallbackStatus containing the button status
      * @param index: Button ID of the to be updated
      */
-    void SetButton(Input::CallbackStatus callback, std::size_t index);
+    void SetButton(Common::Input::CallbackStatus callback, std::size_t index);
 
     /**
      * Updates the analog stick status of the controller
      * @param callback: A CallbackStatus containing the analog stick status
      * @param index: stick ID of the to be updated
      */
-    void SetStick(Input::CallbackStatus callback, std::size_t index);
+    void SetStick(Common::Input::CallbackStatus callback, std::size_t index);
 
     /**
      * Updates the trigger status of the controller
      * @param callback: A CallbackStatus containing the trigger status
      * @param index: trigger ID of the to be updated
      */
-    void SetTrigger(Input::CallbackStatus callback, std::size_t index);
+    void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index);
 
     /**
      * Updates the motion status of the controller
      * @param callback: A CallbackStatus containing gyro and accelerometer data
      * @param index: motion ID of the to be updated
      */
-    void SetMotion(Input::CallbackStatus callback, std::size_t index);
+    void SetMotion(Common::Input::CallbackStatus callback, std::size_t index);
 
     /**
      * Updates the battery status of the controller
      * @param callback: A CallbackStatus containing the battery status
      * @param index: Button ID of the to be updated
      */
-    void SetBattery(Input::CallbackStatus callback, std::size_t index);
+    void SetBattery(Common::Input::CallbackStatus callback, std::size_t index);
 
     /**
      * Triggers a callback that something has changed on the controller status
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
index eb59c310c7..c76a86b6c4 100644
--- a/src/core/hid/emulated_devices.cpp
+++ b/src/core/hid/emulated_devices.cpp
@@ -2,6 +2,7 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included
 
+#include <algorithm>
 #include <fmt/format.h>
 
 #include "core/hid/emulated_devices.h"
@@ -25,21 +26,25 @@ void EmulatedDevices::ReloadFromSettings() {
 void EmulatedDevices::ReloadInput() {
     std::transform(mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_BEGIN,
                    mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_END,
-                   mouse_button_devices.begin(), Input::CreateDevice<Input::InputDevice>);
+                   mouse_button_devices.begin(),
+                   Common::Input::CreateDevice<Common::Input::InputDevice>);
 
     std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(),
-                   keyboard_devices.begin(), Input::CreateDeviceFromString<Input::InputDevice>);
+                   keyboard_devices.begin(),
+                   Common::Input::CreateDeviceFromString<Common::Input::InputDevice>);
 
     std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(),
                    keyboard_modifier_devices.begin(),
-                   Input::CreateDeviceFromString<Input::InputDevice>);
+                   Common::Input::CreateDeviceFromString<Common::Input::InputDevice>);
 
     for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) {
         if (!mouse_button_devices[index]) {
             continue;
         }
-        Input::InputCallback button_callback{
-            [this, index](Input::CallbackStatus callback) { SetMouseButton(callback, index); }};
+        Common::Input::InputCallback button_callback{
+            [this, index](Common::Input::CallbackStatus callback) {
+                SetMouseButton(callback, index);
+            }};
         mouse_button_devices[index]->SetCallback(button_callback);
     }
 
@@ -47,8 +52,10 @@ void EmulatedDevices::ReloadInput() {
         if (!keyboard_devices[index]) {
             continue;
         }
-        Input::InputCallback button_callback{
-            [this, index](Input::CallbackStatus callback) { SetKeyboardButton(callback, index); }};
+        Common::Input::InputCallback button_callback{
+            [this, index](Common::Input::CallbackStatus callback) {
+                SetKeyboardButton(callback, index);
+            }};
         keyboard_devices[index]->SetCallback(button_callback);
     }
 
@@ -56,9 +63,10 @@ void EmulatedDevices::ReloadInput() {
         if (!keyboard_modifier_devices[index]) {
             continue;
         }
-        Input::InputCallback button_callback{[this, index](Input::CallbackStatus callback) {
-            SetKeyboardModifier(callback, index);
-        }};
+        Common::Input::InputCallback button_callback{
+            [this, index](Common::Input::CallbackStatus callback) {
+                SetKeyboardModifier(callback, index);
+            }};
         keyboard_modifier_devices[index]->SetCallback(button_callback);
     }
 }
@@ -122,7 +130,7 @@ void EmulatedDevices::SetMouseButtonParam(std::size_t index, Common::ParamPackag
     ReloadInput();
 }
 
-void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::size_t index) {
+void EmulatedDevices::SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index) {
     if (index >= device_status.keyboard_values.size()) {
         return;
     }
@@ -170,7 +178,7 @@ void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::siz
 void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) {
     constexpr u8 KEYS_PER_BYTE = 8;
     auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE];
-    const u8 mask = 1 << (key_index % KEYS_PER_BYTE);
+    const u8 mask = static_cast<u8>(1 << (key_index % KEYS_PER_BYTE));
     if (status) {
         entry = entry | mask;
     } else {
@@ -178,7 +186,8 @@ void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) {
     }
 }
 
-void EmulatedDevices::SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index) {
+void EmulatedDevices::SetKeyboardModifier(Common::Input::CallbackStatus callback,
+                                          std::size_t index) {
     if (index >= device_status.keyboard_moddifier_values.size()) {
         return;
     }
@@ -247,7 +256,7 @@ void EmulatedDevices::SetKeyboardModifier(Input::CallbackStatus callback, std::s
     TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
 }
 
-void EmulatedDevices::SetMouseButton(Input::CallbackStatus callback, std::size_t index) {
+void EmulatedDevices::SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index) {
     if (index >= device_status.mouse_button_values.size()) {
         return;
     }
diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h
index 7ed95eac6b..418b2f9b55 100644
--- a/src/core/hid/emulated_devices.h
+++ b/src/core/hid/emulated_devices.h
@@ -4,10 +4,13 @@
 
 #pragma once
 
+#include <array>
 #include <functional>
+#include <memory>
 #include <mutex>
 #include <unordered_map>
 
+#include "common/common_types.h"
 #include "common/input.h"
 #include "common/param_package.h"
 #include "common/settings.h"
@@ -16,21 +19,22 @@
 
 namespace Core::HID {
 
-using KeyboardDevices =
-    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeKeyboard::NumKeyboardKeys>;
-using KeyboardModifierDevices =
-    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeKeyboard::NumKeyboardMods>;
-using MouseButtonDevices =
-    std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeMouseButton::NumMouseButtons>;
+using KeyboardDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
+                                   Settings::NativeKeyboard::NumKeyboardKeys>;
+using KeyboardModifierDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
+                                           Settings::NativeKeyboard::NumKeyboardMods>;
+using MouseButtonDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
+                                      Settings::NativeMouseButton::NumMouseButtons>;
 
 using MouseButtonParams =
     std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons>;
 
-using KeyboardValues = std::array<Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardKeys>;
+using KeyboardValues =
+    std::array<Common::Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardKeys>;
 using KeyboardModifierValues =
-    std::array<Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardMods>;
+    std::array<Common::Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardMods>;
 using MouseButtonValues =
-    std::array<Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>;
+    std::array<Common::Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>;
 
 struct MousePosition {
     s32 x;
@@ -151,21 +155,21 @@ private:
      * @param callback: A CallbackStatus containing the key status
      * @param index: key ID to be updated
      */
-    void SetKeyboardButton(Input::CallbackStatus callback, std::size_t index);
+    void SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index);
 
     /**
      * Updates the touch status of the console
      * @param callback: A CallbackStatus containing the modifier key status
      * @param index: modifier key ID to be updated
      */
-    void SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index);
+    void SetKeyboardModifier(Common::Input::CallbackStatus callback, std::size_t index);
 
     /**
      * Updates the touch status of the console
      * @param callback: A CallbackStatus containing the button status
      * @param index: Button ID of the to be updated
      */
-    void SetMouseButton(Input::CallbackStatus callback, std::size_t index);
+    void SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index);
 
     /**
      * Triggers a callback that something has changed on the device status
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index e2598f367c..14204917e1 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -9,35 +9,35 @@
 
 namespace Core::HID {
 
-Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback) {
-    Input::BatteryStatus battery{Input::BatteryStatus::None};
+Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback) {
+    Common::Input::BatteryStatus battery{Common::Input::BatteryStatus::None};
     switch (callback.type) {
-    case Input::InputType::Analog:
-    case Input::InputType::Trigger: {
+    case Common::Input::InputType::Analog:
+    case Common::Input::InputType::Trigger: {
         const auto value = TransformToTrigger(callback).analog.value;
-        battery = Input::BatteryLevel::Empty;
+        battery = Common::Input::BatteryLevel::Empty;
         if (value > 0.2f) {
-            battery = Input::BatteryLevel::Critical;
+            battery = Common::Input::BatteryLevel::Critical;
         }
         if (value > 0.4f) {
-            battery = Input::BatteryLevel::Low;
+            battery = Common::Input::BatteryLevel::Low;
         }
         if (value > 0.6f) {
-            battery = Input::BatteryLevel::Medium;
+            battery = Common::Input::BatteryLevel::Medium;
         }
         if (value > 0.8f) {
-            battery = Input::BatteryLevel::Full;
+            battery = Common::Input::BatteryLevel::Full;
         }
         if (value >= 1.0f) {
-            battery = Input::BatteryLevel::Charging;
+            battery = Common::Input::BatteryLevel::Charging;
         }
         break;
     }
-    case Input::InputType::Button:
-        battery = callback.button_status.value ? Input::BatteryLevel::Charging
-                                               : Input::BatteryLevel::Critical;
+    case Common::Input::InputType::Button:
+        battery = callback.button_status.value ? Common::Input::BatteryLevel::Charging
+                                               : Common::Input::BatteryLevel::Critical;
         break;
-    case Input::InputType::Battery:
+    case Common::Input::InputType::Battery:
         battery = callback.battery_status;
         break;
     default:
@@ -48,14 +48,14 @@ Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback) {
     return battery;
 }
 
-Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback) {
-    Input::ButtonStatus status{};
+Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback) {
+    Common::Input::ButtonStatus status{};
     switch (callback.type) {
-    case Input::InputType::Analog:
-    case Input::InputType::Trigger:
+    case Common::Input::InputType::Analog:
+    case Common::Input::InputType::Trigger:
         status.value = TransformToTrigger(callback).pressed;
         break;
-    case Input::InputType::Button:
+    case Common::Input::InputType::Button:
         status = callback.button_status;
         break;
     default:
@@ -70,15 +70,15 @@ Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback) {
     return status;
 }
 
-Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback) {
-    Input::MotionStatus status{};
+Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback) {
+    Common::Input::MotionStatus status{};
     switch (callback.type) {
-    case Input::InputType::Button: {
+    case Common::Input::InputType::Button: {
         if (TransformToButton(callback).value) {
             std::random_device device;
             std::mt19937 gen(device());
             std::uniform_int_distribution<s16> distribution(-1000, 1000);
-            Input::AnalogProperties properties{
+            Common::Input::AnalogProperties properties{
                 .deadzone = 0.0,
                 .range = 1.0f,
                 .offset = 0.0,
@@ -116,7 +116,7 @@ Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback) {
         }
         break;
     }
-    case Input::InputType::Motion:
+    case Common::Input::InputType::Motion:
         status = callback.motion_status;
         break;
     default:
@@ -133,11 +133,11 @@ Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback) {
     return status;
 }
 
-Input::StickStatus TransformToStick(const Input::CallbackStatus& callback) {
-    Input::StickStatus status{};
+Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback) {
+    Common::Input::StickStatus status{};
 
     switch (callback.type) {
-    case Input::InputType::Stick:
+    case Common::Input::InputType::Stick:
         status = callback.stick_status;
         break;
     default:
@@ -160,11 +160,11 @@ Input::StickStatus TransformToStick(const Input::CallbackStatus& callback) {
     return status;
 }
 
-Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback) {
-    Input::TouchStatus status{};
+Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback) {
+    Common::Input::TouchStatus status{};
 
     switch (callback.type) {
-    case Input::InputType::Touch:
+    case Common::Input::InputType::Touch:
         status = callback.touch_status;
         break;
     default:
@@ -192,22 +192,22 @@ Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback) {
     return status;
 }
 
-Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback) {
-    Input::TriggerStatus status{};
+Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback) {
+    Common::Input::TriggerStatus status{};
     float& raw_value = status.analog.raw_value;
     bool calculate_button_value = true;
 
     switch (callback.type) {
-    case Input::InputType::Analog:
+    case Common::Input::InputType::Analog:
         status.analog.properties = callback.analog_status.properties;
         raw_value = callback.analog_status.raw_value;
         break;
-    case Input::InputType::Button:
+    case Common::Input::InputType::Button:
         status.analog.properties.range = 1.0f;
         status.analog.properties.inverted = callback.button_status.inverted;
         raw_value = callback.button_status.value ? 1.0f : 0.0f;
         break;
-    case Input::InputType::Trigger:
+    case Common::Input::InputType::Trigger:
         status = callback.trigger_status;
         calculate_button_value = false;
         break;
@@ -234,7 +234,7 @@ Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback) {
     return status;
 }
 
-void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value) {
+void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) {
     const auto& properties = analog.properties;
     float& raw_value = analog.raw_value;
     float& value = analog.value;
@@ -274,7 +274,8 @@ void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value) {
     }
 }
 
-void SanitizeStick(Input::AnalogStatus& analog_x, Input::AnalogStatus& analog_y, bool clamp_value) {
+void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y,
+                   bool clamp_value) {
     const auto& properties_x = analog_x.properties;
     const auto& properties_y = analog_y.properties;
     float& raw_x = analog_x.raw_value;
diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h
index 3cc32e26a9..b38e657b08 100644
--- a/src/core/hid/input_converter.h
+++ b/src/core/hid/input_converter.h
@@ -16,7 +16,7 @@ namespace Core::HID {
  * @param Supported callbacks: Analog, Battery, Trigger.
  * @return A valid BatteryStatus object.
  */
-Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback);
+Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback);
 
 /**
  * Converts raw input data into a valid button status. Applies invert properties to the output.
@@ -24,7 +24,7 @@ Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback);
  * @param Supported callbacks: Analog, Button, Trigger.
  * @return A valid TouchStatus object.
  */
-Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback);
+Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback);
 
 /**
  * Converts raw input data into a valid motion status.
@@ -32,7 +32,7 @@ Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback);
  * @param Supported callbacks: Motion.
  * @return A valid TouchStatus object.
  */
-Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback);
+Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback);
 
 /**
  * Converts raw input data into a valid stick status. Applies offset, deadzone, range and invert
@@ -41,7 +41,7 @@ Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback);
  * @param Supported callbacks: Stick.
  * @return A valid StickStatus object.
  */
-Input::StickStatus TransformToStick(const Input::CallbackStatus& callback);
+Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback);
 
 /**
  * Converts raw input data into a valid touch status.
@@ -49,7 +49,7 @@ Input::StickStatus TransformToStick(const Input::CallbackStatus& callback);
  * @param Supported callbacks: Touch.
  * @return A valid TouchStatus object.
  */
-Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback);
+Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback);
 
 /**
  * Converts raw input data into a valid trigger status. Applies offset, deadzone, range and
@@ -58,20 +58,21 @@ Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback);
  * @param Supported callbacks: Analog, Button, Trigger.
  * @return A valid TriggerStatus object.
  */
-Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback);
+Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback);
 
 /**
  * Converts raw analog data into a valid analog value
  * @param An analog object containing raw data and properties, bool that determines if the value
  * needs to be clamped between -1.0f and 1.0f.
  */
-void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value);
+void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value);
 
 /**
  * Converts raw stick data into a valid stick value
  * @param Two analog objects containing raw data and properties, bool that determines if the value
  * needs to be clamped into the unit circle.
  */
-void SanitizeStick(Input::AnalogStatus& analog_x, Input::AnalogStatus& analog_y, bool clamp_value);
+void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y,
+                   bool clamp_value);
 
 } // namespace Core::HID
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index 345134357d..b009ed086e 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -13,9 +13,6 @@
 
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
-constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
-[[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
-enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right };
 
 Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} {
     controller = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Other);
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index f4d49965ff..60dc62f2c8 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -12,7 +12,6 @@
 
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
-constexpr u8 KEYS_PER_BYTE = 8;
 
 Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} {
     emulated_devices = system.HIDCore().GetEmulatedDevices();
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index af4934c558..4a9c9cc1ab 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -403,8 +403,7 @@ private:
         AppletFooterUiType type;
         INSERT_PADDING_BYTES(0x5B); // Reserved
     };
-    static_assert(sizeof(AppletFooterUi) == 0x60,
-                  "AppletFooterUi is an invalid size");
+    static_assert(sizeof(AppletFooterUi) == 0x60, "AppletFooterUi is an invalid size");
 
     // This is nn::hid::NpadLarkType
     enum class NpadLarkType : u32 {
diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h
index 382350a2d2..6209ed0d15 100644
--- a/src/core/hle/service/hid/ring_lifo.h
+++ b/src/core/hle/service/hid/ring_lifo.h
@@ -4,6 +4,8 @@
 
 #pragma once
 
+#include <array>
+
 #include "common/common_types.h"
 #include "common/swap.h"
 
@@ -29,10 +31,10 @@ struct Lifo {
     }
 
     const AtomicStorage<State>& ReadPreviousEntry() const {
-        return entries[GetPreviuousEntryIndex()];
+        return entries[GetPreviousEntryIndex()];
     }
 
-    std::size_t GetPreviuousEntryIndex() const {
+    std::size_t GetPreviousEntryIndex() const {
         return (buffer_tail + total_buffer_count - 1) % total_buffer_count;
     }
 
diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp
index 62dc287119..2550f8cba5 100644
--- a/src/input_common/drivers/gc_adapter.cpp
+++ b/src/input_common/drivers/gc_adapter.cpp
@@ -248,7 +248,7 @@ bool GCAdapter::Setup() {
         std::size_t port = 0;
         for (GCController& pad : pads) {
             pad.identifier = {
-                .guid = Common::UUID{""},
+                .guid = Common::UUID{Common::INVALID_UUID},
                 .port = port++,
                 .pad = 0,
             };
@@ -325,8 +325,8 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) {
     return true;
 }
 
-Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier,
-                                           const Input::VibrationStatus vibration) {
+Common::Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier,
+                                                   const Common::Input::VibrationStatus vibration) {
     const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f;
     const auto processed_amplitude =
         static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8);
@@ -334,9 +334,9 @@ Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier,
     pads[identifier.port].rumble_amplitude = processed_amplitude;
 
     if (!rumble_enabled) {
-        return Input::VibrationError::Disabled;
+        return Common::Input::VibrationError::Disabled;
     }
-    return Input::VibrationError::None;
+    return Common::Input::VibrationError::None;
 }
 
 void GCAdapter::UpdateVibrations() {
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h
index b82e4803dd..fba90352e9 100644
--- a/src/input_common/drivers/gc_adapter.h
+++ b/src/input_common/drivers/gc_adapter.h
@@ -4,8 +4,11 @@
 
 #pragma once
 
+#include <array>
+#include <memory>
 #include <mutex>
 #include <stop_token>
+#include <string>
 #include <thread>
 
 #include "input_common/input_engine.h"
@@ -24,8 +27,8 @@ public:
     explicit GCAdapter(const std::string input_engine_);
     ~GCAdapter();
 
-    Input::VibrationError SetRumble(const PadIdentifier& identifier,
-                                    const Input::VibrationStatus vibration) override;
+    Common::Input::VibrationError SetRumble(
+        const PadIdentifier& identifier, const Common::Input::VibrationStatus vibration) override;
 
     /// Used for automapping features
     std::vector<Common::ParamPackage> GetInputDevices() const override;
diff --git a/src/input_common/drivers/keyboard.h b/src/input_common/drivers/keyboard.h
index a3e0d8a617..58df150507 100644
--- a/src/input_common/drivers/keyboard.h
+++ b/src/input_common/drivers/keyboard.h
@@ -35,7 +35,7 @@ public:
 
 private:
     const PadIdentifier identifier = {
-        .guid = Common::UUID{""},
+        .guid = Common::UUID{Common::INVALID_UUID},
         .port = 0,
         .pad = 0,
     };
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index d3178b1a9b..cf09184098 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -63,7 +63,7 @@ private:
     void StopPanning();
 
     const PadIdentifier identifier = {
-        .guid = Common::UUID{""},
+        .guid = Common::UUID{Common::INVALID_UUID},
         .port = 0,
         .pad = 0,
     };
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index 53e282ef3c..1e3741e0f8 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -92,7 +92,7 @@ public:
         return motion;
     }
 
-    bool RumblePlay(const Input::VibrationStatus vibration) {
+    bool RumblePlay(const Common::Input::VibrationStatus vibration) {
         constexpr u32 rumble_max_duration_ms = 1000;
         if (sdl_controller) {
             return SDL_GameControllerRumble(
@@ -515,8 +515,8 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
     }
     return devices;
 }
-Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier,
-                                           const Input::VibrationStatus vibration) {
+Common::Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier,
+                                                   const Common::Input::VibrationStatus vibration) {
     const auto joystick =
         GetSDLJoystickByGUID(identifier.guid.Format(), static_cast<int>(identifier.port));
     const auto process_amplitude_exp = [](f32 amplitude, f32 factor) {
@@ -527,7 +527,7 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier,
     f32 factor = 0.35f;
 
     // If vibration is set as a linear output use a flatter value
-    if (vibration.type == Input::VibrationAmplificationType::Linear) {
+    if (vibration.type == Common::Input::VibrationAmplificationType::Linear) {
         factor = 0.5f;
     }
 
@@ -536,19 +536,19 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier,
         factor = 1.0f;
     }
 
-    const Input::VibrationStatus new_vibration{
+    const Common::Input::VibrationStatus new_vibration{
         .low_amplitude = process_amplitude_exp(vibration.low_amplitude, factor),
         .low_frequency = vibration.low_frequency,
         .high_amplitude = process_amplitude_exp(vibration.high_amplitude, factor),
         .high_frequency = vibration.high_frequency,
-        .type = Input::VibrationAmplificationType::Exponential,
+        .type = Common::Input::VibrationAmplificationType::Exponential,
     };
 
     if (!joystick->RumblePlay(new_vibration)) {
-        return Input::VibrationError::Unknown;
+        return Common::Input::VibrationError::Unknown;
     }
 
-    return Input::VibrationError::None;
+    return Common::Input::VibrationError::None;
 }
 Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,
                                                                  s32 axis, float value) const {
diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h
index 1ff85f48de..b879df8abf 100644
--- a/src/input_common/drivers/sdl_driver.h
+++ b/src/input_common/drivers/sdl_driver.h
@@ -58,8 +58,8 @@ public:
     std::string GetHatButtonName(u8 direction_value) const override;
     u8 GetHatButtonId(const std::string direction_name) const override;
 
-    Input::VibrationError SetRumble(const PadIdentifier& identifier,
-                                    const Input::VibrationStatus vibration) override;
+    Common::Input::VibrationError SetRumble(
+        const PadIdentifier& identifier, const Common::Input::VibrationStatus vibration) override;
 
 private:
     void InitJoystick(int joystick_index);
@@ -105,9 +105,6 @@ private:
     /// Returns true if the button is on the left joycon
     bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const;
 
-    // Set to true if SDL supports game controller subsystem
-    bool has_gamecontroller = false;
-
     /// Map of GUID of a list of corresponding virtual Joysticks
     std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
     std::mutex joystick_map_mutex;
diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h
index 5fbb2f47ff..d297d253ce 100644
--- a/src/input_common/drivers/touch_screen.h
+++ b/src/input_common/drivers/touch_screen.h
@@ -41,7 +41,7 @@ public:
 
 private:
     const PadIdentifier identifier = {
-        .guid = Common::UUID{""},
+        .guid = Common::UUID{Common::INVALID_UUID},
         .port = 0,
         .pad = 0,
     };
diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp
index 806a0e8bba..1d5948f793 100644
--- a/src/input_common/helpers/stick_from_buttons.cpp
+++ b/src/input_common/helpers/stick_from_buttons.cpp
@@ -10,25 +10,27 @@
 
 namespace InputCommon {
 
-class Stick final : public Input::InputDevice {
+class Stick final : public Common::Input::InputDevice {
 public:
-    using Button = std::unique_ptr<Input::InputDevice>;
+    using Button = std::unique_ptr<Common::Input::InputDevice>;
 
     Stick(Button up_, Button down_, Button left_, Button right_, Button modifier_,
           float modifier_scale_, float modifier_angle_)
         : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)),
           right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_),
           modifier_angle(modifier_angle_) {
-        Input::InputCallback button_up_callback{
-            [this](Input::CallbackStatus callback_) { UpdateUpButtonStatus(callback_); }};
-        Input::InputCallback button_down_callback{
-            [this](Input::CallbackStatus callback_) { UpdateDownButtonStatus(callback_); }};
-        Input::InputCallback button_left_callback{
-            [this](Input::CallbackStatus callback_) { UpdateLeftButtonStatus(callback_); }};
-        Input::InputCallback button_right_callback{
-            [this](Input::CallbackStatus callback_) { UpdateRightButtonStatus(callback_); }};
-        Input::InputCallback button_modifier_callback{
-            [this](Input::CallbackStatus callback_) { UpdateModButtonStatus(callback_); }};
+        Common::Input::InputCallback button_up_callback{
+            [this](Common::Input::CallbackStatus callback_) { UpdateUpButtonStatus(callback_); }};
+        Common::Input::InputCallback button_down_callback{
+            [this](Common::Input::CallbackStatus callback_) { UpdateDownButtonStatus(callback_); }};
+        Common::Input::InputCallback button_left_callback{
+            [this](Common::Input::CallbackStatus callback_) { UpdateLeftButtonStatus(callback_); }};
+        Common::Input::InputCallback button_right_callback{
+            [this](Common::Input::CallbackStatus callback_) {
+                UpdateRightButtonStatus(callback_);
+            }};
+        Common::Input::InputCallback button_modifier_callback{
+            [this](Common::Input::CallbackStatus callback_) { UpdateModButtonStatus(callback_); }};
         up->SetCallback(button_up_callback);
         down->SetCallback(button_down_callback);
         left->SetCallback(button_left_callback);
@@ -129,27 +131,27 @@ public:
         }
     }
 
-    void UpdateUpButtonStatus(Input::CallbackStatus button_callback) {
+    void UpdateUpButtonStatus(Common::Input::CallbackStatus button_callback) {
         up_status = button_callback.button_status.value;
         UpdateStatus();
     }
 
-    void UpdateDownButtonStatus(Input::CallbackStatus button_callback) {
+    void UpdateDownButtonStatus(Common::Input::CallbackStatus button_callback) {
         down_status = button_callback.button_status.value;
         UpdateStatus();
     }
 
-    void UpdateLeftButtonStatus(Input::CallbackStatus button_callback) {
+    void UpdateLeftButtonStatus(Common::Input::CallbackStatus button_callback) {
         left_status = button_callback.button_status.value;
         UpdateStatus();
     }
 
-    void UpdateRightButtonStatus(Input::CallbackStatus button_callback) {
+    void UpdateRightButtonStatus(Common::Input::CallbackStatus button_callback) {
         right_status = button_callback.button_status.value;
         UpdateStatus();
     }
 
-    void UpdateModButtonStatus(Input::CallbackStatus button_callback) {
+    void UpdateModButtonStatus(Common::Input::CallbackStatus button_callback) {
         modifier_status = button_callback.button_status.value;
         UpdateStatus();
     }
@@ -193,8 +195,8 @@ public:
         }
 
         last_update = now;
-        Input::CallbackStatus status{
-            .type = Input::InputType::Stick,
+        Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Stick,
             .stick_status = GetStatus(),
         };
         TriggerOnChange(status);
@@ -209,15 +211,15 @@ public:
     }
 
     void SoftUpdate() override {
-        Input::CallbackStatus status{
-            .type = Input::InputType::Stick,
+        Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Stick,
             .stick_status = GetStatus(),
         };
         TriggerOnChange(status);
     }
 
-    Input::StickStatus GetStatus() const {
-        Input::StickStatus status{};
+    Common::Input::StickStatus GetStatus() const {
+        Common::Input::StickStatus status{};
         status.x.properties = properties;
         status.y.properties = properties;
         if (Settings::values.emulate_analog_keyboard) {
@@ -263,19 +265,23 @@ private:
     bool left_status;
     bool right_status;
     bool modifier_status;
-    const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
+    const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
     std::chrono::time_point<std::chrono::steady_clock> last_update;
 };
 
-std::unique_ptr<Input::InputDevice> StickFromButton::Create(const Common::ParamPackage& params) {
+std::unique_ptr<Common::Input::InputDevice> StickFromButton::Create(
+    const Common::ParamPackage& params) {
     const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
-    auto up = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("up", null_engine));
-    auto down = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("down", null_engine));
-    auto left = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("left", null_engine));
-    auto right =
-        Input::CreateDeviceFromString<Input::InputDevice>(params.Get("right", null_engine));
-    auto modifier =
-        Input::CreateDeviceFromString<Input::InputDevice>(params.Get("modifier", null_engine));
+    auto up = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
+        params.Get("up", null_engine));
+    auto down = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
+        params.Get("down", null_engine));
+    auto left = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
+        params.Get("left", null_engine));
+    auto right = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
+        params.Get("right", null_engine));
+    auto modifier = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
+        params.Get("modifier", null_engine));
     auto modifier_scale = params.Get("modifier_scale", 0.5f);
     auto modifier_angle = params.Get("modifier_angle", 5.5f);
     return std::make_unique<Stick>(std::move(up), std::move(down), std::move(left),
diff --git a/src/input_common/helpers/stick_from_buttons.h b/src/input_common/helpers/stick_from_buttons.h
index 82dff5ca87..437ace4f7e 100644
--- a/src/input_common/helpers/stick_from_buttons.h
+++ b/src/input_common/helpers/stick_from_buttons.h
@@ -12,7 +12,7 @@ namespace InputCommon {
  * An analog device factory that takes direction button devices and combines them into a analog
  * device.
  */
-class StickFromButton final : public Input::Factory<Input::InputDevice> {
+class StickFromButton final : public Common::Input::Factory<Common::Input::InputDevice> {
 public:
     /**
      * Creates an analog device from direction button devices
@@ -24,7 +24,7 @@ public:
      *     - "modifier": a serialized ParamPackage for creating a button device as the modifier
      *     - "modifier_scale": a float for the multiplier the modifier gives to the position
      */
-    std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
+    std::unique_ptr<Common::Input::InputDevice> Create(const Common::ParamPackage& params) override;
 };
 
 } // namespace InputCommon
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp
index bb2bad5b11..fee41cae34 100644
--- a/src/input_common/helpers/touch_from_buttons.cpp
+++ b/src/input_common/helpers/touch_from_buttons.cpp
@@ -9,22 +9,22 @@
 
 namespace InputCommon {
 
-class TouchFromButtonDevice final : public Input::InputDevice {
+class TouchFromButtonDevice final : public Common::Input::InputDevice {
 public:
-    using Button = std::unique_ptr<Input::InputDevice>;
+    using Button = std::unique_ptr<Common::Input::InputDevice>;
     TouchFromButtonDevice(Button button_, u32 touch_id_, float x_, float y_)
         : button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) {
-        Input::InputCallback button_up_callback{
-            [this](Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }};
+        Common::Input::InputCallback button_up_callback{
+            [this](Common::Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }};
         button->SetCallback(button_up_callback);
         button->ForceUpdate();
     }
 
-    Input::TouchStatus GetStatus(bool pressed) const {
-        const Input::ButtonStatus button_status{
+    Common::Input::TouchStatus GetStatus(bool pressed) const {
+        const Common::Input::ButtonStatus button_status{
             .value = pressed,
         };
-        Input::TouchStatus status{
+        Common::Input::TouchStatus status{
             .pressed = button_status,
             .x = {},
             .y = {},
@@ -42,9 +42,9 @@ public:
         return status;
     }
 
-    void UpdateButtonStatus(Input::CallbackStatus button_callback) {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Touch,
+    void UpdateButtonStatus(Common::Input::CallbackStatus button_callback) {
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Touch,
             .touch_status = GetStatus(button_callback.button_status.value),
         };
         TriggerOnChange(status);
@@ -55,13 +55,14 @@ private:
     const u32 touch_id;
     const float x;
     const float y;
-    const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
+    const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
 };
 
-std::unique_ptr<Input::InputDevice> TouchFromButton::Create(const Common::ParamPackage& params) {
+std::unique_ptr<Common::Input::InputDevice> TouchFromButton::Create(
+    const Common::ParamPackage& params) {
     const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
-    auto button =
-        Input::CreateDeviceFromString<Input::InputDevice>(params.Get("button", null_engine));
+    auto button = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
+        params.Get("button", null_engine));
     const auto touch_id = params.Get("touch_id", 0);
     const float x = params.Get("x", 0.0f) / 1280.0f;
     const float y = params.Get("y", 0.0f) / 720.0f;
diff --git a/src/input_common/helpers/touch_from_buttons.h b/src/input_common/helpers/touch_from_buttons.h
index 21b353728a..628f182157 100644
--- a/src/input_common/helpers/touch_from_buttons.h
+++ b/src/input_common/helpers/touch_from_buttons.h
@@ -11,12 +11,12 @@ namespace InputCommon {
 /**
  * A touch device factory that takes a list of button devices and combines them into a touch device.
  */
-class TouchFromButton final : public Input::Factory<Input::InputDevice> {
+class TouchFromButton final : public Common::Input::Factory<Common::Input::InputDevice> {
 public:
     /**
      * Creates a touch device from a list of button devices
      */
-    std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
+    std::unique_ptr<Common::Input::InputDevice> Create(const Common::ParamPackage& params) override;
 };
 
 } // namespace InputCommon
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h
index 31ce900d76..ed79d3d934 100644
--- a/src/input_common/input_engine.h
+++ b/src/input_common/input_engine.h
@@ -116,22 +116,22 @@ public:
 
     // Sets a led pattern for a controller
     virtual void SetLeds([[maybe_unused]] const PadIdentifier& identifier,
-                         [[maybe_unused]] const Input::LedStatus led_status) {
+                         [[maybe_unused]] const Common::Input::LedStatus led_status) {
         return;
     }
 
     // Sets rumble to a controller
-    virtual Input::VibrationError SetRumble(
+    virtual Common::Input::VibrationError SetRumble(
         [[maybe_unused]] const PadIdentifier& identifier,
-        [[maybe_unused]] const Input::VibrationStatus vibration) {
-        return Input::VibrationError::NotSupported;
+        [[maybe_unused]] const Common::Input::VibrationStatus vibration) {
+        return Common::Input::VibrationError::NotSupported;
     }
 
     // Sets polling mode to a controller
-    virtual Input::PollingError SetPollingMode(
+    virtual Common::Input::PollingError SetPollingMode(
         [[maybe_unused]] const PadIdentifier& identifier,
-        [[maybe_unused]] const Input::PollingMode vibration) {
-        return Input::PollingError::NotSupported;
+        [[maybe_unused]] const Common::Input::PollingMode vibration) {
+        return Common::Input::PollingError::NotSupported;
     }
 
     // Returns the engine name
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 6edb8d9005..2b3b779380 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -10,13 +10,13 @@
 
 namespace InputCommon {
 
-class DummyInput final : public Input::InputDevice {
+class DummyInput final : public Common::Input::InputDevice {
 public:
     explicit DummyInput() {}
     ~DummyInput() {}
 };
 
-class InputFromButton final : public Input::InputDevice {
+class InputFromButton final : public Common::Input::InputDevice {
 public:
     explicit InputFromButton(PadIdentifier identifier_, u32 button_, bool toggle_, bool inverted_,
                              InputEngine* input_engine_)
@@ -37,7 +37,7 @@ public:
         input_engine->DeleteCallback(callback_key);
     }
 
-    Input::ButtonStatus GetStatus() const {
+    Common::Input::ButtonStatus GetStatus() const {
         return {
             .value = input_engine->GetButton(identifier, button),
             .inverted = inverted,
@@ -46,8 +46,8 @@ public:
     }
 
     void ForceUpdate() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Button,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Button,
             .button_status = GetStatus(),
         };
 
@@ -56,8 +56,8 @@ public:
     }
 
     void OnChange() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Button,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Button,
             .button_status = GetStatus(),
         };
 
@@ -77,7 +77,7 @@ private:
     InputEngine* input_engine;
 };
 
-class InputFromHatButton final : public Input::InputDevice {
+class InputFromHatButton final : public Common::Input::InputDevice {
 public:
     explicit InputFromHatButton(PadIdentifier identifier_, u32 button_, u8 direction_, bool toggle_,
                                 bool inverted_, InputEngine* input_engine_)
@@ -98,7 +98,7 @@ public:
         input_engine->DeleteCallback(callback_key);
     }
 
-    Input::ButtonStatus GetStatus() const {
+    Common::Input::ButtonStatus GetStatus() const {
         return {
             .value = input_engine->GetHatButton(identifier, button, direction),
             .inverted = inverted,
@@ -107,8 +107,8 @@ public:
     }
 
     void ForceUpdate() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Button,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Button,
             .button_status = GetStatus(),
         };
 
@@ -117,8 +117,8 @@ public:
     }
 
     void OnChange() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Button,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Button,
             .button_status = GetStatus(),
         };
 
@@ -139,11 +139,12 @@ private:
     InputEngine* input_engine;
 };
 
-class InputFromStick final : public Input::InputDevice {
+class InputFromStick final : public Common::Input::InputDevice {
 public:
     explicit InputFromStick(PadIdentifier identifier_, u32 axis_x_, u32 axis_y_,
-                            Input::AnalogProperties properties_x_,
-                            Input::AnalogProperties properties_y_, InputEngine* input_engine_)
+                            Common::Input::AnalogProperties properties_x_,
+                            Common::Input::AnalogProperties properties_y_,
+                            InputEngine* input_engine_)
         : identifier(identifier_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_),
           properties_y(properties_y_), input_engine(input_engine_) {
         UpdateCallback engine_callback{[this]() { OnChange(); }};
@@ -170,8 +171,8 @@ public:
         input_engine->DeleteCallback(callback_key_y);
     }
 
-    Input::StickStatus GetStatus() const {
-        Input::StickStatus status;
+    Common::Input::StickStatus GetStatus() const {
+        Common::Input::StickStatus status;
         status.x = {
             .raw_value = input_engine->GetAxis(identifier, axis_x),
             .properties = properties_x,
@@ -184,8 +185,8 @@ public:
     }
 
     void ForceUpdate() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Stick,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Stick,
             .stick_status = GetStatus(),
         };
 
@@ -195,8 +196,8 @@ public:
     }
 
     void OnChange() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Stick,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Stick,
             .stick_status = GetStatus(),
         };
 
@@ -212,8 +213,8 @@ private:
     const PadIdentifier identifier;
     const u32 axis_x;
     const u32 axis_y;
-    const Input::AnalogProperties properties_x;
-    const Input::AnalogProperties properties_y;
+    const Common::Input::AnalogProperties properties_x;
+    const Common::Input::AnalogProperties properties_y;
     int callback_key_x;
     int callback_key_y;
     float last_axis_x_value;
@@ -221,12 +222,13 @@ private:
     InputEngine* input_engine;
 };
 
-class InputFromTouch final : public Input::InputDevice {
+class InputFromTouch final : public Common::Input::InputDevice {
 public:
     explicit InputFromTouch(PadIdentifier identifier_, u32 touch_id_, u32 button_, bool toggle_,
                             bool inverted_, u32 axis_x_, u32 axis_y_,
-                            Input::AnalogProperties properties_x_,
-                            Input::AnalogProperties properties_y_, InputEngine* input_engine_)
+                            Common::Input::AnalogProperties properties_x_,
+                            Common::Input::AnalogProperties properties_y_,
+                            InputEngine* input_engine_)
         : identifier(identifier_), touch_id(touch_id_), button(button_), toggle(toggle_),
           inverted(inverted_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_),
           properties_y(properties_y_), input_engine(input_engine_) {
@@ -263,8 +265,8 @@ public:
         input_engine->DeleteCallback(callback_key_y);
     }
 
-    Input::TouchStatus GetStatus() const {
-        Input::TouchStatus status;
+    Common::Input::TouchStatus GetStatus() const {
+        Common::Input::TouchStatus status;
         status.id = touch_id;
         status.pressed = {
             .value = input_engine->GetButton(identifier, button),
@@ -283,8 +285,8 @@ public:
     }
 
     void OnChange() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Touch,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Touch,
             .touch_status = GetStatus(),
         };
 
@@ -306,8 +308,8 @@ private:
     const bool inverted;
     const u32 axis_x;
     const u32 axis_y;
-    const Input::AnalogProperties properties_x;
-    const Input::AnalogProperties properties_y;
+    const Common::Input::AnalogProperties properties_x;
+    const Common::Input::AnalogProperties properties_y;
     int callback_key_button;
     int callback_key_x;
     int callback_key_y;
@@ -317,10 +319,10 @@ private:
     InputEngine* input_engine;
 };
 
-class InputFromTrigger final : public Input::InputDevice {
+class InputFromTrigger final : public Common::Input::InputDevice {
 public:
     explicit InputFromTrigger(PadIdentifier identifier_, u32 button_, bool toggle_, bool inverted_,
-                              u32 axis_, Input::AnalogProperties properties_,
+                              u32 axis_, Common::Input::AnalogProperties properties_,
                               InputEngine* input_engine_)
         : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_),
           axis(axis_), properties(properties_), input_engine(input_engine_) {
@@ -348,8 +350,8 @@ public:
         input_engine->DeleteCallback(axis_callback_key);
     }
 
-    Input::TriggerStatus GetStatus() const {
-        const Input::AnalogStatus analog_status{
+    Common::Input::TriggerStatus GetStatus() const {
+        const Common::Input::AnalogStatus analog_status{
             .raw_value = input_engine->GetAxis(identifier, axis),
             .properties = properties,
         };
@@ -360,8 +362,8 @@ public:
     }
 
     void OnChange() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Trigger,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Trigger,
             .trigger_status = GetStatus(),
         };
 
@@ -379,7 +381,7 @@ private:
     const bool toggle;
     const bool inverted;
     const u32 axis;
-    const Input::AnalogProperties properties;
+    const Common::Input::AnalogProperties properties;
     int callback_key_button;
     int axis_callback_key;
     bool last_button_value;
@@ -387,10 +389,11 @@ private:
     InputEngine* input_engine;
 };
 
-class InputFromAnalog final : public Input::InputDevice {
+class InputFromAnalog final : public Common::Input::InputDevice {
 public:
     explicit InputFromAnalog(PadIdentifier identifier_, u32 axis_,
-                             Input::AnalogProperties properties_, InputEngine* input_engine_)
+                             Common::Input::AnalogProperties properties_,
+                             InputEngine* input_engine_)
         : identifier(identifier_), axis(axis_), properties(properties_),
           input_engine(input_engine_) {
         UpdateCallback engine_callback{[this]() { OnChange(); }};
@@ -408,7 +411,7 @@ public:
         input_engine->DeleteCallback(callback_key);
     }
 
-    Input::AnalogStatus GetStatus() const {
+    Common::Input::AnalogStatus GetStatus() const {
         return {
             .raw_value = input_engine->GetAxis(identifier, axis),
             .properties = properties,
@@ -416,8 +419,8 @@ public:
     }
 
     void OnChange() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Analog,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Analog,
             .analog_status = GetStatus(),
         };
 
@@ -430,13 +433,13 @@ public:
 private:
     const PadIdentifier identifier;
     const u32 axis;
-    const Input::AnalogProperties properties;
+    const Common::Input::AnalogProperties properties;
     int callback_key;
     float last_axis_value;
     InputEngine* input_engine;
 };
 
-class InputFromBattery final : public Input::InputDevice {
+class InputFromBattery final : public Common::Input::InputDevice {
 public:
     explicit InputFromBattery(PadIdentifier identifier_, InputEngine* input_engine_)
         : identifier(identifier_), input_engine(input_engine_) {
@@ -447,7 +450,7 @@ public:
             .index = 0,
             .callback = engine_callback,
         };
-        last_battery_value = Input::BatteryStatus::Charging;
+        last_battery_value = Common::Input::BatteryStatus::Charging;
         callback_key = input_engine->SetCallback(input_identifier);
     }
 
@@ -455,13 +458,13 @@ public:
         input_engine->DeleteCallback(callback_key);
     }
 
-    Input::BatteryStatus GetStatus() const {
-        return static_cast<Input::BatteryLevel>(input_engine->GetBattery(identifier));
+    Common::Input::BatteryStatus GetStatus() const {
+        return static_cast<Common::Input::BatteryLevel>(input_engine->GetBattery(identifier));
     }
 
     void ForceUpdate() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Battery,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Battery,
             .battery_status = GetStatus(),
         };
 
@@ -470,8 +473,8 @@ public:
     }
 
     void OnChange() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Battery,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Battery,
             .battery_status = GetStatus(),
         };
 
@@ -484,11 +487,11 @@ public:
 private:
     const PadIdentifier identifier;
     int callback_key;
-    Input::BatteryStatus last_battery_value;
+    Common::Input::BatteryStatus last_battery_value;
     InputEngine* input_engine;
 };
 
-class InputFromMotion final : public Input::InputDevice {
+class InputFromMotion final : public Common::Input::InputDevice {
 public:
     explicit InputFromMotion(PadIdentifier identifier_, u32 motion_sensor_,
                              InputEngine* input_engine_)
@@ -507,10 +510,10 @@ public:
         input_engine->DeleteCallback(callback_key);
     }
 
-    Input::MotionStatus GetStatus() const {
+    Common::Input::MotionStatus GetStatus() const {
         const auto basic_motion = input_engine->GetMotion(identifier, motion_sensor);
-        Input::MotionStatus status{};
-        const Input::AnalogProperties properties = {
+        Common::Input::MotionStatus status{};
+        const Common::Input::AnalogProperties properties = {
             .deadzone = 0.001f,
             .range = 1.0f,
             .offset = 0.0f,
@@ -526,8 +529,8 @@ public:
     }
 
     void OnChange() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Motion,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Motion,
             .motion_status = GetStatus(),
         };
 
@@ -541,12 +544,13 @@ private:
     InputEngine* input_engine;
 };
 
-class InputFromAxisMotion final : public Input::InputDevice {
+class InputFromAxisMotion final : public Common::Input::InputDevice {
 public:
     explicit InputFromAxisMotion(PadIdentifier identifier_, u32 axis_x_, u32 axis_y_, u32 axis_z_,
-                                 Input::AnalogProperties properties_x_,
-                                 Input::AnalogProperties properties_y_,
-                                 Input::AnalogProperties properties_z_, InputEngine* input_engine_)
+                                 Common::Input::AnalogProperties properties_x_,
+                                 Common::Input::AnalogProperties properties_y_,
+                                 Common::Input::AnalogProperties properties_z_,
+                                 InputEngine* input_engine_)
         : identifier(identifier_), axis_x(axis_x_), axis_y(axis_y_), axis_z(axis_z_),
           properties_x(properties_x_), properties_y(properties_y_), properties_z(properties_z_),
           input_engine(input_engine_) {
@@ -583,8 +587,8 @@ public:
         input_engine->DeleteCallback(callback_key_z);
     }
 
-    Input::MotionStatus GetStatus() const {
-        Input::MotionStatus status{};
+    Common::Input::MotionStatus GetStatus() const {
+        Common::Input::MotionStatus status{};
         status.gyro.x = {
             .raw_value = input_engine->GetAxis(identifier, axis_x),
             .properties = properties_x,
@@ -601,8 +605,8 @@ public:
     }
 
     void ForceUpdate() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Motion,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Motion,
             .motion_status = GetStatus(),
         };
 
@@ -613,8 +617,8 @@ public:
     }
 
     void OnChange() {
-        const Input::CallbackStatus status{
-            .type = Input::InputType::Motion,
+        const Common::Input::CallbackStatus status{
+            .type = Common::Input::InputType::Motion,
             .motion_status = GetStatus(),
         };
 
@@ -633,9 +637,9 @@ private:
     const u32 axis_x;
     const u32 axis_y;
     const u32 axis_z;
-    const Input::AnalogProperties properties_x;
-    const Input::AnalogProperties properties_y;
-    const Input::AnalogProperties properties_z;
+    const Common::Input::AnalogProperties properties_x;
+    const Common::Input::AnalogProperties properties_y;
+    const Common::Input::AnalogProperties properties_z;
     int callback_key_x;
     int callback_key_y;
     int callback_key_z;
@@ -645,20 +649,21 @@ private:
     InputEngine* input_engine;
 };
 
-class OutputFromIdentifier final : public Input::OutputDevice {
+class OutputFromIdentifier final : public Common::Input::OutputDevice {
 public:
     explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_)
         : identifier(identifier_), input_engine(input_engine_) {}
 
-    virtual void SetLED(Input::LedStatus led_status) {
+    virtual void SetLED(Common::Input::LedStatus led_status) {
         input_engine->SetLeds(identifier, led_status);
     }
 
-    virtual Input::VibrationError SetVibration(Input::VibrationStatus vibration_status) {
+    virtual Common::Input::VibrationError SetVibration(
+        Common::Input::VibrationStatus vibration_status) {
         return input_engine->SetRumble(identifier, vibration_status);
     }
 
-    virtual Input::PollingError SetPollingMode(Input::PollingMode polling_mode) {
+    virtual Common::Input::PollingError SetPollingMode(Common::Input::PollingMode polling_mode) {
         return input_engine->SetPollingMode(identifier, polling_mode);
     }
 
@@ -667,7 +672,7 @@ private:
     InputEngine* input_engine;
 };
 
-std::unique_ptr<Input::InputDevice> InputFactory::CreateButtonDevice(
+std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateButtonDevice(
     const Common::ParamPackage& params) {
     const PadIdentifier identifier = {
         .guid = Common::UUID{params.Get("guid", "")},
@@ -690,7 +695,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateButtonDevice(
                                              input_engine.get());
 }
 
-std::unique_ptr<Input::InputDevice> InputFactory::CreateHatButtonDevice(
+std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateHatButtonDevice(
     const Common::ParamPackage& params) {
     const PadIdentifier identifier = {
         .guid = Common::UUID{params.Get("guid", "")},
@@ -709,7 +714,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateHatButtonDevice(
                                                 input_engine.get());
 }
 
-std::unique_ptr<Input::InputDevice> InputFactory::CreateStickDevice(
+std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice(
     const Common::ParamPackage& params) {
     const auto deadzone = std::clamp(params.Get("deadzone", 0.15f), 0.0f, 1.0f);
     const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f);
@@ -721,7 +726,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateStickDevice(
     };
 
     const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
-    const Input::AnalogProperties properties_x = {
+    const Common::Input::AnalogProperties properties_x = {
         .deadzone = deadzone,
         .range = range,
         .threshold = threshold,
@@ -730,7 +735,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateStickDevice(
     };
 
     const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
-    const Input::AnalogProperties properties_y = {
+    const Common::Input::AnalogProperties properties_y = {
         .deadzone = deadzone,
         .range = range,
         .threshold = threshold,
@@ -744,7 +749,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateStickDevice(
                                             input_engine.get());
 }
 
-std::unique_ptr<Input::InputDevice> InputFactory::CreateAnalogDevice(
+std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateAnalogDevice(
     const Common::ParamPackage& params) {
     const PadIdentifier identifier = {
         .guid = Common::UUID{params.Get("guid", "")},
@@ -753,7 +758,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateAnalogDevice(
     };
 
     const auto axis = static_cast<u32>(params.Get("axis", 0));
-    const Input::AnalogProperties properties = {
+    const Common::Input::AnalogProperties properties = {
         .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f),
         .range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f),
         .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f),
@@ -765,7 +770,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateAnalogDevice(
     return std::make_unique<InputFromAnalog>(identifier, axis, properties, input_engine.get());
 }
 
-std::unique_ptr<Input::InputDevice> InputFactory::CreateTriggerDevice(
+std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTriggerDevice(
     const Common::ParamPackage& params) {
     const PadIdentifier identifier = {
         .guid = Common::UUID{params.Get("guid", "")},
@@ -778,7 +783,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateTriggerDevice(
     const auto inverted = params.Get("inverted", false);
 
     const auto axis = static_cast<u32>(params.Get("axis", 0));
-    const Input::AnalogProperties properties = {
+    const Common::Input::AnalogProperties properties = {
         .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f),
         .range = std::clamp(params.Get("range", 1.0f), 0.25f, 2.50f),
         .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f),
@@ -792,7 +797,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateTriggerDevice(
                                               properties, input_engine.get());
 }
 
-std::unique_ptr<Input::InputDevice> InputFactory::CreateTouchDevice(
+std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice(
     const Common::ParamPackage& params) {
     const auto touch_id = params.Get("touch_id", 0);
     const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
@@ -809,7 +814,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateTouchDevice(
     const auto inverted = params.Get("inverted", false);
 
     const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
-    const Input::AnalogProperties properties_x = {
+    const Common::Input::AnalogProperties properties_x = {
         .deadzone = deadzone,
         .range = range,
         .threshold = threshold,
@@ -818,7 +823,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateTouchDevice(
     };
 
     const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
-    const Input::AnalogProperties properties_y = {
+    const Common::Input::AnalogProperties properties_y = {
         .deadzone = deadzone,
         .range = range,
         .threshold = threshold,
@@ -833,7 +838,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateTouchDevice(
                                             axis_y, properties_x, properties_y, input_engine.get());
 }
 
-std::unique_ptr<Input::InputDevice> InputFactory::CreateBatteryDevice(
+std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateBatteryDevice(
     const Common::ParamPackage& params) {
     const PadIdentifier identifier = {
         .guid = Common::UUID{params.Get("guid", "")},
@@ -845,7 +850,8 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateBatteryDevice(
     return std::make_unique<InputFromBattery>(identifier, input_engine.get());
 }
 
-std::unique_ptr<Input::InputDevice> InputFactory::CreateMotionDevice(Common::ParamPackage params) {
+std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateMotionDevice(
+    Common::ParamPackage params) {
     const PadIdentifier identifier = {
         .guid = Common::UUID{params.Get("guid", "")},
         .port = static_cast<std::size_t>(params.Get("port", 0)),
@@ -864,7 +870,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateMotionDevice(Common::Par
     const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f);
 
     const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
-    const Input::AnalogProperties properties_x = {
+    const Common::Input::AnalogProperties properties_x = {
         .deadzone = deadzone,
         .range = range,
         .threshold = threshold,
@@ -873,7 +879,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateMotionDevice(Common::Par
     };
 
     const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
-    const Input::AnalogProperties properties_y = {
+    const Common::Input::AnalogProperties properties_y = {
         .deadzone = deadzone,
         .range = range,
         .threshold = threshold,
@@ -882,7 +888,7 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateMotionDevice(Common::Par
     };
 
     const auto axis_z = static_cast<u32>(params.Get("axis_z", 1));
-    const Input::AnalogProperties properties_z = {
+    const Common::Input::AnalogProperties properties_z = {
         .deadzone = deadzone,
         .range = range,
         .threshold = threshold,
@@ -900,7 +906,8 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateMotionDevice(Common::Par
 InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_)
     : input_engine(std::move(input_engine_)) {}
 
-std::unique_ptr<Input::InputDevice> InputFactory::Create(const Common::ParamPackage& params) {
+std::unique_ptr<Common::Input::InputDevice> InputFactory::Create(
+    const Common::ParamPackage& params) {
     if (params.Has("battery")) {
         return CreateBatteryDevice(params);
     }
@@ -935,7 +942,8 @@ std::unique_ptr<Input::InputDevice> InputFactory::Create(const Common::ParamPack
 OutputFactory::OutputFactory(std::shared_ptr<InputEngine> input_engine_)
     : input_engine(std::move(input_engine_)) {}
 
-std::unique_ptr<Input::OutputDevice> OutputFactory::Create(const Common::ParamPackage& params) {
+std::unique_ptr<Common::Input::OutputDevice> OutputFactory::Create(
+    const Common::ParamPackage& params) {
     const PadIdentifier identifier = {
         .guid = Common::UUID{params.Get("guid", "")},
         .port = static_cast<std::size_t>(params.Get("port", 0)),
diff --git a/src/input_common/input_poller.h b/src/input_common/input_poller.h
index 1357e104be..573f09fded 100644
--- a/src/input_common/input_poller.h
+++ b/src/input_common/input_poller.h
@@ -17,7 +17,7 @@ class InputEngine;
  * An Input factory. It receives input events and forward them to all input devices it created.
  */
 
-class OutputFactory final : public Input::Factory<Input::OutputDevice> {
+class OutputFactory final : public Common::Input::Factory<Common::Input::OutputDevice> {
 public:
     explicit OutputFactory(std::shared_ptr<InputEngine> input_engine_);
 
@@ -29,13 +29,14 @@ public:
      * @param    - "pad": slot of the connected controller
      * @return an unique ouput device with the parameters specified
      */
-    std::unique_ptr<Input::OutputDevice> Create(const Common::ParamPackage& params) override;
+    std::unique_ptr<Common::Input::OutputDevice> Create(
+        const Common::ParamPackage& params) override;
 
 private:
     std::shared_ptr<InputEngine> input_engine;
 };
 
-class InputFactory final : public Input::Factory<Input::InputDevice> {
+class InputFactory final : public Common::Input::Factory<Common::Input::InputDevice> {
 public:
     explicit InputFactory(std::shared_ptr<InputEngine> input_engine_);
 
@@ -64,7 +65,7 @@ public:
      * @param    - "battery": Only used as a placeholder to set the input type
      * @return an unique input device with the parameters specified
      */
-    std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
+    std::unique_ptr<Common::Input::InputDevice> Create(const Common::ParamPackage& params) override;
 
 private:
     /**
@@ -79,7 +80,8 @@ private:
      * @param    - "pad": slot of the connected controller
      * @return an unique input device with the parameters specified
      */
-    std::unique_ptr<Input::InputDevice> CreateButtonDevice(const Common::ParamPackage& params);
+    std::unique_ptr<Common::Input::InputDevice> CreateButtonDevice(
+        const Common::ParamPackage& params);
 
     /**
      * Creates a hat button device from the parameters given.
@@ -93,7 +95,8 @@ private:
      * @param    - "pad": slot of the connected controller
      * @return an unique input device with the parameters specified
      */
-    std::unique_ptr<Input::InputDevice> CreateHatButtonDevice(const Common::ParamPackage& params);
+    std::unique_ptr<Common::Input::InputDevice> CreateHatButtonDevice(
+        const Common::ParamPackage& params);
 
     /**
      * Creates a stick device from the parameters given.
@@ -112,7 +115,8 @@ private:
      * @param    - "pad": slot of the connected controller
      * @return an unique input device with the parameters specified
      */
-    std::unique_ptr<Input::InputDevice> CreateStickDevice(const Common::ParamPackage& params);
+    std::unique_ptr<Common::Input::InputDevice> CreateStickDevice(
+        const Common::ParamPackage& params);
 
     /**
      * Creates an analog device from the parameters given.
@@ -128,7 +132,8 @@ private:
      * @param    - "pad": slot of the connected controller
      * @return an unique input device with the parameters specified
      */
-    std::unique_ptr<Input::InputDevice> CreateAnalogDevice(const Common::ParamPackage& params);
+    std::unique_ptr<Common::Input::InputDevice> CreateAnalogDevice(
+        const Common::ParamPackage& params);
 
     /**
      * Creates a trigger device from the parameters given.
@@ -148,7 +153,8 @@ private:
      * @param    - "pad": slot of the connected controller
      * @return an unique input device with the parameters specified
      */
-    std::unique_ptr<Input::InputDevice> CreateTriggerDevice(const Common::ParamPackage& params);
+    std::unique_ptr<Common::Input::InputDevice> CreateTriggerDevice(
+        const Common::ParamPackage& params);
 
     /**
      * Creates a touch device from the parameters given.
@@ -171,7 +177,8 @@ private:
      * @param    - "pad": slot of the connected controller
      * @return an unique input device with the parameters specified
      */
-    std::unique_ptr<Input::InputDevice> CreateTouchDevice(const Common::ParamPackage& params);
+    std::unique_ptr<Common::Input::InputDevice> CreateTouchDevice(
+        const Common::ParamPackage& params);
 
     /**
      * Creates a battery device from the parameters given.
@@ -181,7 +188,8 @@ private:
      * @param    - "pad": slot of the connected controller
      * @return an unique input device with the parameters specified
      */
-    std::unique_ptr<Input::InputDevice> CreateBatteryDevice(const Common::ParamPackage& params);
+    std::unique_ptr<Common::Input::InputDevice> CreateBatteryDevice(
+        const Common::ParamPackage& params);
 
     /**
      * Creates a motion device from the parameters given.
@@ -202,7 +210,7 @@ private:
      * @param    - "pad": slot of the connected controller
      * @return an unique input device with the parameters specified
      */
-    std::unique_ptr<Input::InputDevice> CreateMotionDevice(Common::ParamPackage params);
+    std::unique_ptr<Common::Input::InputDevice> CreateMotionDevice(Common::ParamPackage params);
 
     std::shared_ptr<InputEngine> input_engine;
 };
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 07d514ad73..df36a337c7 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -33,89 +33,97 @@ struct InputSubsystem::Impl {
         keyboard->SetMappingCallback(mapping_callback);
         keyboard_factory = std::make_shared<InputFactory>(keyboard);
         keyboard_output_factory = std::make_shared<OutputFactory>(keyboard);
-        Input::RegisterFactory<Input::InputDevice>(keyboard->GetEngineName(), keyboard_factory);
-        Input::RegisterFactory<Input::OutputDevice>(keyboard->GetEngineName(),
-                                                    keyboard_output_factory);
+        Common::Input::RegisterFactory<Common::Input::InputDevice>(keyboard->GetEngineName(),
+                                                                   keyboard_factory);
+        Common::Input::RegisterFactory<Common::Input::OutputDevice>(keyboard->GetEngineName(),
+                                                                    keyboard_output_factory);
 
         mouse = std::make_shared<Mouse>("mouse");
         mouse->SetMappingCallback(mapping_callback);
         mouse_factory = std::make_shared<InputFactory>(mouse);
         mouse_output_factory = std::make_shared<OutputFactory>(mouse);
-        Input::RegisterFactory<Input::InputDevice>(mouse->GetEngineName(), mouse_factory);
-        Input::RegisterFactory<Input::OutputDevice>(mouse->GetEngineName(), mouse_output_factory);
+        Common::Input::RegisterFactory<Common::Input::InputDevice>(mouse->GetEngineName(),
+                                                                   mouse_factory);
+        Common::Input::RegisterFactory<Common::Input::OutputDevice>(mouse->GetEngineName(),
+                                                                    mouse_output_factory);
 
         touch_screen = std::make_shared<TouchScreen>("touch");
         touch_screen_factory = std::make_shared<InputFactory>(touch_screen);
-        Input::RegisterFactory<Input::InputDevice>(touch_screen->GetEngineName(),
-                                                   touch_screen_factory);
+        Common::Input::RegisterFactory<Common::Input::InputDevice>(touch_screen->GetEngineName(),
+                                                                   touch_screen_factory);
 
         gcadapter = std::make_shared<GCAdapter>("gcpad");
         gcadapter->SetMappingCallback(mapping_callback);
         gcadapter_input_factory = std::make_shared<InputFactory>(gcadapter);
         gcadapter_output_factory = std::make_shared<OutputFactory>(gcadapter);
-        Input::RegisterFactory<Input::InputDevice>(gcadapter->GetEngineName(),
-                                                   gcadapter_input_factory);
-        Input::RegisterFactory<Input::OutputDevice>(gcadapter->GetEngineName(),
-                                                    gcadapter_output_factory);
+        Common::Input::RegisterFactory<Common::Input::InputDevice>(gcadapter->GetEngineName(),
+                                                                   gcadapter_input_factory);
+        Common::Input::RegisterFactory<Common::Input::OutputDevice>(gcadapter->GetEngineName(),
+                                                                    gcadapter_output_factory);
 
         udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
         udp_client->SetMappingCallback(mapping_callback);
         udp_client_factory = std::make_shared<InputFactory>(udp_client);
-        Input::RegisterFactory<Input::InputDevice>(udp_client->GetEngineName(), udp_client_factory);
+        Common::Input::RegisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName(),
+                                                                   udp_client_factory);
 
         tas_input = std::make_shared<TasInput::Tas>("tas");
         tas_input->SetMappingCallback(mapping_callback);
         tas_input_factory = std::make_shared<InputFactory>(tas_input);
         tas_output_factory = std::make_shared<OutputFactory>(tas_input);
-        Input::RegisterFactory<Input::InputDevice>(tas_input->GetEngineName(), tas_input_factory);
-        Input::RegisterFactory<Input::OutputDevice>(tas_input->GetEngineName(), tas_output_factory);
+        Common::Input::RegisterFactory<Common::Input::InputDevice>(tas_input->GetEngineName(),
+                                                                   tas_input_factory);
+        Common::Input::RegisterFactory<Common::Input::OutputDevice>(tas_input->GetEngineName(),
+                                                                    tas_output_factory);
 
 #ifdef HAVE_SDL2
         sdl = std::make_shared<SDLDriver>("sdl");
         sdl->SetMappingCallback(mapping_callback);
         sdl_input_factory = std::make_shared<InputFactory>(sdl);
         sdl_output_factory = std::make_shared<OutputFactory>(sdl);
-        Input::RegisterFactory<Input::InputDevice>(sdl->GetEngineName(), sdl_input_factory);
-        Input::RegisterFactory<Input::OutputDevice>(sdl->GetEngineName(), sdl_output_factory);
+        Common::Input::RegisterFactory<Common::Input::InputDevice>(sdl->GetEngineName(),
+                                                                   sdl_input_factory);
+        Common::Input::RegisterFactory<Common::Input::OutputDevice>(sdl->GetEngineName(),
+                                                                    sdl_output_factory);
 #endif
 
-        Input::RegisterFactory<Input::InputDevice>("touch_from_button",
-                                                   std::make_shared<TouchFromButton>());
-        Input::RegisterFactory<Input::InputDevice>("analog_from_button",
-                                                   std::make_shared<StickFromButton>());
+        Common::Input::RegisterFactory<Common::Input::InputDevice>(
+            "touch_from_button", std::make_shared<TouchFromButton>());
+        Common::Input::RegisterFactory<Common::Input::InputDevice>(
+            "analog_from_button", std::make_shared<StickFromButton>());
     }
 
     void Shutdown() {
-        Input::UnregisterFactory<Input::InputDevice>(keyboard->GetEngineName());
-        Input::UnregisterFactory<Input::OutputDevice>(keyboard->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::InputDevice>(keyboard->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(keyboard->GetEngineName());
         keyboard.reset();
 
-        Input::UnregisterFactory<Input::InputDevice>(mouse->GetEngineName());
-        Input::UnregisterFactory<Input::OutputDevice>(mouse->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::InputDevice>(mouse->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(mouse->GetEngineName());
         mouse.reset();
 
-        Input::UnregisterFactory<Input::InputDevice>(touch_screen->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::InputDevice>(touch_screen->GetEngineName());
         touch_screen.reset();
 
-        Input::UnregisterFactory<Input::InputDevice>(gcadapter->GetEngineName());
-        Input::UnregisterFactory<Input::OutputDevice>(gcadapter->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::InputDevice>(gcadapter->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(gcadapter->GetEngineName());
         gcadapter.reset();
 
-        Input::UnregisterFactory<Input::InputDevice>(udp_client->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName());
         udp_client.reset();
 
-        Input::UnregisterFactory<Input::InputDevice>(tas_input->GetEngineName());
-        Input::UnregisterFactory<Input::OutputDevice>(tas_input->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::InputDevice>(tas_input->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(tas_input->GetEngineName());
         tas_input.reset();
 
 #ifdef HAVE_SDL2
-        Input::UnregisterFactory<Input::InputDevice>(sdl->GetEngineName());
-        Input::UnregisterFactory<Input::OutputDevice>(sdl->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::InputDevice>(sdl->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(sdl->GetEngineName());
         sdl.reset();
 #endif
 
-        Input::UnregisterFactory<Input::InputDevice>("touch_from_button");
-        Input::UnregisterFactory<Input::InputDevice>("analog_from_button");
+        Common::Input::UnregisterFactory<Common::Input::InputDevice>("touch_from_button");
+        Common::Input::UnregisterFactory<Common::Input::InputDevice>("analog_from_button");
     }
 
     [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 67e56ed3ab..bb20e9339b 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -1945,8 +1945,8 @@ void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) {
 }
 
 void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center,
-                                           const Input::ButtonStatus& left_pressed,
-                                           const Input::ButtonStatus& right_pressed) {
+                                           const Common::Input::ButtonStatus& left_pressed,
+                                           const Common::Input::ButtonStatus& right_pressed) {
     std::array<QPointF, pro_left_trigger.size() / 2> qleft_trigger;
     std::array<QPointF, pro_left_trigger.size() / 2> qright_trigger;
     std::array<QPointF, pro_body_top.size()> qbody_top;
@@ -1984,8 +1984,8 @@ void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center,
 }
 
 void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center,
-                                          Input::TriggerStatus left_trigger,
-                                          Input::TriggerStatus right_trigger) {
+                                          Common::Input::TriggerStatus left_trigger,
+                                          Common::Input::TriggerStatus right_trigger) {
     std::array<QPointF, left_gc_trigger.size() / 2> qleft_trigger;
     std::array<QPointF, left_gc_trigger.size() / 2> qright_trigger;
 
@@ -2022,8 +2022,8 @@ void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center,
 }
 
 void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF center,
-                                                const Input::ButtonStatus& left_pressed,
-                                                const Input::ButtonStatus& right_pressed) {
+                                                const Common::Input::ButtonStatus& left_pressed,
+                                                const Common::Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
     std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
 
@@ -2048,8 +2048,8 @@ void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF cente
 }
 
 void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center,
-                                            const Input::ButtonStatus& left_pressed,
-                                            const Input::ButtonStatus& right_pressed) {
+                                            const Common::Input::ButtonStatus& left_pressed,
+                                            const Common::Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
     std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
     constexpr float size = 1.62f;
@@ -2076,9 +2076,9 @@ void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center,
     DrawPolygon(p, qright_trigger);
 }
 
-void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF center,
-                                                   const Input::ButtonStatus& left_pressed,
-                                                   const Input::ButtonStatus& right_pressed) {
+void PlayerControlPreview::DrawDualTriggersTopView(
+    QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed,
+    const Common::Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger;
     std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger;
     constexpr float size = 0.9f;
@@ -2113,9 +2113,9 @@ void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF ce
     DrawSymbol(p, center + QPointF(177, -84), Symbol::R, 1.0f);
 }
 
-void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF center,
-                                                    const Input::ButtonStatus& left_pressed,
-                                                    const Input::ButtonStatus& right_pressed) {
+void PlayerControlPreview::DrawDualZTriggersTopView(
+    QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed,
+    const Common::Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger;
     std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger;
     constexpr float size = 0.9f;
@@ -2149,7 +2149,7 @@ void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF c
 }
 
 void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center,
-                                            const Input::ButtonStatus& left_pressed) {
+                                            const Common::Input::ButtonStatus& left_pressed) {
     std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
     constexpr float size = 1.78f;
     constexpr float offset = 311.5f;
@@ -2166,7 +2166,7 @@ void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center,
 }
 
 void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center,
-                                             const Input::ButtonStatus& left_pressed) {
+                                             const Common::Input::ButtonStatus& left_pressed) {
     std::array<QPointF, left_joycon_sideview_zl.size() / 2> qleft_trigger;
     constexpr float size = 1.1115f;
     constexpr float offset2 = 335;
@@ -2184,8 +2184,8 @@ void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center,
               225 * 16, 44 * 16);
 }
 
-void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF center,
-                                                   const Input::ButtonStatus& left_pressed) {
+void PlayerControlPreview::DrawLeftTriggersTopView(
+    QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed) {
     std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger;
 
     for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
@@ -2203,8 +2203,8 @@ void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF ce
     DrawSymbol(p, center + QPointF(-143, -36), Symbol::L, 1.0f);
 }
 
-void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF center,
-                                                    const Input::ButtonStatus& left_pressed) {
+void PlayerControlPreview::DrawLeftZTriggersTopView(
+    QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed) {
     std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger;
 
     for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
@@ -2223,7 +2223,7 @@ void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF c
 }
 
 void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center,
-                                             const Input::ButtonStatus& right_pressed) {
+                                             const Common::Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
     constexpr float size = 1.78f;
     constexpr float offset = 311.5f;
@@ -2240,7 +2240,7 @@ void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center,
 }
 
 void PlayerControlPreview::DrawRightZTriggers(QPainter& p, const QPointF center,
-                                              const Input::ButtonStatus& right_pressed) {
+                                              const Common::Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joycon_sideview_zl.size() / 2> qright_trigger;
     constexpr float size = 1.1115f;
     constexpr float offset2 = 335;
@@ -2259,8 +2259,8 @@ void PlayerControlPreview::DrawRightZTriggers(QPainter& p, const QPointF center,
               271 * 16, 44 * 16);
 }
 
-void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF center,
-                                                    const Input::ButtonStatus& right_pressed) {
+void PlayerControlPreview::DrawRightTriggersTopView(
+    QPainter& p, const QPointF center, const Common::Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger;
 
     for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
@@ -2278,8 +2278,8 @@ void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF c
     DrawSymbol(p, center + QPointF(137, -36), Symbol::R, 1.0f);
 }
 
-void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF center,
-                                                     const Input::ButtonStatus& right_pressed) {
+void PlayerControlPreview::DrawRightZTriggersTopView(
+    QPainter& p, const QPointF center, const Common::Input::ButtonStatus& right_pressed) {
     std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger;
 
     for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
@@ -2298,7 +2298,7 @@ void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF
 }
 
 void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float size,
-                                        const Input::ButtonStatus& pressed) {
+                                        const Common::Input::ButtonStatus& pressed) {
     const float radius1 = 13.0f * size;
     const float radius2 = 9.0f * size;
 
@@ -2317,7 +2317,8 @@ void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float
 }
 
 void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF center, float angle,
-                                                float size, const Input::ButtonStatus& pressed) {
+                                                float size,
+                                                const Common::Input::ButtonStatus& pressed) {
     QVector<QPointF> joystick;
     joystick.reserve(static_cast<int>(left_joystick_sideview.size() / 2));
 
@@ -2342,7 +2343,7 @@ void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF cente
 
 void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, const QPointF offset,
                                            float offset_scalar,
-                                           const Input::ButtonStatus& pressed) {
+                                           const Common::Input::ButtonStatus& pressed) {
     const float radius1 = 24.0f;
     const float radius2 = 17.0f;
 
@@ -2377,7 +2378,7 @@ void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, co
 }
 
 void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center,
-                                          const Input::ButtonStatus& pressed) {
+                                          const Common::Input::ButtonStatus& pressed) {
     // Outer circle
     p.setPen(colors.outline);
     p.setBrush(pressed.value ? colors.highlight : colors.button);
@@ -2414,8 +2415,8 @@ void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPo
     }
 }
 
-void PlayerControlPreview::DrawJoystickProperties(QPainter& p, const QPointF center,
-                                                  const Input::AnalogProperties& properties) {
+void PlayerControlPreview::DrawJoystickProperties(
+    QPainter& p, const QPointF center, const Common::Input::AnalogProperties& properties) {
     constexpr float size = 45.0f;
     const float range = size * properties.range;
     const float deadzone = size * properties.deadzone;
@@ -2435,7 +2436,7 @@ void PlayerControlPreview::DrawJoystickProperties(QPainter& p, const QPointF cen
 }
 
 void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center,
-                                           const Input::StickStatus& stick, bool raw) {
+                                           const Common::Input::StickStatus& stick, bool raw) {
     constexpr float size = 45.0f;
     const float range = size * stick.x.properties.range;
 
@@ -2450,7 +2451,7 @@ void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center,
 }
 
 void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center,
-                                           const Input::ButtonStatus& pressed, float width,
+                                           const Common::Input::ButtonStatus& pressed, float width,
                                            float height, Direction direction, float radius) {
     p.setBrush(button_color);
     if (pressed.value) {
@@ -2476,13 +2477,15 @@ void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center,
     p.drawRoundedRect(rect, radius, radius);
 }
 void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center,
-                                           const Input::ButtonStatus& pressed, int button_size) {
+                                           const Common::Input::ButtonStatus& pressed,
+                                           int button_size) {
     p.setPen(colors.outline);
     p.setBrush(pressed.value ? colors.highlight : colors.button);
     DrawRectangle(p, center, button_size, button_size / 3.0f);
 }
 void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center,
-                                          const Input::ButtonStatus& pressed, int button_size) {
+                                          const Common::Input::ButtonStatus& pressed,
+                                          int button_size) {
     // Draw outer line
     p.setPen(colors.outline);
     p.setBrush(pressed.value ? colors.highlight : colors.button);
@@ -2499,7 +2502,7 @@ void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center,
 }
 
 void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center,
-                                         const Input::ButtonStatus& pressed) {
+                                         const Common::Input::ButtonStatus& pressed) {
     std::array<QPointF, gc_button_x.size() / 2> button_x;
 
     for (std::size_t point = 0; point < gc_button_x.size() / 2; ++point) {
@@ -2512,7 +2515,7 @@ void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center,
 }
 
 void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center,
-                                         const Input::ButtonStatus& pressed) {
+                                         const Common::Input::ButtonStatus& pressed) {
     std::array<QPointF, gc_button_y.size() / 2> button_x;
 
     for (std::size_t point = 0; point < gc_button_y.size() / 2; ++point) {
@@ -2525,7 +2528,7 @@ void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center,
 }
 
 void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center,
-                                         const Input::ButtonStatus& pressed) {
+                                         const Common::Input::ButtonStatus& pressed) {
     std::array<QPointF, gc_button_z.size() / 2> button_x;
 
     for (std::size_t point = 0; point < gc_button_z.size() / 2; ++point) {
@@ -2539,7 +2542,8 @@ void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center,
 }
 
 void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center,
-                                            const Input::ButtonStatus& pressed, float button_size) {
+                                            const Common::Input::ButtonStatus& pressed,
+                                            float button_size) {
     p.setBrush(button_color);
     if (pressed.value) {
         p.setBrush(colors.highlight);
@@ -2571,7 +2575,7 @@ void PlayerControlPreview::DrawArrowButtonOutline(QPainter& p, const QPointF cen
 
 void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
                                            const Direction direction,
-                                           const Input::ButtonStatus& pressed, float size) {
+                                           const Common::Input::ButtonStatus& pressed, float size) {
     std::array<QPointF, up_arrow_button.size() / 2> arrow_button;
     QPoint offset;
 
@@ -2628,7 +2632,7 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
 
 void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center,
                                              const Direction direction,
-                                             const Input::ButtonStatus& pressed) {
+                                             const Common::Input::ButtonStatus& pressed) {
     std::array<QPointF, trigger_button.size() / 2> qtrigger_button;
 
     for (std::size_t point = 0; point < trigger_button.size() / 2; ++point) {
@@ -2655,8 +2659,9 @@ void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center,
     DrawPolygon(p, qtrigger_button);
 }
 
-void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::BatteryLevel battery) {
-    if (battery == Input::BatteryLevel::None) {
+void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center,
+                                       Common::Input::BatteryLevel battery) {
+    if (battery == Common::Input::BatteryLevel::None) {
         return;
     }
     p.setPen(colors.outline);
@@ -2665,29 +2670,29 @@ void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::Batte
     p.drawRect(center.x() + 56, center.y() + 6, 3, 8);
     p.setBrush(colors.deadzone);
     switch (battery) {
-    case Input::BatteryLevel::Charging:
+    case Common::Input::BatteryLevel::Charging:
         p.setBrush(colors.indicator2);
         p.drawText(center + QPoint(2, 14), tr("Charging"));
         break;
-    case Input::BatteryLevel::Full:
+    case Common::Input::BatteryLevel::Full:
         p.drawRect(center.x() + 42, center.y(), 14, 20);
         p.drawRect(center.x() + 28, center.y(), 14, 20);
         p.drawRect(center.x() + 14, center.y(), 14, 20);
         p.drawRect(center.x(), center.y(), 14, 20);
         break;
-    case Input::BatteryLevel::Medium:
+    case Common::Input::BatteryLevel::Medium:
         p.drawRect(center.x() + 28, center.y(), 14, 20);
         p.drawRect(center.x() + 14, center.y(), 14, 20);
         p.drawRect(center.x(), center.y(), 14, 20);
         break;
-    case Input::BatteryLevel::Low:
+    case Common::Input::BatteryLevel::Low:
         p.drawRect(center.x() + 14, center.y(), 14, 20);
         p.drawRect(center.x(), center.y(), 14, 20);
         break;
-    case Input::BatteryLevel::Critical:
+    case Common::Input::BatteryLevel::Critical:
         p.drawRect(center.x(), center.y(), 14, 20);
         break;
-    case Input::BatteryLevel::Empty:
+    case Common::Input::BatteryLevel::Empty:
         p.drawRect(center.x(), center.y(), 5, 20);
         break;
     default:
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index 333c3fc56b..430e4f4f4c 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -115,66 +115,75 @@ private:
     void DrawGCBody(QPainter& p, QPointF center);
 
     // Draw triggers functions
-    void DrawProTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed,
-                         const Input::ButtonStatus& right_pressed);
-    void DrawGCTriggers(QPainter& p, QPointF center, Input::TriggerStatus left_trigger,
-                        Input::TriggerStatus right_trigger);
-    void DrawHandheldTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed,
-                              const Input::ButtonStatus& right_pressed);
-    void DrawDualTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed,
-                          const Input::ButtonStatus& right_pressed);
+    void DrawProTriggers(QPainter& p, QPointF center,
+                         const Common::Input::ButtonStatus& left_pressed,
+                         const Common::Input::ButtonStatus& right_pressed);
+    void DrawGCTriggers(QPainter& p, QPointF center, Common::Input::TriggerStatus left_trigger,
+                        Common::Input::TriggerStatus right_trigger);
+    void DrawHandheldTriggers(QPainter& p, QPointF center,
+                              const Common::Input::ButtonStatus& left_pressed,
+                              const Common::Input::ButtonStatus& right_pressed);
+    void DrawDualTriggers(QPainter& p, QPointF center,
+                          const Common::Input::ButtonStatus& left_pressed,
+                          const Common::Input::ButtonStatus& right_pressed);
     void DrawDualTriggersTopView(QPainter& p, QPointF center,
-                                 const Input::ButtonStatus& left_pressed,
-                                 const Input::ButtonStatus& right_pressed);
+                                 const Common::Input::ButtonStatus& left_pressed,
+                                 const Common::Input::ButtonStatus& right_pressed);
     void DrawDualZTriggersTopView(QPainter& p, QPointF center,
-                                  const Input::ButtonStatus& left_pressed,
-                                  const Input::ButtonStatus& right_pressed);
-    void DrawLeftTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed);
-    void DrawLeftZTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed);
+                                  const Common::Input::ButtonStatus& left_pressed,
+                                  const Common::Input::ButtonStatus& right_pressed);
+    void DrawLeftTriggers(QPainter& p, QPointF center,
+                          const Common::Input::ButtonStatus& left_pressed);
+    void DrawLeftZTriggers(QPainter& p, QPointF center,
+                           const Common::Input::ButtonStatus& left_pressed);
     void DrawLeftTriggersTopView(QPainter& p, QPointF center,
-                                 const Input::ButtonStatus& left_pressed);
+                                 const Common::Input::ButtonStatus& left_pressed);
     void DrawLeftZTriggersTopView(QPainter& p, QPointF center,
-                                  const Input::ButtonStatus& left_pressed);
-    void DrawRightTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& right_pressed);
-    void DrawRightZTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& right_pressed);
+                                  const Common::Input::ButtonStatus& left_pressed);
+    void DrawRightTriggers(QPainter& p, QPointF center,
+                           const Common::Input::ButtonStatus& right_pressed);
+    void DrawRightZTriggers(QPainter& p, QPointF center,
+                            const Common::Input::ButtonStatus& right_pressed);
     void DrawRightTriggersTopView(QPainter& p, QPointF center,
-                                  const Input::ButtonStatus& right_pressed);
+                                  const Common::Input::ButtonStatus& right_pressed);
     void DrawRightZTriggersTopView(QPainter& p, QPointF center,
-                                   const Input::ButtonStatus& right_pressed);
+                                   const Common::Input::ButtonStatus& right_pressed);
 
     // Draw joystick functions
-    void DrawJoystick(QPainter& p, QPointF center, float size, const Input::ButtonStatus& pressed);
+    void DrawJoystick(QPainter& p, QPointF center, float size,
+                      const Common::Input::ButtonStatus& pressed);
     void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size,
-                              const Input::ButtonStatus& pressed);
+                              const Common::Input::ButtonStatus& pressed);
     void DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right);
     void DrawJoystickProperties(QPainter& p, QPointF center,
-                                const Input::AnalogProperties& properties);
-    void DrawJoystickDot(QPainter& p, QPointF center, const Input::StickStatus& stick, bool raw);
+                                const Common::Input::AnalogProperties& properties);
+    void DrawJoystickDot(QPainter& p, QPointF center, const Common::Input::StickStatus& stick,
+                         bool raw);
     void DrawProJoystick(QPainter& p, QPointF center, QPointF offset, float scalar,
-                         const Input::ButtonStatus& pressed);
-    void DrawGCJoystick(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
+                         const Common::Input::ButtonStatus& pressed);
+    void DrawGCJoystick(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed);
 
     // Draw button functions
-    void DrawCircleButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
+    void DrawCircleButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed,
                           float button_size);
-    void DrawRoundButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
+    void DrawRoundButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed,
                          float width, float height, Direction direction = Direction::None,
                          float radius = 2);
-    void DrawMinusButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
+    void DrawMinusButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed,
                          int button_size);
-    void DrawPlusButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
+    void DrawPlusButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed,
                         int button_size);
-    void DrawGCButtonX(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
-    void DrawGCButtonY(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
-    void DrawGCButtonZ(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
+    void DrawGCButtonX(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed);
+    void DrawGCButtonY(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed);
+    void DrawGCButtonZ(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed);
     void DrawArrowButtonOutline(QPainter& p, const QPointF center, float size = 1.0f);
     void DrawArrowButton(QPainter& p, QPointF center, Direction direction,
-                         const Input::ButtonStatus& pressed, float size = 1.0f);
+                         const Common::Input::ButtonStatus& pressed, float size = 1.0f);
     void DrawTriggerButton(QPainter& p, QPointF center, Direction direction,
-                           const Input::ButtonStatus& pressed);
+                           const Common::Input::ButtonStatus& pressed);
 
     // Draw battery functions
-    void DrawBattery(QPainter& p, QPointF center, Input::BatteryLevel battery);
+    void DrawBattery(QPainter& p, QPointF center, Common::Input::BatteryLevel battery);
 
     // Draw icon functions
     void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size);

From 730f07830247cfcdc551c253d30c6717fc16316c Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 31 Oct 2021 10:41:44 -0500
Subject: [PATCH 62/88] settings: Fix Debug controller type options

---
 src/common/input.h                            |  4 +-
 src/core/hid/emulated_console.cpp             |  3 +-
 src/core/hid/emulated_controller.cpp          | 11 ++-
 src/core/hid/input_converter.cpp              |  4 +-
 src/input_common/drivers/tas_input.h          |  1 -
 .../helpers/touch_from_buttons.cpp            |  4 +-
 src/input_common/input_engine.cpp             |  2 +-
 src/input_common/input_engine.h               |  5 +-
 src/input_common/input_poller.cpp             | 89 ++++++++++---------
 src/yuzu/applets/qt_controller.cpp            |  2 -
 .../configuration/configure_input_player.cpp  |  2 -
 .../configuration/configure_input_player.ui   | 25 ------
 .../configure_input_player_widget.cpp         | 20 +++--
 13 files changed, 77 insertions(+), 95 deletions(-)

diff --git a/src/common/input.h b/src/common/input.h
index 6d3227f5e2..16b1e6f1ba 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -100,7 +100,7 @@ struct StickStatus {
 
 struct TriggerStatus {
     AnalogStatus analog{};
-    bool pressed{};
+    ButtonStatus pressed{};
 };
 
 struct MotionSensor {
@@ -119,7 +119,7 @@ struct TouchStatus {
     ButtonStatus pressed{};
     AnalogStatus x{};
     AnalogStatus y{};
-    u32 id{};
+    int id{};
 };
 
 struct BodyColorStatus {
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index c259de0f17..0129099544 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -166,9 +166,10 @@ void EmulatedConsole::SetTouch(Common::Input::CallbackStatus callback,
         return;
     }
 
+    // TODO(german77): Remap touch id in sequential order
     console.touch_state[index] = {
         .position = {console.touch_values[index].x.value, console.touch_values[index].y.value},
-        .id = console.touch_values[index].id,
+        .id = static_cast<u32>(console.touch_values[index].id),
         .pressed = console.touch_values[index].pressed.value,
     };
 
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 49893cdbda..9a18642791 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -77,7 +77,12 @@ void EmulatedController::ReloadFromSettings() {
 
     controller.colors_state.fullkey = controller.colors_state.left;
 
-    SetNpadType(MapSettingsTypeToNPad(player.controller_type));
+    // Other or debug controller should always be a pro controller
+    if (npad_id_type != NpadIdType::Other) {
+        SetNpadType(MapSettingsTypeToNPad(player.controller_type));
+    } else {
+        SetNpadType(NpadType::ProController);
+    }
 
     if (player.connected) {
         Connect();
@@ -606,12 +611,12 @@ void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std:
     switch (index) {
     case Settings::NativeTrigger::LTrigger:
         controller.gc_trigger_state.left = static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX);
-        controller.npad_button_state.zl.Assign(trigger.pressed);
+        controller.npad_button_state.zl.Assign(trigger.pressed.value);
         break;
     case Settings::NativeTrigger::RTrigger:
         controller.gc_trigger_state.right =
             static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX);
-        controller.npad_button_state.zr.Assign(trigger.pressed);
+        controller.npad_button_state.zr.Assign(trigger.pressed.value);
         break;
     }
 
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index 14204917e1..5b123bd3ab 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -53,7 +53,7 @@ Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatu
     switch (callback.type) {
     case Common::Input::InputType::Analog:
     case Common::Input::InputType::Trigger:
-        status.value = TransformToTrigger(callback).pressed;
+        status.value = TransformToTrigger(callback).pressed.value;
         break;
     case Common::Input::InputType::Button:
         status = callback.button_status;
@@ -222,7 +222,7 @@ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackSta
 
     // Set button status
     if (calculate_button_value) {
-        status.pressed = value > properties.threshold;
+        status.pressed.value = value > properties.threshold;
     }
 
     // Adjust if value is inverted
diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h
index 5f5c3267c3..82dc9d6160 100644
--- a/src/input_common/drivers/tas_input.h
+++ b/src/input_common/drivers/tas_input.h
@@ -188,7 +188,6 @@ private:
     std::string WriteCommandAxis(TasAnalog data) const;
 
     size_t script_length{0};
-    bool is_old_input_saved{false};
     bool is_recording{false};
     bool is_running{false};
     bool needs_reset{false};
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp
index fee41cae34..0243437158 100644
--- a/src/input_common/helpers/touch_from_buttons.cpp
+++ b/src/input_common/helpers/touch_from_buttons.cpp
@@ -12,7 +12,7 @@ namespace InputCommon {
 class TouchFromButtonDevice final : public Common::Input::InputDevice {
 public:
     using Button = std::unique_ptr<Common::Input::InputDevice>;
-    TouchFromButtonDevice(Button button_, u32 touch_id_, float x_, float y_)
+    TouchFromButtonDevice(Button button_, int touch_id_, float x_, float y_)
         : button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) {
         Common::Input::InputCallback button_up_callback{
             [this](Common::Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }};
@@ -52,7 +52,7 @@ public:
 
 private:
     Button button;
-    const u32 touch_id;
+    const int touch_id;
     const float x;
     const float y;
     const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp
index 9cfe0f2323..965a2bdf16 100644
--- a/src/input_common/input_engine.cpp
+++ b/src/input_common/input_engine.cpp
@@ -315,7 +315,7 @@ void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int mot
 
 bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier,
                                          const PadIdentifier& identifier, EngineInputType type,
-                                         std::size_t index) const {
+                                         int index) const {
     if (input_identifier.type != type) {
         return false;
     }
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h
index ed79d3d934..5430c0cf8f 100644
--- a/src/input_common/input_engine.h
+++ b/src/input_common/input_engine.h
@@ -96,7 +96,7 @@ struct MappingCallback {
 struct InputIdentifier {
     PadIdentifier identifier;
     EngineInputType type;
-    std::size_t index;
+    int index;
     UpdateCallback callback;
 };
 
@@ -216,12 +216,11 @@ private:
 
     bool IsInputIdentifierEqual(const InputIdentifier& input_identifier,
                                 const PadIdentifier& identifier, EngineInputType type,
-                                std::size_t index) const;
+                                int index) const;
 
     mutable std::mutex mutex;
     mutable std::mutex mutex_callback;
     bool configuring{false};
-    bool is_callback_enabled{true};
     const std::string input_engine;
     int last_callback_key = 0;
     std::unordered_map<PadIdentifier, ControllerData> controller_list;
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 2b3b779380..01c4358023 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -18,7 +18,7 @@ public:
 
 class InputFromButton final : public Common::Input::InputDevice {
 public:
-    explicit InputFromButton(PadIdentifier identifier_, u32 button_, bool toggle_, bool inverted_,
+    explicit InputFromButton(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_,
                              InputEngine* input_engine_)
         : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_),
           input_engine(input_engine_) {
@@ -69,7 +69,7 @@ public:
 
 private:
     const PadIdentifier identifier;
-    const u32 button;
+    const int button;
     const bool toggle;
     const bool inverted;
     int callback_key;
@@ -79,7 +79,7 @@ private:
 
 class InputFromHatButton final : public Common::Input::InputDevice {
 public:
-    explicit InputFromHatButton(PadIdentifier identifier_, u32 button_, u8 direction_, bool toggle_,
+    explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool toggle_,
                                 bool inverted_, InputEngine* input_engine_)
         : identifier(identifier_), button(button_), direction(direction_), toggle(toggle_),
           inverted(inverted_), input_engine(input_engine_) {
@@ -130,7 +130,7 @@ public:
 
 private:
     const PadIdentifier identifier;
-    const u32 button;
+    const int button;
     const u8 direction;
     const bool toggle;
     const bool inverted;
@@ -141,7 +141,7 @@ private:
 
 class InputFromStick final : public Common::Input::InputDevice {
 public:
-    explicit InputFromStick(PadIdentifier identifier_, u32 axis_x_, u32 axis_y_,
+    explicit InputFromStick(PadIdentifier identifier_, int axis_x_, int axis_y_,
                             Common::Input::AnalogProperties properties_x_,
                             Common::Input::AnalogProperties properties_y_,
                             InputEngine* input_engine_)
@@ -211,8 +211,8 @@ public:
 
 private:
     const PadIdentifier identifier;
-    const u32 axis_x;
-    const u32 axis_y;
+    const int axis_x;
+    const int axis_y;
     const Common::Input::AnalogProperties properties_x;
     const Common::Input::AnalogProperties properties_y;
     int callback_key_x;
@@ -224,8 +224,8 @@ private:
 
 class InputFromTouch final : public Common::Input::InputDevice {
 public:
-    explicit InputFromTouch(PadIdentifier identifier_, u32 touch_id_, u32 button_, bool toggle_,
-                            bool inverted_, u32 axis_x_, u32 axis_y_,
+    explicit InputFromTouch(PadIdentifier identifier_, int touch_id_, int button_, bool toggle_,
+                            bool inverted_, int axis_x_, int axis_y_,
                             Common::Input::AnalogProperties properties_x_,
                             Common::Input::AnalogProperties properties_y_,
                             InputEngine* input_engine_)
@@ -302,12 +302,12 @@ public:
 
 private:
     const PadIdentifier identifier;
-    const u32 touch_id;
-    const u32 button;
+    const int touch_id;
+    const int button;
     const bool toggle;
     const bool inverted;
-    const u32 axis_x;
-    const u32 axis_y;
+    const int axis_x;
+    const int axis_y;
     const Common::Input::AnalogProperties properties_x;
     const Common::Input::AnalogProperties properties_y;
     int callback_key_button;
@@ -321,8 +321,8 @@ private:
 
 class InputFromTrigger final : public Common::Input::InputDevice {
 public:
-    explicit InputFromTrigger(PadIdentifier identifier_, u32 button_, bool toggle_, bool inverted_,
-                              u32 axis_, Common::Input::AnalogProperties properties_,
+    explicit InputFromTrigger(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_,
+                              int axis_, Common::Input::AnalogProperties properties_,
                               InputEngine* input_engine_)
         : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_),
           axis(axis_), properties(properties_), input_engine(input_engine_) {
@@ -355,9 +355,14 @@ public:
             .raw_value = input_engine->GetAxis(identifier, axis),
             .properties = properties,
         };
+        const Common::Input::ButtonStatus button_status{
+            .value = input_engine->GetButton(identifier, button),
+            .inverted = inverted,
+            .toggle = toggle,
+        };
         return {
             .analog = analog_status,
-            .pressed = input_engine->GetButton(identifier, button),
+            .pressed = button_status,
         };
     }
 
@@ -368,19 +373,19 @@ public:
         };
 
         if (status.trigger_status.analog.raw_value != last_axis_value ||
-            status.trigger_status.pressed != last_button_value) {
+            status.trigger_status.pressed.value != last_button_value) {
             last_axis_value = status.trigger_status.analog.raw_value;
-            last_button_value = status.trigger_status.pressed;
+            last_button_value = status.trigger_status.pressed.value;
             TriggerOnChange(status);
         }
     }
 
 private:
     const PadIdentifier identifier;
-    const u32 button;
+    const int button;
     const bool toggle;
     const bool inverted;
-    const u32 axis;
+    const int axis;
     const Common::Input::AnalogProperties properties;
     int callback_key_button;
     int axis_callback_key;
@@ -391,7 +396,7 @@ private:
 
 class InputFromAnalog final : public Common::Input::InputDevice {
 public:
-    explicit InputFromAnalog(PadIdentifier identifier_, u32 axis_,
+    explicit InputFromAnalog(PadIdentifier identifier_, int axis_,
                              Common::Input::AnalogProperties properties_,
                              InputEngine* input_engine_)
         : identifier(identifier_), axis(axis_), properties(properties_),
@@ -432,7 +437,7 @@ public:
 
 private:
     const PadIdentifier identifier;
-    const u32 axis;
+    const int axis;
     const Common::Input::AnalogProperties properties;
     int callback_key;
     float last_axis_value;
@@ -493,7 +498,7 @@ private:
 
 class InputFromMotion final : public Common::Input::InputDevice {
 public:
-    explicit InputFromMotion(PadIdentifier identifier_, u32 motion_sensor_,
+    explicit InputFromMotion(PadIdentifier identifier_, int motion_sensor_,
                              InputEngine* input_engine_)
         : identifier(identifier_), motion_sensor(motion_sensor_), input_engine(input_engine_) {
         UpdateCallback engine_callback{[this]() { OnChange(); }};
@@ -539,14 +544,14 @@ public:
 
 private:
     const PadIdentifier identifier;
-    const u32 motion_sensor;
+    const int motion_sensor;
     int callback_key;
     InputEngine* input_engine;
 };
 
 class InputFromAxisMotion final : public Common::Input::InputDevice {
 public:
-    explicit InputFromAxisMotion(PadIdentifier identifier_, u32 axis_x_, u32 axis_y_, u32 axis_z_,
+    explicit InputFromAxisMotion(PadIdentifier identifier_, int axis_x_, int axis_y_, int axis_z_,
                                  Common::Input::AnalogProperties properties_x_,
                                  Common::Input::AnalogProperties properties_y_,
                                  Common::Input::AnalogProperties properties_z_,
@@ -634,9 +639,9 @@ public:
 
 private:
     const PadIdentifier identifier;
-    const u32 axis_x;
-    const u32 axis_y;
-    const u32 axis_z;
+    const int axis_x;
+    const int axis_y;
+    const int axis_z;
     const Common::Input::AnalogProperties properties_x;
     const Common::Input::AnalogProperties properties_y;
     const Common::Input::AnalogProperties properties_z;
@@ -680,8 +685,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateButtonDevice(
         .pad = static_cast<std::size_t>(params.Get("pad", 0)),
     };
 
-    const auto button_id = static_cast<u32>(params.Get("button", 0));
-    const auto keyboard_key = static_cast<u32>(params.Get("code", 0));
+    const auto button_id = params.Get("button", 0);
+    const auto keyboard_key = params.Get("code", 0);
     const auto toggle = params.Get("toggle", false);
     const auto inverted = params.Get("inverted", false);
     input_engine->PreSetController(identifier);
@@ -703,7 +708,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateHatButtonDevice(
         .pad = static_cast<std::size_t>(params.Get("pad", 0)),
     };
 
-    const auto button_id = static_cast<u32>(params.Get("hat", 0));
+    const auto button_id = params.Get("hat", 0);
     const auto direction = input_engine->GetHatButtonId(params.Get("direction", ""));
     const auto toggle = params.Get("toggle", false);
     const auto inverted = params.Get("inverted", false);
@@ -725,7 +730,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice(
         .pad = static_cast<std::size_t>(params.Get("pad", 0)),
     };
 
-    const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
+    const auto axis_x = params.Get("axis_x", 0);
     const Common::Input::AnalogProperties properties_x = {
         .deadzone = deadzone,
         .range = range,
@@ -734,7 +739,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice(
         .inverted = params.Get("invert_x", "+") == "-",
     };
 
-    const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
+    const auto axis_y = params.Get("axis_y", 1);
     const Common::Input::AnalogProperties properties_y = {
         .deadzone = deadzone,
         .range = range,
@@ -757,7 +762,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateAnalogDevice(
         .pad = static_cast<std::size_t>(params.Get("pad", 0)),
     };
 
-    const auto axis = static_cast<u32>(params.Get("axis", 0));
+    const auto axis = params.Get("axis", 0);
     const Common::Input::AnalogProperties properties = {
         .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f),
         .range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f),
@@ -778,11 +783,11 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTriggerDevice(
         .pad = static_cast<std::size_t>(params.Get("pad", 0)),
     };
 
-    const auto button = static_cast<u32>(params.Get("button", 0));
+    const auto button = params.Get("button", 0);
     const auto toggle = params.Get("toggle", false);
     const auto inverted = params.Get("inverted", false);
 
-    const auto axis = static_cast<u32>(params.Get("axis", 0));
+    const auto axis = params.Get("axis", 0);
     const Common::Input::AnalogProperties properties = {
         .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f),
         .range = std::clamp(params.Get("range", 1.0f), 0.25f, 2.50f),
@@ -809,11 +814,11 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice(
         .pad = static_cast<std::size_t>(params.Get("pad", 0)),
     };
 
-    const auto button = static_cast<u32>(params.Get("button", 0));
+    const auto button = params.Get("button", 0);
     const auto toggle = params.Get("toggle", false);
     const auto inverted = params.Get("inverted", false);
 
-    const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
+    const auto axis_x = params.Get("axis_x", 0);
     const Common::Input::AnalogProperties properties_x = {
         .deadzone = deadzone,
         .range = range,
@@ -822,7 +827,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice(
         .inverted = params.Get("invert_x", "+") == "-",
     };
 
-    const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
+    const auto axis_y = params.Get("axis_y", 1);
     const Common::Input::AnalogProperties properties_y = {
         .deadzone = deadzone,
         .range = range,
@@ -869,7 +874,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateMotionDevice(
     const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f);
     const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f);
 
-    const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
+    const auto axis_x = params.Get("axis_x", 0);
     const Common::Input::AnalogProperties properties_x = {
         .deadzone = deadzone,
         .range = range,
@@ -878,7 +883,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateMotionDevice(
         .inverted = params.Get("invert_x", "+") == "-",
     };
 
-    const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
+    const auto axis_y = params.Get("axis_y", 1);
     const Common::Input::AnalogProperties properties_y = {
         .deadzone = deadzone,
         .range = range,
@@ -887,7 +892,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateMotionDevice(
         .inverted = params.Get("invert_y", "+") != "+",
     };
 
-    const auto axis_z = static_cast<u32>(params.Get("axis_z", 1));
+    const auto axis_z = params.Get("axis_z", 1);
     const Common::Input::AnalogProperties properties_z = {
         .deadzone = deadzone,
         .range = range,
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 59289c6a5f..e9cb578b4a 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -26,8 +26,6 @@
 
 namespace {
 
-constexpr std::size_t HANDHELD_INDEX = 8;
-
 void UpdateController(Core::HID::EmulatedController* controller,
                       Core::HID::NpadType controller_type, bool connected) {
     if (controller->IsConnected()) {
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 9a1b3575e2..8d6289d8e6 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -38,8 +38,6 @@ const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM>
 
 namespace {
 
-constexpr std::size_t HANDHELD_INDEX = 8;
-
 QString GetKeyName(int key_code) {
     switch (key_code) {
     case Qt::Key_Shift:
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui
index 14ca02fd84..958a892290 100644
--- a/src/yuzu/configuration/configure_input_player.ui
+++ b/src/yuzu/configuration/configure_input_player.ui
@@ -89,31 +89,6 @@
               <height>21</height>
              </size>
             </property>
-            <item>
-             <property name="text">
-              <string>Pro Controller</string>
-             </property>
-            </item>
-            <item>
-             <property name="text">
-              <string>Dual Joycons</string>
-             </property>
-            </item>
-            <item>
-             <property name="text">
-              <string>Left Joycon</string>
-             </property>
-            </item>
-            <item>
-             <property name="text">
-              <string>Right Joycon</string>
-             </property>
-            </item>
-            <item>
-             <property name="text">
-              <string>Handheld</string>
-             </property>
-            </item>
            </widget>
           </item>
          </layout>
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index bb20e9339b..99c4f13c36 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -118,7 +118,7 @@ void PlayerControlPreview::ResetInputs() {
     });
     trigger_values.fill({
         .analog = {.value = 0, .properties = {0, 1, 0}},
-        .pressed = false,
+        .pressed = {.value = false},
     });
     update();
 }
@@ -2001,11 +2001,11 @@ void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center,
 
     // Left trigger
     p.setPen(colors.outline);
-    p.setBrush(left_trigger.pressed ? colors.highlight : colors.button);
+    p.setBrush(left_trigger.pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qleft_trigger);
 
     // Right trigger
-    p.setBrush(right_trigger.pressed ? colors.highlight : colors.button);
+    p.setBrush(right_trigger.pressed.value ? colors.highlight : colors.button);
     DrawPolygon(p, qright_trigger);
 
     // Draw L text
@@ -2587,15 +2587,17 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
         case Direction::Up:
             arrow_button[point] = center + QPointF(up_arrow_x * size, up_arrow_y * size);
             break;
-        case Direction::Left:
-            arrow_button[point] = center + QPointF(up_arrow_y * size, up_arrow_x * size);
-            break;
         case Direction::Right:
             arrow_button[point] = center + QPointF(-up_arrow_y * size, up_arrow_x * size);
             break;
         case Direction::Down:
             arrow_button[point] = center + QPointF(up_arrow_x * size, -up_arrow_y * size);
             break;
+        case Direction::Left:
+            // Compiler doesn't optimize this correctly
+            arrow_button[point] = center + QPointF(up_arrow_button[point * 2 + 1] * size,
+                                                   up_arrow_button[point * 2 + 0] * size);
+            break;
         case Direction::None:
             break;
         }
@@ -2610,15 +2612,15 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
     case Direction::Up:
         offset = QPoint(0, -20 * size);
         break;
-    case Direction::Left:
-        offset = QPoint(-20 * size, 0);
-        break;
     case Direction::Right:
         offset = QPoint(20 * size, 0);
         break;
     case Direction::Down:
         offset = QPoint(0, 20 * size);
         break;
+    case Direction::Left:
+        offset = QPoint(-20 * size, 0);
+        break;
     case Direction::None:
         offset = QPoint(0, 0);
         break;

From 77fa4d4bf60526826ef8b53ee3870f7d2a761976 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 1 Nov 2021 14:17:53 -0600
Subject: [PATCH 63/88] second commit lion review

---
 src/common/input.h                                   |  2 +-
 src/core/hid/emulated_console.cpp                    |  5 +++--
 src/core/hid/emulated_controller.cpp                 |  5 +++--
 src/core/hid/emulated_devices.cpp                    |  5 +++--
 src/core/hid/hid_core.cpp                            |  3 +++
 src/core/hid/hid_core.h                              | 10 +++++++---
 src/core/hid/input_converter.h                       | 12 ++++++++++--
 .../hle/service/am/applets/applet_controller.cpp     |  2 ++
 .../hle/service/hid/controllers/console_sixaxis.cpp  |  1 +
 src/core/hle/service/hid/controllers/debug_pad.cpp   |  1 +
 src/core/hle/service/hid/controllers/gesture.h       |  5 +----
 src/core/hle/service/hid/controllers/keyboard.cpp    |  1 +
 src/core/hle/service/hid/controllers/mouse.cpp       |  1 +
 src/core/hle/service/hid/controllers/npad.cpp        |  2 ++
 src/core/hle/service/hid/controllers/npad.h          |  6 +++++-
 src/core/hle/service/hid/controllers/touchscreen.h   |  1 +
 src/input_common/drivers/keyboard.cpp                |  6 ++++++
 src/input_common/drivers/keyboard.h                  |  7 -------
 src/input_common/drivers/mouse.cpp                   |  5 +++++
 src/input_common/drivers/mouse.h                     |  5 -----
 src/input_common/drivers/touch_screen.cpp            |  6 ++++++
 src/input_common/drivers/touch_screen.h              |  8 +-------
 src/input_common/input_engine.cpp                    |  5 +++--
 src/yuzu/applets/qt_controller.cpp                   |  1 +
 .../configuration/configure_input_player_widget.cpp  |  5 ++---
 .../configuration/configure_input_player_widget.h    |  1 +
 src/yuzu/debugger/controller.h                       |  3 ++-
 src/yuzu/main.cpp                                    |  1 +
 28 files changed, 73 insertions(+), 42 deletions(-)

diff --git a/src/common/input.h b/src/common/input.h
index 16b1e6f1ba..12acd8785f 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -29,7 +29,7 @@ enum class InputType {
     Ir,
 };
 
-enum class BatteryLevel {
+enum class BatteryLevel : u32 {
     None,
     Empty,
     Critical,
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index 0129099544..dfbaa3f8c6 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -209,10 +209,11 @@ int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) {
 
 void EmulatedConsole::DeleteCallback(int key) {
     std::lock_guard lock{mutex};
-    if (!callback_list.contains(key)) {
+    const auto& iterator = callback_list.find(key);
+    if (iterator == callback_list.end()) {
         LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
         return;
     }
-    callback_list.erase(key);
+    callback_list.erase(iterator);
 }
 } // namespace Core::HID
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 9a18642791..7bab00bb1b 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -993,10 +993,11 @@ int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) {
 
 void EmulatedController::DeleteCallback(int key) {
     std::lock_guard lock{mutex};
-    if (!callback_list.contains(key)) {
+    const auto& iterator = callback_list.find(key);
+    if (iterator == callback_list.end()) {
         LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
         return;
     }
-    callback_list.erase(key);
+    callback_list.erase(iterator);
 }
 } // namespace Core::HID
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
index c76a86b6c4..e97470240e 100644
--- a/src/core/hid/emulated_devices.cpp
+++ b/src/core/hid/emulated_devices.cpp
@@ -362,10 +362,11 @@ int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) {
 
 void EmulatedDevices::DeleteCallback(int key) {
     std::lock_guard lock{mutex};
-    if (!callback_list.contains(key)) {
+    const auto& iterator = callback_list.find(key);
+    if (iterator == callback_list.end()) {
         LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
         return;
     }
-    callback_list.erase(key);
+    callback_list.erase(iterator);
 }
 } // namespace Core::HID
diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp
index 3cb26e1e71..741a69c3cc 100644
--- a/src/core/hid/hid_core.cpp
+++ b/src/core/hid/hid_core.cpp
@@ -3,6 +3,9 @@
 // Refer to the license.txt file included.
 
 #include "common/assert.h"
+#include "core/hid/emulated_console.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/emulated_devices.h"
 #include "core/hid/hid_core.h"
 
 namespace Core::HID {
diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h
index a4a66a3a44..1fe2fd89be 100644
--- a/src/core/hid/hid_core.h
+++ b/src/core/hid/hid_core.h
@@ -6,9 +6,13 @@
 
 #include <memory>
 
-#include "core/hid/emulated_console.h"
-#include "core/hid/emulated_controller.h"
-#include "core/hid/emulated_devices.h"
+#include "core/hid/hid_types.h"
+
+namespace Core::HID {
+class EmulatedConsole;
+class EmulatedController;
+class EmulatedDevices;
+} // namespace Core::HID
 
 namespace Core::HID {
 
diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h
index b38e657b08..2a722b39f8 100644
--- a/src/core/hid/input_converter.h
+++ b/src/core/hid/input_converter.h
@@ -4,9 +4,17 @@
 
 #pragma once
 
-namespace Input {
+namespace Common::Input {
 struct CallbackStatus;
-};
+enum class BatteryLevel : u32;
+using BatteryStatus = BatteryLevel;
+struct AnalogStatus;
+struct ButtonStatus;
+struct MotionStatus;
+struct StickStatus;
+struct TouchStatus;
+struct TriggerStatus;
+}; // namespace Common::Input
 
 namespace Core::HID {
 
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index 658265a004..374e0c7f46 100644
--- a/src/core/hle/service/am/applets/applet_controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -10,6 +10,8 @@
 #include "common/string_util.h"
 #include "core/core.h"
 #include "core/frontend/applets/controller.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/result.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applet_controller.h"
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
index 1d351fde05..2bebcf0d0b 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
@@ -5,6 +5,7 @@
 #include "common/settings.h"
 #include "core/core.h"
 #include "core/core_timing.h"
+#include "core/hid/emulated_console.h"
 #include "core/hle/service/hid/controllers/console_sixaxis.h"
 
 namespace Service::HID {
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index b009ed086e..86b95f2c8b 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -7,6 +7,7 @@
 #include "common/settings.h"
 #include "core/core.h"
 #include "core/core_timing.h"
+#include "core/hid/emulated_controller.h"
 #include "core/hid/hid_core.h"
 #include "core/hid/hid_types.h"
 #include "core/hle/service/hid/controllers/debug_pad.h"
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 58139a5cf9..9bffde438e 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -8,13 +8,10 @@
 #include "common/bit_field.h"
 #include "common/common_types.h"
 #include "common/point.h"
+#include "core/hid/emulated_console.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 {
 class Controller_Gesture final : public ControllerBase {
 public:
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 60dc62f2c8..acea68e24e 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -7,6 +7,7 @@
 #include "common/settings.h"
 #include "core/core.h"
 #include "core/core_timing.h"
+#include "core/hid/emulated_devices.h"
 #include "core/hid/hid_core.h"
 #include "core/hle/service/hid/controllers/keyboard.h"
 
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 7ec75e8c87..21f7e48bb6 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -7,6 +7,7 @@
 #include "core/core.h"
 #include "core/core_timing.h"
 #include "core/frontend/emu_window.h"
+#include "core/hid/emulated_devices.h"
 #include "core/hid/hid_core.h"
 #include "core/hle/service/hid/controllers/mouse.h"
 
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 9f82f872ae..0b5a236969 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -12,6 +12,8 @@
 #include "common/settings.h"
 #include "core/core.h"
 #include "core/core_timing.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/kernel/k_event.h"
 #include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_writable_event.h"
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 4a9c9cc1ab..871d245fd8 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -12,11 +12,15 @@
 #include "common/common_types.h"
 #include "common/quaternion.h"
 #include "common/settings.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/ring_lifo.h"
 
+namespace Core::HID {
+class EmulatedController;
+enum class ControllerTriggerType;
+} // namespace Core::HID
+
 namespace Kernel {
 class KEvent;
 class KReadableEvent;
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index fa4dfa1a20..50dadd25f5 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -9,6 +9,7 @@
 #include "common/common_types.h"
 #include "common/point.h"
 #include "common/swap.h"
+#include "core/hid/emulated_console.h"
 #include "core/hid/hid_core.h"
 #include "core/hid/hid_types.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp
index 85a781a304..549704e89a 100644
--- a/src/input_common/drivers/keyboard.cpp
+++ b/src/input_common/drivers/keyboard.cpp
@@ -7,6 +7,12 @@
 
 namespace InputCommon {
 
+constexpr PadIdentifier identifier = {
+    .guid = Common::UUID{Common::INVALID_UUID},
+    .port = 0,
+    .pad = 0,
+};
+
 Keyboard::Keyboard(const std::string& input_engine_) : InputEngine(input_engine_) {
     PreSetController(identifier);
 }
diff --git a/src/input_common/drivers/keyboard.h b/src/input_common/drivers/keyboard.h
index 58df150507..46fe785764 100644
--- a/src/input_common/drivers/keyboard.h
+++ b/src/input_common/drivers/keyboard.h
@@ -32,13 +32,6 @@ public:
 
     /// Used for automapping features
     std::vector<Common::ParamPackage> GetInputDevices() const override;
-
-private:
-    const PadIdentifier identifier = {
-        .guid = Common::UUID{Common::INVALID_UUID},
-        .port = 0,
-        .pad = 0,
-    };
 };
 
 } // namespace InputCommon
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
index 1c32b54bea..afa92b4583 100644
--- a/src/input_common/drivers/mouse.cpp
+++ b/src/input_common/drivers/mouse.cpp
@@ -14,6 +14,11 @@
 namespace InputCommon {
 constexpr int touch_axis_x = 10;
 constexpr int touch_axis_y = 11;
+constexpr PadIdentifier identifier = {
+    .guid = Common::UUID{Common::INVALID_UUID},
+    .port = 0,
+    .pad = 0,
+};
 
 Mouse::Mouse(const std::string input_engine_) : InputEngine(input_engine_) {
     PreSetController(identifier);
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index cf09184098..1be362b946 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -62,11 +62,6 @@ private:
     void UpdateThread(std::stop_token stop_token);
     void StopPanning();
 
-    const PadIdentifier identifier = {
-        .guid = Common::UUID{Common::INVALID_UUID},
-        .port = 0,
-        .pad = 0,
-    };
     Common::Vec2<int> mouse_origin;
     Common::Vec2<int> last_mouse_position;
     Common::Vec2<float> last_mouse_change;
diff --git a/src/input_common/drivers/touch_screen.cpp b/src/input_common/drivers/touch_screen.cpp
index e13835e9f3..377c9ee2b5 100644
--- a/src/input_common/drivers/touch_screen.cpp
+++ b/src/input_common/drivers/touch_screen.cpp
@@ -7,6 +7,12 @@
 
 namespace InputCommon {
 
+constexpr PadIdentifier identifier = {
+    .guid = Common::UUID{Common::INVALID_UUID},
+    .port = 0,
+    .pad = 0,
+};
+
 TouchScreen::TouchScreen(const std::string input_engine_) : InputEngine(input_engine_) {
     PreSetController(identifier);
 }
diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h
index d297d253ce..0f4cd0e7ad 100644
--- a/src/input_common/drivers/touch_screen.h
+++ b/src/input_common/drivers/touch_screen.h
@@ -37,14 +37,8 @@ public:
      */
     void TouchReleased(std::size_t finger);
 
+    /// Resets all inputs to their initial value
     void ReleaseAllTouch();
-
-private:
-    const PadIdentifier identifier = {
-        .guid = Common::UUID{Common::INVALID_UUID},
-        .port = 0,
-        .pad = 0,
-    };
 };
 
 } // namespace InputCommon
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp
index 965a2bdf16..139d8d2e61 100644
--- a/src/input_common/input_engine.cpp
+++ b/src/input_common/input_engine.cpp
@@ -353,11 +353,12 @@ void InputEngine::SetMappingCallback(MappingCallback callback) {
 
 void InputEngine::DeleteCallback(int key) {
     std::lock_guard lock{mutex_callback};
-    if (!callback_list.contains(key)) {
+    const auto& iterator = callback_list.find(key);
+    if (iterator == callback_list.end()) {
         LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
         return;
     }
-    callback_list.erase(key);
+    callback_list.erase(iterator);
 }
 
 } // namespace InputCommon
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index e9cb578b4a..9c6377cf0a 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -10,6 +10,7 @@
 #include "common/string_util.h"
 #include "core/core.h"
 #include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
 #include "core/hid/hid_types.h"
 #include "core/hle/lock.h"
 #include "core/hle/service/hid/controllers/npad.h"
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 99c4f13c36..7e71a0f58a 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -2594,9 +2594,8 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
             arrow_button[point] = center + QPointF(up_arrow_x * size, -up_arrow_y * size);
             break;
         case Direction::Left:
-            // Compiler doesn't optimize this correctly
-            arrow_button[point] = center + QPointF(up_arrow_button[point * 2 + 1] * size,
-                                                   up_arrow_button[point * 2 + 0] * size);
+            // Compiler doesn't optimize this correctly check why
+            arrow_button[point] = center + QPointF(up_arrow_y * size, up_arrow_x * size);
             break;
         case Direction::None:
             break;
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index 430e4f4f4c..acc53a9e30 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -9,6 +9,7 @@
 #include <QPointer>
 #include "common/input.h"
 #include "common/settings.h"
+#include "core/hid/emulated_controller.h"
 #include "core/hid/hid_core.h"
 #include "core/hid/hid_types.h"
 
diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h
index ba4185a4bb..d08643baaf 100644
--- a/src/yuzu/debugger/controller.h
+++ b/src/yuzu/debugger/controller.h
@@ -21,7 +21,8 @@ class System;
 
 namespace Core::HID {
 class EmulatedController;
-}
+enum class ControllerTriggerType;
+} // namespace Core::HID
 
 class ControllerDialog : public QWidget {
     Q_OBJECT
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 56db337a4e..7c95851b37 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -26,6 +26,7 @@
 #include "core/frontend/applets/controller.h"
 #include "core/frontend/applets/general_frontend.h"
 #include "core/frontend/applets/software_keyboard.h"
+#include "core/hid/emulated_controller.h"
 #include "core/hid/hid_core.h"
 #include "core/hle/service/acc/profile_manager.h"
 #include "core/hle/service/am/applet_ae.h"

From 136eb9c4c2b2425c2dd45a79cf444dee7170714d Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 1 Nov 2021 19:49:14 -0600
Subject: [PATCH 64/88] core/hid: Fully emulate motion from button

---
 src/common/input.h                            |  5 ++
 src/core/hid/emulated_controller.cpp          | 11 ++-
 src/core/hid/emulated_controller.h            |  1 +
 src/core/hid/input_converter.cpp              | 78 ++++++++++---------
 src/core/hid/motion_input.h                   | 16 ++++
 .../helpers/stick_from_buttons.cpp            | 12 +++
 .../helpers/touch_from_buttons.cpp            | 11 ++-
 7 files changed, 97 insertions(+), 37 deletions(-)

diff --git a/src/common/input.h b/src/common/input.h
index 12acd8785f..8f29026a11 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -110,9 +110,14 @@ struct MotionSensor {
 };
 
 struct MotionStatus {
+    // Gyroscope vector measurement in radians/s.
     MotionSensor gyro{};
+    // Acceleration vector measurement in G force
     MotionSensor accel{};
+    // Time since last measurement in microseconds
     u64 delta_timestamp{};
+    // Request to update after reading the value
+    bool force_update{};
 };
 
 struct TouchStatus {
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 7bab00bb1b..2db2b4da09 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -644,6 +644,7 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std::
     });
     emulated.UpdateRotation(raw_status.delta_timestamp);
     emulated.UpdateOrientation(raw_status.delta_timestamp);
+    force_update_motion = raw_status.force_update;
 
     if (is_configuring) {
         TriggerOnChange(ControllerTriggerType::Motion, false);
@@ -653,7 +654,7 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std::
     auto& motion = controller.motion_state[index];
     motion.accel = emulated.GetAcceleration();
     motion.gyro = emulated.GetGyroscope();
-    motion.rotation = emulated.GetGyroscope();
+    motion.rotation = emulated.GetRotations();
     motion.orientation = emulated.GetOrientation();
     motion.is_at_rest = emulated.IsMoving(motion_sensitivity);
 
@@ -962,6 +963,14 @@ NpadGcTriggerState EmulatedController::GetTriggers() const {
 }
 
 MotionState EmulatedController::GetMotions() const {
+    if (force_update_motion) {
+        for (auto& device : motion_devices) {
+            if (!device) {
+                continue;
+            }
+            device->ForceUpdate();
+        }
+    }
     return controller.motion_state;
 }
 
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index dd9a93364a..2f7afff56d 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -355,6 +355,7 @@ private:
     bool is_connected{false};
     bool is_configuring{false};
     f32 motion_sensitivity{0.01f};
+    bool force_update_motion{false};
 
     // Temporary values to avoid doing changes while the controller is on configuration mode
     NpadType tmp_npad_type{NpadType::None};
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index 5b123bd3ab..480b862fdc 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -74,45 +74,53 @@ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatu
     Common::Input::MotionStatus status{};
     switch (callback.type) {
     case Common::Input::InputType::Button: {
+        Common::Input::AnalogProperties properties{
+            .deadzone = 0.0f,
+            .range = 1.0f,
+            .offset = 0.0f,
+        };
+        status.delta_timestamp = 5000;
+        status.force_update = true;
+        status.accel.x = {
+            .value = 0.0f,
+            .raw_value = 0.0f,
+            .properties = properties,
+        };
+        status.accel.y = {
+            .value = 0.0f,
+            .raw_value = 0.0f,
+            .properties = properties,
+        };
+        status.accel.z = {
+            .value = 0.0f,
+            .raw_value = -1.0f,
+            .properties = properties,
+        };
+        status.gyro.x = {
+            .value = 0.0f,
+            .raw_value = 0.0f,
+            .properties = properties,
+        };
+        status.gyro.y = {
+            .value = 0.0f,
+            .raw_value = 0.0f,
+            .properties = properties,
+        };
+        status.gyro.z = {
+            .value = 0.0f,
+            .raw_value = 0.0f,
+            .properties = properties,
+        };
         if (TransformToButton(callback).value) {
             std::random_device device;
             std::mt19937 gen(device());
             std::uniform_int_distribution<s16> distribution(-1000, 1000);
-            Common::Input::AnalogProperties properties{
-                .deadzone = 0.0,
-                .range = 1.0f,
-                .offset = 0.0,
-            };
-            status.accel.x = {
-                .value = 0,
-                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
-                .properties = properties,
-            };
-            status.accel.y = {
-                .value = 0,
-                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
-                .properties = properties,
-            };
-            status.accel.z = {
-                .value = 0,
-                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
-                .properties = properties,
-            };
-            status.gyro.x = {
-                .value = 0,
-                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
-                .properties = properties,
-            };
-            status.gyro.y = {
-                .value = 0,
-                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
-                .properties = properties,
-            };
-            status.gyro.z = {
-                .value = 0,
-                .raw_value = static_cast<f32>(distribution(gen)) * 0.001f,
-                .properties = properties,
-            };
+            status.accel.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
+            status.accel.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
+            status.accel.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
+            status.gyro.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
+            status.gyro.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
+            status.gyro.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
         }
         break;
     }
diff --git a/src/core/hid/motion_input.h b/src/core/hid/motion_input.h
index 3deef5ac30..5b5b420bba 100644
--- a/src/core/hid/motion_input.h
+++ b/src/core/hid/motion_input.h
@@ -56,15 +56,31 @@ private:
     Common::Vec3f integral_error;
     Common::Vec3f derivative_error;
 
+    // Quaternion containing the device orientation
     Common::Quaternion<f32> quat{{0.0f, 0.0f, -1.0f}, 0.0f};
+
+    // Number of full rotations in each axis
     Common::Vec3f rotations;
+
+    // Acceleration vector measurement in G force
     Common::Vec3f accel;
+
+    // Gyroscope vector measurement in radians/s.
     Common::Vec3f gyro;
+
+    // Vector to be substracted from gyro measurements
     Common::Vec3f gyro_drift;
 
+    // Minimum gyro amplitude to detect if the device is moving
     f32 gyro_threshold = 0.0f;
+
+    // Number of invalid sequential data
     u32 reset_counter = 0;
+
+    // If the provided data is invalid the device will be autocalibrated
     bool reset_enabled = true;
+
+    // Use accelerometer values to calculate position
     bool only_accelerometer = true;
 };
 
diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp
index 1d5948f793..77fcd655ed 100644
--- a/src/input_common/helpers/stick_from_buttons.cpp
+++ b/src/input_common/helpers/stick_from_buttons.cpp
@@ -36,6 +36,8 @@ public:
         left->SetCallback(button_left_callback);
         right->SetCallback(button_right_callback);
         modifier->SetCallback(button_modifier_callback);
+        last_x_axis_value = 0.0f;
+        last_y_axis_value = 0.0f;
     }
 
     bool IsAngleGreater(float old_angle, float new_angle) const {
@@ -199,6 +201,8 @@ public:
             .type = Common::Input::InputType::Stick,
             .stick_status = GetStatus(),
         };
+        last_x_axis_value = status.stick_status.x.raw_value;
+        last_y_axis_value = status.stick_status.y.raw_value;
         TriggerOnChange(status);
     }
 
@@ -215,6 +219,12 @@ public:
             .type = Common::Input::InputType::Stick,
             .stick_status = GetStatus(),
         };
+        if (last_x_axis_value == status.stick_status.x.raw_value &&
+            last_y_axis_value == status.stick_status.y.raw_value) {
+            return;
+        }
+        last_x_axis_value = status.stick_status.x.raw_value;
+        last_y_axis_value = status.stick_status.y.raw_value;
         TriggerOnChange(status);
     }
 
@@ -265,6 +275,8 @@ private:
     bool left_status;
     bool right_status;
     bool modifier_status;
+    float last_x_axis_value;
+    float last_y_axis_value;
     const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
     std::chrono::time_point<std::chrono::steady_clock> last_update;
 };
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp
index 0243437158..35d60bc909 100644
--- a/src/input_common/helpers/touch_from_buttons.cpp
+++ b/src/input_common/helpers/touch_from_buttons.cpp
@@ -16,10 +16,15 @@ public:
         : button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) {
         Common::Input::InputCallback button_up_callback{
             [this](Common::Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }};
+        last_button_value = false;
         button->SetCallback(button_up_callback);
         button->ForceUpdate();
     }
 
+    void ForceUpdate() override {
+        button->ForceUpdate();
+    }
+
     Common::Input::TouchStatus GetStatus(bool pressed) const {
         const Common::Input::ButtonStatus button_status{
             .value = pressed,
@@ -47,11 +52,15 @@ public:
             .type = Common::Input::InputType::Touch,
             .touch_status = GetStatus(button_callback.button_status.value),
         };
-        TriggerOnChange(status);
+        if (last_button_value != button_callback.button_status.value) {
+            last_button_value = button_callback.button_status.value;
+            TriggerOnChange(status);
+        }
     }
 
 private:
     Button button;
+    bool last_button_value;
     const int touch_id;
     const float x;
     const float y;

From 157e0b85fdd805e02d234dccf1ce578e3159adee Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Tue, 2 Nov 2021 22:50:30 -0600
Subject: [PATCH 65/88] core/hid: Prevent Emulated controller from flapping
 with multiple inputs devices

---
 src/common/input.h                     |  4 ++
 src/core/hid/emulated_controller.cpp   | 68 ++++++++++++++++++++++----
 src/core/hid/emulated_controller.h     |  6 +--
 src/input_common/drivers/tas_input.cpp | 24 ++++-----
 src/input_common/drivers/tas_input.h   | 11 ++---
 5 files changed, 77 insertions(+), 36 deletions(-)

diff --git a/src/common/input.h b/src/common/input.h
index 8f29026a11..f21872b0a5 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -11,6 +11,7 @@
 #include <utility>
 #include "common/logging/log.h"
 #include "common/param_package.h"
+#include "common/uuid.h"
 
 namespace Common::Input {
 
@@ -81,6 +82,7 @@ struct AnalogStatus {
 };
 
 struct ButtonStatus {
+    Common::UUID uuid{};
     bool value{};
     bool inverted{};
     bool toggle{};
@@ -90,6 +92,7 @@ struct ButtonStatus {
 using BatteryStatus = BatteryLevel;
 
 struct StickStatus {
+    Common::UUID uuid{};
     AnalogStatus x{};
     AnalogStatus y{};
     bool left{};
@@ -99,6 +102,7 @@ struct StickStatus {
 };
 
 struct TriggerStatus {
+    Common::UUID uuid{};
     AnalogStatus analog{};
     ButtonStatus pressed{};
 };
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 2db2b4da09..6fe3744fd2 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -183,8 +183,11 @@ void EmulatedController::ReloadInput() {
         if (!button_devices[index]) {
             continue;
         }
+        const auto uuid = Common::UUID{button_params[index].Get("guid", "")};
         Common::Input::InputCallback button_callback{
-            [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }};
+            [this, index, uuid](Common::Input::CallbackStatus callback) {
+                SetButton(callback, index, uuid);
+            }};
         button_devices[index]->SetCallback(button_callback);
         button_devices[index]->ForceUpdate();
     }
@@ -193,8 +196,11 @@ void EmulatedController::ReloadInput() {
         if (!stick_devices[index]) {
             continue;
         }
+        const auto uuid = Common::UUID{stick_params[index].Get("guid", "")};
         Common::Input::InputCallback stick_callback{
-            [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }};
+            [this, index, uuid](Common::Input::CallbackStatus callback) {
+                SetStick(callback, index, uuid);
+            }};
         stick_devices[index]->SetCallback(stick_callback);
         stick_devices[index]->ForceUpdate();
     }
@@ -203,8 +209,11 @@ void EmulatedController::ReloadInput() {
         if (!trigger_devices[index]) {
             continue;
         }
+        const auto uuid = Common::UUID{trigger_params[index].Get("guid", "")};
         Common::Input::InputCallback trigger_callback{
-            [this, index](Common::Input::CallbackStatus callback) { SetTrigger(callback, index); }};
+            [this, index, uuid](Common::Input::CallbackStatus callback) {
+                SetTrigger(callback, index, uuid);
+            }};
         trigger_devices[index]->SetCallback(trigger_callback);
         trigger_devices[index]->ForceUpdate();
     }
@@ -229,13 +238,18 @@ void EmulatedController::ReloadInput() {
         motion_devices[index]->ForceUpdate();
     }
 
+    // Use a common UUID for TAS
+    const auto tas_uuid = Common::UUID{0x0, 0x7A5};
+
     // Register TAS devices. No need to force update
     for (std::size_t index = 0; index < tas_button_devices.size(); ++index) {
         if (!tas_button_devices[index]) {
             continue;
         }
         Common::Input::InputCallback button_callback{
-            [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }};
+            [this, index, tas_uuid](Common::Input::CallbackStatus callback) {
+                SetButton(callback, index, tas_uuid);
+            }};
         tas_button_devices[index]->SetCallback(button_callback);
     }
 
@@ -244,7 +258,9 @@ void EmulatedController::ReloadInput() {
             continue;
         }
         Common::Input::InputCallback stick_callback{
-            [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }};
+            [this, index, tas_uuid](Common::Input::CallbackStatus callback) {
+                SetStick(callback, index, tas_uuid);
+            }};
         tas_stick_devices[index]->SetCallback(stick_callback);
     }
 }
@@ -423,7 +439,8 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage
     ReloadInput();
 }
 
-void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index) {
+void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index,
+                                   Common::UUID uuid) {
     if (index >= controller.button_values.size()) {
         return;
     }
@@ -432,7 +449,16 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::
         bool value_changed = false;
         const auto new_status = TransformToButton(callback);
         auto& current_status = controller.button_values[index];
+
+        // Only read button values that have the same uuid or are pressed once
+        if (current_status.uuid != uuid) {
+            if (!new_status.value) {
+                return;
+            }
+        }
+
         current_status.toggle = new_status.toggle;
+        current_status.uuid = uuid;
 
         // Update button status with current
         if (!current_status.toggle) {
@@ -553,12 +579,23 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::
     TriggerOnChange(ControllerTriggerType::Button, true);
 }
 
-void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index) {
+void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index,
+                                  Common::UUID uuid) {
     if (index >= controller.stick_values.size()) {
         return;
     }
     std::lock_guard lock{mutex};
-    controller.stick_values[index] = TransformToStick(callback);
+    const auto stick_value = TransformToStick(callback);
+
+    // Only read stick values that have the same uuid or are over the threshold to avoid flapping
+    if (controller.stick_values[index].uuid != uuid) {
+        if (!stick_value.down && !stick_value.up && !stick_value.left && !stick_value.right) {
+            return;
+        }
+    }
+
+    controller.stick_values[index] = stick_value;
+    controller.stick_values[index].uuid = uuid;
 
     if (is_configuring) {
         controller.analog_stick_state.left = {};
@@ -592,12 +629,23 @@ void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::s
     TriggerOnChange(ControllerTriggerType::Stick, true);
 }
 
-void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index) {
+void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index,
+                                    Common::UUID uuid) {
     if (index >= controller.trigger_values.size()) {
         return;
     }
     std::lock_guard lock{mutex};
-    controller.trigger_values[index] = TransformToTrigger(callback);
+    const auto trigger_value = TransformToTrigger(callback);
+
+    // Only read trigger values that have the same uuid or are pressed once
+    if (controller.stick_values[index].uuid != uuid) {
+        if (!trigger_value.pressed.value) {
+            return;
+        }
+    }
+
+    controller.trigger_values[index] = trigger_value;
+    controller.trigger_values[index].uuid = uuid;
 
     if (is_configuring) {
         controller.gc_trigger_state.left = 0;
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 2f7afff56d..9a8bdf14dc 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -313,21 +313,21 @@ private:
      * @param callback: A CallbackStatus containing the button status
      * @param index: Button ID of the to be updated
      */
-    void SetButton(Common::Input::CallbackStatus callback, std::size_t index);
+    void SetButton(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
 
     /**
      * Updates the analog stick status of the controller
      * @param callback: A CallbackStatus containing the analog stick status
      * @param index: stick ID of the to be updated
      */
-    void SetStick(Common::Input::CallbackStatus callback, std::size_t index);
+    void SetStick(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
 
     /**
      * Updates the trigger status of the controller
      * @param callback: A CallbackStatus containing the trigger status
      * @param index: trigger ID of the to be updated
      */
-    void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index);
+    void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
 
     /**
      * Updates the motion status of the controller
diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp
index d2748b2407..bb9c236eae 100644
--- a/src/input_common/drivers/tas_input.cpp
+++ b/src/input_common/drivers/tas_input.cpp
@@ -71,21 +71,21 @@ Tas::~Tas() {
 void Tas::LoadTasFiles() {
     script_length = 0;
     for (size_t i = 0; i < commands.size(); i++) {
-        LoadTasFile(i);
+        LoadTasFile(i, 0);
         if (commands[i].size() > script_length) {
             script_length = commands[i].size();
         }
     }
 }
 
-void Tas::LoadTasFile(size_t player_index) {
+void Tas::LoadTasFile(size_t player_index, size_t file_index) {
     if (!commands[player_index].empty()) {
         commands[player_index].clear();
     }
-    std::string file =
-        Common::FS::ReadStringFromFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) /
-                                           fmt::format("script0-{}.txt", player_index + 1),
-                                       Common::FS::FileType::BinaryFile);
+    std::string file = Common::FS::ReadStringFromFile(
+        Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) /
+            fmt::format("script{}-{}.txt", file_index, player_index + 1),
+        Common::FS::FileType::BinaryFile);
     std::stringstream command_line(file);
     std::string line;
     int frame_no = 0;
@@ -144,15 +144,8 @@ void Tas::WriteTasFile(std::u8string file_name) {
 void Tas::RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis) {
     last_input = {
         .buttons = buttons,
-        .l_axis = FlipAxisY(left_axis),
-        .r_axis = FlipAxisY(right_axis),
-    };
-}
-
-TasAnalog Tas::FlipAxisY(TasAnalog old) {
-    return {
-        .x = old.x,
-        .y = -old.y,
+        .l_axis = left_axis,
+        .r_axis = right_axis,
     };
 }
 
@@ -219,6 +212,7 @@ void Tas::UpdateThread() {
         }
     } else {
         is_running = Settings::values.tas_loop.GetValue();
+        LoadTasFiles();
         current_command = 0;
         ClearInput();
     }
diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h
index 82dc9d6160..bfb37a638b 100644
--- a/src/input_common/drivers/tas_input.h
+++ b/src/input_common/drivers/tas_input.h
@@ -138,21 +138,16 @@ private:
     void LoadTasFiles();
 
     /** Loads TAS file from the specified player
-     * @param player_index: player number where data is going to be stored
+     * @param player_index: player number to save the script
+     * @param file_index: script number of the file
      */
-    void LoadTasFile(size_t player_index);
+    void LoadTasFile(size_t player_index, size_t file_index);
 
     /** Writes a TAS file from the recorded commands
      * @param file_name: name of the file to be written
      */
     void WriteTasFile(std::u8string file_name);
 
-    /** Inverts the Y axis polarity
-     * @param old: value of the axis
-     * @return new value of the axis
-     */
-    TasAnalog FlipAxisY(TasAnalog old);
-
     /**
      * Parses a string containing the axis values. X and Y have a range from -32767 to 32767
      * @param line: string containing axis values with the following format "x;y"

From c35af8d1c05d94028b215df7721e5235083bcb97 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Wed, 3 Nov 2021 17:06:21 -0600
Subject: [PATCH 66/88] input_common: Fix motion from 3 axis

---
 src/input_common/input_poller.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 01c4358023..92cf690cd9 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -606,6 +606,8 @@ public:
             .raw_value = input_engine->GetAxis(identifier, axis_z),
             .properties = properties_z,
         };
+        status.delta_timestamp = 5000;
+        status.force_update = true;
         return status;
     }
 

From 84c58666a4dbb6d46e132514e4d91437fb689fa0 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Wed, 3 Nov 2021 22:35:45 -0600
Subject: [PATCH 67/88] config: Cleanup and documentation

---
 src/common/input.h                            | 34 ++++++++-
 src/common/settings.h                         |  3 -
 src/core/hid/emulated_console.cpp             |  6 +-
 src/yuzu/configuration/config.cpp             |  4 --
 .../configuration/configure_motion_touch.cpp  |  8 +--
 .../configuration/configure_motion_touch.ui   | 70 ++-----------------
 src/yuzu_cmd/config.cpp                       |  3 -
 src/yuzu_cmd/default_ini.h                    | 17 +----
 8 files changed, 46 insertions(+), 99 deletions(-)

diff --git a/src/common/input.h b/src/common/input.h
index f21872b0a5..d997853c61 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -15,6 +15,7 @@
 
 namespace Common::Input {
 
+// Type of data that is expected to recieve or send
 enum class InputType {
     None,
     Battery,
@@ -30,6 +31,7 @@ enum class InputType {
     Ir,
 };
 
+// Internal battery charge level
 enum class BatteryLevel : u32 {
     None,
     Empty,
@@ -41,13 +43,17 @@ enum class BatteryLevel : u32 {
 };
 
 enum class PollingMode {
+    // Constant polling of buttons, analogs and motion data
     Active,
+    // Only update on button change, digital analogs
     Pasive,
-    Camera,
-    NCF,
+    // Enable near field communication polling
+    NFC,
+    // Enable infrared camera polling
     IR,
 };
 
+// Vibration reply from the controller
 enum class VibrationError {
     None,
     NotSupported,
@@ -55,6 +61,7 @@ enum class VibrationError {
     Unknown,
 };
 
+// Polling mode reply from the controller
 enum class PollingError {
     None,
     NotSupported,
@@ -67,20 +74,28 @@ enum class VibrationAmplificationType {
     Exponential,
 };
 
+// Analog properties for calibration
 struct AnalogProperties {
+    // Anything below this value will be detected as zero
     float deadzone{};
+    // Anyting above this values will be detected as one
     float range{1.0f};
+    // Minimum value to be detected as active
     float threshold{0.5f};
+    // Drift correction applied to the raw data
     float offset{};
+    // Invert direction of the sensor data
     bool inverted{};
 };
 
+// Single analog sensor data
 struct AnalogStatus {
     float value{};
     float raw_value{};
     AnalogProperties properties{};
 };
 
+// Button data
 struct ButtonStatus {
     Common::UUID uuid{};
     bool value{};
@@ -89,8 +104,10 @@ struct ButtonStatus {
     bool locked{};
 };
 
+// Internal battery data
 using BatteryStatus = BatteryLevel;
 
+// Analog and digital joystick data
 struct StickStatus {
     Common::UUID uuid{};
     AnalogStatus x{};
@@ -101,18 +118,21 @@ struct StickStatus {
     bool down{};
 };
 
+// Analog and digital trigger data
 struct TriggerStatus {
     Common::UUID uuid{};
     AnalogStatus analog{};
     ButtonStatus pressed{};
 };
 
+// 3D vector representing motion input
 struct MotionSensor {
     AnalogStatus x{};
     AnalogStatus y{};
     AnalogStatus z{};
 };
 
+// Motion data used to calculate controller orientation
 struct MotionStatus {
     // Gyroscope vector measurement in radians/s.
     MotionSensor gyro{};
@@ -124,6 +144,7 @@ struct MotionStatus {
     bool force_update{};
 };
 
+// Data of a single point on a touch screen
 struct TouchStatus {
     ButtonStatus pressed{};
     AnalogStatus x{};
@@ -131,11 +152,13 @@ struct TouchStatus {
     int id{};
 };
 
+// Physical controller color in RGB format
 struct BodyColorStatus {
     u32 body{};
     u32 buttons{};
 };
 
+// HD rumble data
 struct VibrationStatus {
     f32 low_amplitude{};
     f32 low_frequency{};
@@ -144,6 +167,7 @@ struct VibrationStatus {
     VibrationAmplificationType type;
 };
 
+// Physical controller LED pattern
 struct LedStatus {
     bool led_1{};
     bool led_2{};
@@ -151,6 +175,7 @@ struct LedStatus {
     bool led_4{};
 };
 
+// Callback data consisting of an input type and the equivalent data status
 struct CallbackStatus {
     InputType type{InputType::None};
     ButtonStatus button_status{};
@@ -164,6 +189,7 @@ struct CallbackStatus {
     VibrationStatus vibration_status{};
 };
 
+// Triggered once every input change
 struct InputCallback {
     std::function<void(CallbackStatus)> on_change;
 };
@@ -178,15 +204,17 @@ public:
         return;
     }
 
-    // Force input device to update data regarless of the current state
+    // Force input device to update data regardless of the current state
     virtual void ForceUpdate() {
         return;
     }
 
+    // Sets the function to be triggered when input changes
     void SetCallback(InputCallback callback_) {
         callback = std::move(callback_);
     }
 
+    // Triggers the function set in the callback
     void TriggerOnChange(CallbackStatus status) {
         if (callback.on_change) {
             callback.on_change(status);
diff --git a/src/common/settings.h b/src/common/settings.h
index 95225fba7e..b52d0d1d0f 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -559,8 +559,6 @@ struct Values {
     Setting<bool> enable_accurate_vibrations{false, "enable_accurate_vibrations"};
 
     Setting<bool> motion_enabled{true, "motion_enabled"};
-    BasicSetting<std::string> motion_device{"engine:motion_emu,update_period:100,sensitivity:0.01",
-                                            "motion_device"};
     BasicSetting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"};
 
     BasicSetting<bool> pause_tas_on_load{true, "pause_tas_on_load"};
@@ -583,7 +581,6 @@ struct Values {
 
     TouchscreenInput touchscreen;
 
-    BasicSetting<bool> use_touch_from_button{false, "use_touch_from_button"};
     BasicSetting<std::string> touch_device{"min_x:100,min_y:50,max_x:1800,max_y:850",
                                            "touch_device"};
     BasicSetting<int> touch_from_button_map_index{0, "touch_from_button_map"};
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index dfbaa3f8c6..b51c72eae0 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -11,7 +11,7 @@ EmulatedConsole::EmulatedConsole() = default;
 EmulatedConsole::~EmulatedConsole() = default;
 
 void EmulatedConsole::ReloadFromSettings() {
-    // Using first motion device from player 1. No need to assign a special config at the moment
+    // Using first motion device from player 1. No need to assign any unique config at the moment
     const auto& player = Settings::values.players.GetValue()[0];
     motion_params = Common::ParamPackage(player.motions[0]);
 
@@ -33,6 +33,7 @@ void EmulatedConsole::SetTouchParams() {
         static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
     const auto& touch_buttons = Settings::values.touch_from_button_maps[button_index].buttons;
 
+    // Map the rest of the fingers from touch from button configuration
     for (const auto& config_entry : touch_buttons) {
         Common::ParamPackage params{config_entry};
         Common::ParamPackage touch_button_params;
@@ -54,7 +55,9 @@ void EmulatedConsole::SetTouchParams() {
 }
 
 void EmulatedConsole::ReloadInput() {
+    // If you load any device here add the equivalent to the UnloadInput() function
     SetTouchParams();
+
     motion_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(motion_params);
     if (motion_devices) {
         Common::Input::InputCallback motion_callback{
@@ -62,6 +65,7 @@ void EmulatedConsole::ReloadInput() {
         motion_devices->SetCallback(motion_callback);
     }
 
+    // Unique index for identifying touch device source
     std::size_t index = 0;
     for (auto& touch_device : touch_devices) {
         touch_device = Common::Input::CreateDevice<Common::Input::InputDevice>(touch_params[index]);
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 7a748d9c83..7669fe4748 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -623,9 +623,7 @@ void Config::ReadMotionTouchValues() {
     }
     qt_config->endArray();
 
-    ReadBasicSetting(Settings::values.motion_device);
     ReadBasicSetting(Settings::values.touch_device);
-    ReadBasicSetting(Settings::values.use_touch_from_button);
     ReadBasicSetting(Settings::values.touch_from_button_map_index);
     Settings::values.touch_from_button_map_index = std::clamp(
         Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
@@ -1131,9 +1129,7 @@ void Config::SaveTouchscreenValues() {
 }
 
 void Config::SaveMotionTouchValues() {
-    WriteBasicSetting(Settings::values.motion_device);
     WriteBasicSetting(Settings::values.touch_device);
-    WriteBasicSetting(Settings::values.use_touch_from_button);
     WriteBasicSetting(Settings::values.touch_from_button_map_index);
     WriteBasicSetting(Settings::values.udp_input_servers);
 
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp
index 9fd1a919f2..8539a5c8b6 100644
--- a/src/yuzu/configuration/configure_motion_touch.cpp
+++ b/src/yuzu/configuration/configure_motion_touch.cpp
@@ -93,6 +93,7 @@ ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent,
            "using-a-controller-or-android-phone-for-motion-or-touch-input'><span "
            "style=\"text-decoration: underline; color:#039be5;\">Learn More</span></a>"));
 
+    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
     SetConfiguration();
     UpdateUiDisplay();
     ConnectEvents();
@@ -101,17 +102,14 @@ ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent,
 ConfigureMotionTouch::~ConfigureMotionTouch() = default;
 
 void ConfigureMotionTouch::SetConfiguration() {
-    const Common::ParamPackage motion_param(Settings::values.motion_device.GetValue());
     const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue());
 
-    ui->touch_from_button_checkbox->setChecked(Settings::values.use_touch_from_button.GetValue());
     touch_from_button_maps = Settings::values.touch_from_button_maps;
     for (const auto& touch_map : touch_from_button_maps) {
         ui->touch_from_button_map->addItem(QString::fromStdString(touch_map.name));
     }
     ui->touch_from_button_map->setCurrentIndex(
         Settings::values.touch_from_button_map_index.GetValue());
-    ui->motion_sensitivity->setValue(motion_param.Get("sensitivity", 0.01f));
 
     min_x = touch_param.Get("min_x", 100);
     min_y = touch_param.Get("min_y", 50);
@@ -139,9 +137,6 @@ void ConfigureMotionTouch::SetConfiguration() {
 void ConfigureMotionTouch::UpdateUiDisplay() {
     const QString cemuhook_udp = QStringLiteral("cemuhookudp");
 
-    ui->motion_sensitivity_label->setVisible(true);
-    ui->motion_sensitivity->setVisible(true);
-
     ui->touch_calibration->setVisible(true);
     ui->touch_calibration_config->setVisible(true);
     ui->touch_calibration_label->setVisible(true);
@@ -312,7 +307,6 @@ void ConfigureMotionTouch::ApplyConfiguration() {
     touch_param.Set("max_y", max_y);
 
     Settings::values.touch_device = touch_param.Serialize();
-    Settings::values.use_touch_from_button = ui->touch_from_button_checkbox->isChecked();
     Settings::values.touch_from_button_map_index = ui->touch_from_button_map->currentIndex();
     Settings::values.touch_from_button_maps = touch_from_button_maps;
     Settings::values.udp_input_servers = GetUDPServerString();
diff --git a/src/yuzu/configuration/configure_motion_touch.ui b/src/yuzu/configuration/configure_motion_touch.ui
index 1e35ea946e..c75a84ae41 100644
--- a/src/yuzu/configuration/configure_motion_touch.ui
+++ b/src/yuzu/configuration/configure_motion_touch.ui
@@ -2,14 +2,6 @@
 <ui version="4.0">
  <class>ConfigureMotionTouch</class>
  <widget class="QDialog" name="ConfigureMotionTouch">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>500</width>
-    <height>482</height>
-   </rect>
-  </property>
   <property name="windowTitle">
    <string>Configure Motion / Touch</string>
   </property>
@@ -17,48 +9,6 @@
    <string notr="true"/>
   </property>
   <layout class="QVBoxLayout">
-   <item>
-    <widget class="QGroupBox" name="motion_group_box">
-     <property name="title">
-      <string>Mouse Motion</string>
-     </property>
-     <layout class="QVBoxLayout">
-      <item>
-       <layout class="QHBoxLayout">
-        <item>
-         <widget class="QLabel" name="motion_sensitivity_label">
-          <property name="text">
-           <string>Sensitivity:</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QDoubleSpinBox" name="motion_sensitivity">
-          <property name="alignment">
-           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-          </property>
-          <property name="decimals">
-           <number>4</number>
-          </property>
-          <property name="minimum">
-           <double>0.010000000000000</double>
-          </property>
-          <property name="maximum">
-           <double>10.000000000000000</double>
-          </property>
-          <property name="singleStep">
-           <double>0.001000000000000</double>
-          </property>
-          <property name="value">
-           <double>0.010000000000000</double>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-     </layout>
-    </widget>
-   </item>
    <item>
     <widget class="QGroupBox" name="touch_group_box">
      <property name="title">
@@ -101,19 +51,13 @@
       </item>
       <item>
        <layout class="QHBoxLayout">
-        <item>
-         <widget class="QCheckBox" name="touch_from_button_checkbox">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="text">
-           <string>Use button mapping:</string>
-          </property>
-         </widget>
-        </item>
+         <item>
+           <widget class="QLabel" name="touch_from_button_label">
+             <property name="text">
+               <string>Touch from button profile:</string>
+             </property>
+           </widget>
+         </item>
         <item>
          <widget class="QComboBox" name="touch_from_button_map"/>
         </item>
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 103a12b120..7ca09a635b 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -292,8 +292,6 @@ void Config::ReadValues() {
             Settings::values.mouse_buttons[i] = default_param;
     }
 
-    ReadSetting("ControlsGeneral", Settings::values.motion_device);
-
     ReadSetting("ControlsGeneral", Settings::values.touch_device);
 
     ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled);
@@ -362,7 +360,6 @@ void Config::ReadValues() {
             Settings::TouchFromButtonMap{"default", {}});
         num_touch_from_button_maps = 1;
     }
-    ReadSetting("ControlsGeneral", Settings::values.use_touch_from_button);
     Settings::values.touch_from_button_map_index = std::clamp(
         Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
 
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index ecdc271a80..6d613bf7a1 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -84,23 +84,10 @@ enable_accurate_vibrations=
 # 0: Disabled, 1 (default): Enabled
 motion_enabled =
 
-# for motion input, the following devices are available:
-#  - "motion_emu" (default) for emulating motion input from mouse input. Required parameters:
-#      - "update_period": update period in milliseconds (default to 100)
-#      - "sensitivity": the coefficient converting mouse movement to tilting angle (default to 0.01)
-#  - "cemuhookudp" reads motion input from a udp server that uses cemuhook's udp protocol
-motion_device=
-
-# for touch input, the following devices are available:
-#  - "emu_window" (default) for emulating touch input from mouse input to the emulation window. No parameters required
-#  - "cemuhookudp" reads touch input from a udp server that uses cemuhook's udp protocol
-#      - "min_x", "min_y", "max_x", "max_y": defines the udp device's touch screen coordinate system
+# Defines the udp device's touch screen coordinate system for cemuhookudp devices
+#  - "min_x", "min_y", "max_x", "max_y"
 touch_device=
 
-# Whether to enable or disable touch input from button
-# 0 (default): Disabled, 1: Enabled
-use_touch_from_button=
-
 # for mapping buttons to touch inputs.
 #touch_from_button_map=1
 #touch_from_button_maps_0_name=default

From 5d0f3540c4b085103afa27d6120ea29e0324a5a2 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Thu, 4 Nov 2021 12:08:54 -0600
Subject: [PATCH 68/88] core/hid: Rename NpadType to NpadStyleIndex

---
 src/core/frontend/applets/controller.cpp      |  10 +-
 src/core/hid/emulated_controller.cpp          |  44 +++---
 src/core/hid/emulated_controller.h            |  18 +--
 src/core/hid/hid_types.h                      |  13 +-
 src/core/hle/service/hid/controllers/npad.cpp | 129 +++++++++---------
 src/core/hle/service/hid/controllers/npad.h   |  11 +-
 src/core/hle/service/hid/hid.cpp              |  14 +-
 src/yuzu/applets/qt_controller.cpp            |  65 ++++-----
 src/yuzu/applets/qt_controller.h              |   8 +-
 src/yuzu/applets/qt_software_keyboard.cpp     |  14 +-
 .../configuration/configure_input_player.cpp  |  87 ++++++------
 .../configuration/configure_input_player.h    |   8 +-
 .../configure_input_player_widget.cpp         |  18 +--
 .../configure_input_player_widget.h           |   2 +-
 src/yuzu/main.cpp                             |   2 +-
 15 files changed, 228 insertions(+), 215 deletions(-)

diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp
index 212ace8924..6dbd38ffae 100644
--- a/src/core/frontend/applets/controller.cpp
+++ b/src/core/frontend/applets/controller.cpp
@@ -44,26 +44,26 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
         // Connect controllers based on the following priority list from highest to lowest priority:
         // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
         if (parameters.allow_pro_controller) {
-            controller->SetNpadType(Core::HID::NpadType::ProController);
+            controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
             controller->Connect();
         } else if (parameters.allow_dual_joycons) {
-            controller->SetNpadType(Core::HID::NpadType::JoyconDual);
+            controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual);
             controller->Connect();
         } else if (parameters.allow_left_joycon && parameters.allow_right_joycon) {
             // Assign left joycons to even player indices and right joycons to odd player indices.
             // We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and
             // a right Joycon for Player 2 in 2 Player Assist mode.
             if (index % 2 == 0) {
-                controller->SetNpadType(Core::HID::NpadType::JoyconLeft);
+                controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconLeft);
                 controller->Connect();
             } else {
-                controller->SetNpadType(Core::HID::NpadType::JoyconRight);
+                controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconRight);
                 controller->Connect();
             }
         } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
                    !Settings::values.use_docked_mode.GetValue()) {
             // We should *never* reach here under any normal circumstances.
-            controller->SetNpadType(Core::HID::NpadType::Handheld);
+            controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
             controller->Connect();
         } else {
             UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!");
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 6fe3744fd2..a200992f2f 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -13,38 +13,38 @@ EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type(
 
 EmulatedController::~EmulatedController() = default;
 
-NpadType EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) {
+NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) {
     switch (type) {
     case Settings::ControllerType::ProController:
-        return NpadType::ProController;
+        return NpadStyleIndex::ProController;
     case Settings::ControllerType::DualJoyconDetached:
-        return NpadType::JoyconDual;
+        return NpadStyleIndex::JoyconDual;
     case Settings::ControllerType::LeftJoycon:
-        return NpadType::JoyconLeft;
+        return NpadStyleIndex::JoyconLeft;
     case Settings::ControllerType::RightJoycon:
-        return NpadType::JoyconRight;
+        return NpadStyleIndex::JoyconRight;
     case Settings::ControllerType::Handheld:
-        return NpadType::Handheld;
+        return NpadStyleIndex::Handheld;
     case Settings::ControllerType::GameCube:
-        return NpadType::GameCube;
+        return NpadStyleIndex::GameCube;
     default:
-        return NpadType::ProController;
+        return NpadStyleIndex::ProController;
     }
 }
 
-Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type) {
+Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) {
     switch (type) {
-    case NpadType::ProController:
+    case NpadStyleIndex::ProController:
         return Settings::ControllerType::ProController;
-    case NpadType::JoyconDual:
+    case NpadStyleIndex::JoyconDual:
         return Settings::ControllerType::DualJoyconDetached;
-    case NpadType::JoyconLeft:
+    case NpadStyleIndex::JoyconLeft:
         return Settings::ControllerType::LeftJoycon;
-    case NpadType::JoyconRight:
+    case NpadStyleIndex::JoyconRight:
         return Settings::ControllerType::RightJoycon;
-    case NpadType::Handheld:
+    case NpadStyleIndex::Handheld:
         return Settings::ControllerType::Handheld;
-    case NpadType::GameCube:
+    case NpadStyleIndex::GameCube:
         return Settings::ControllerType::GameCube;
     default:
         return Settings::ControllerType::ProController;
@@ -79,9 +79,9 @@ void EmulatedController::ReloadFromSettings() {
 
     // Other or debug controller should always be a pro controller
     if (npad_id_type != NpadIdType::Other) {
-        SetNpadType(MapSettingsTypeToNPad(player.controller_type));
+        SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type));
     } else {
-        SetNpadType(NpadType::ProController);
+        SetNpadStyleIndex(NpadStyleIndex::ProController);
     }
 
     if (player.connected) {
@@ -306,7 +306,7 @@ void EmulatedController::DisableConfiguration() {
         if (is_connected) {
             Disconnect();
         }
-        SetNpadType(tmp_npad_type);
+        SetNpadStyleIndex(tmp_npad_type);
     }
 
     // Apply temporary connected status to the real controller
@@ -569,10 +569,10 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::
         }
     }
     if (!is_connected) {
-        if (npad_id_type == NpadIdType::Player1 && npad_type != NpadType::Handheld) {
+        if (npad_id_type == NpadIdType::Player1 && npad_type != NpadStyleIndex::Handheld) {
             Connect();
         }
-        if (npad_id_type == NpadIdType::Handheld && npad_type == NpadType::Handheld) {
+        if (npad_id_type == NpadIdType::Handheld && npad_type == NpadStyleIndex::Handheld) {
             Connect();
         }
     }
@@ -896,14 +896,14 @@ NpadIdType EmulatedController::GetNpadIdType() const {
     return npad_id_type;
 }
 
-NpadType EmulatedController::GetNpadType(bool get_temporary_value) const {
+NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const {
     if (get_temporary_value) {
         return tmp_npad_type;
     }
     return npad_type;
 }
 
-void EmulatedController::SetNpadType(NpadType npad_type_) {
+void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
     {
         std::lock_guard lock{mutex};
 
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 9a8bdf14dc..fa2e89c0b8 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -142,23 +142,23 @@ public:
     YUZU_NON_MOVEABLE(EmulatedController);
 
     /// Converts the controller type from settings to npad type
-    static NpadType MapSettingsTypeToNPad(Settings::ControllerType type);
+    static NpadStyleIndex MapSettingsTypeToNPad(Settings::ControllerType type);
 
     /// Converts npad type to the equivalent of controller type from settings
-    static Settings::ControllerType MapNPadToSettingsType(NpadType type);
+    static Settings::ControllerType MapNPadToSettingsType(NpadStyleIndex type);
 
     /// Gets the NpadIdType for this controller
     NpadIdType GetNpadIdType() const;
 
-    /// Sets the NpadType for this controller
-    void SetNpadType(NpadType npad_type_);
+    /// Sets the NpadStyleIndex for this controller
+    void SetNpadStyleIndex(NpadStyleIndex npad_type_);
 
     /**
-     * Gets the NpadType for this controller
+     * Gets the NpadStyleIndex for this controller
      * @param If true tmp_npad_type will be returned
-     * @return NpadType set on the controller
+     * @return NpadStyleIndex set on the controller
      */
-    NpadType GetNpadType(bool get_temporary_value = false) const;
+    NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const;
 
     /// Sets the connected status to true
     void Connect();
@@ -351,14 +351,14 @@ private:
     void TriggerOnChange(ControllerTriggerType type, bool is_service_update);
 
     NpadIdType npad_id_type;
-    NpadType npad_type{NpadType::None};
+    NpadStyleIndex npad_type{NpadStyleIndex::None};
     bool is_connected{false};
     bool is_configuring{false};
     f32 motion_sensitivity{0.01f};
     bool force_update_motion{false};
 
     // Temporary values to avoid doing changes while the controller is on configuration mode
-    NpadType tmp_npad_type{NpadType::None};
+    NpadStyleIndex tmp_npad_type{NpadStyleIndex::None};
     bool tmp_is_connected{false};
 
     ButtonParams button_params;
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index f8a0d5edd0..7e4f6a804e 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -84,8 +84,8 @@ constexpr NpadIdType IndexToNpadIdType(size_t index) {
     }
 }
 
-// This is nn::hid::NpadType
-enum class NpadType : u8 {
+// This is nn::hid::NpadStyleIndex
+enum class NpadStyleIndex : u8 {
     None = 0,
     ProController = 3,
     Handheld = 4,
@@ -94,7 +94,14 @@ enum class NpadType : u8 {
     JoyconRight = 7,
     GameCube = 8,
     Pokeball = 9,
-    MaxNpadType = 10,
+    NES = 10,
+    HandheldNES = 11,
+    SNES = 12,
+    N64 = 13,
+    SegaGenesis = 14,
+    SystemExt = 32,
+    System = 33,
+    MaxNpadType = 34,
 };
 
 // This is nn::hid::NpadStyleTag
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 0b5a236969..e4a3d91634 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -93,7 +93,7 @@ bool Controller_NPad::IsNpadIdValid(u32 npad_id) {
 
 bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) {
     return IsNpadIdValid(device_handle.npad_id) &&
-           device_handle.npad_type < Core::HID::NpadType::MaxNpadType &&
+           device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType &&
            device_handle.device_index < DeviceIndex::MaxDeviceIndex;
 }
 
@@ -134,7 +134,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
 
     auto& controller = controller_data[controller_idx];
     const auto is_connected = controller.device->IsConnected();
-    const auto npad_type = controller.device->GetNpadType();
+    const auto npad_type = controller.device->GetNpadStyleIndex();
     switch (type) {
     case Core::HID::ControllerTriggerType::Connected:
     case Core::HID::ControllerTriggerType::Disconnected:
@@ -161,9 +161,9 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
 
 void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
     auto& controller = controller_data[controller_idx];
-    const auto controller_type = controller.device->GetNpadType();
+    const auto controller_type = controller.device->GetNpadStyleIndex();
     auto& shared_memory = controller.shared_memory_entry;
-    if (controller_type == Core::HID::NpadType::None) {
+    if (controller_type == Core::HID::NpadStyleIndex::None) {
         controller.styleset_changed_event->GetWritableEvent().Signal();
         return;
     }
@@ -171,10 +171,10 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
     shared_memory.device_type.raw = 0;
     shared_memory.system_properties.raw = 0;
     switch (controller_type) {
-    case Core::HID::NpadType::None:
+    case Core::HID::NpadStyleIndex::None:
         UNREACHABLE();
         break;
-    case Core::HID::NpadType::ProController:
+    case Core::HID::NpadStyleIndex::ProController:
         shared_memory.style_set.fullkey.Assign(1);
         shared_memory.device_type.fullkey.Assign(1);
         shared_memory.system_properties.is_vertical.Assign(1);
@@ -183,7 +183,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
         shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController;
         break;
-    case Core::HID::NpadType::Handheld:
+    case Core::HID::NpadStyleIndex::Handheld:
         shared_memory.style_set.handheld.Assign(1);
         shared_memory.device_type.handheld_left.Assign(1);
         shared_memory.device_type.handheld_right.Assign(1);
@@ -193,7 +193,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
         shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
         break;
-    case Core::HID::NpadType::JoyconDual:
+    case Core::HID::NpadStyleIndex::JoyconDual:
         shared_memory.style_set.joycon_dual.Assign(1);
         shared_memory.device_type.joycon_left.Assign(1);
         shared_memory.device_type.joycon_right.Assign(1);
@@ -203,7 +203,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
         shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
         break;
-    case Core::HID::NpadType::JoyconLeft:
+    case Core::HID::NpadStyleIndex::JoyconLeft:
         shared_memory.style_set.joycon_left.Assign(1);
         shared_memory.device_type.joycon_left.Assign(1);
         shared_memory.system_properties.is_horizontal.Assign(1);
@@ -211,7 +211,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
         shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
         break;
-    case Core::HID::NpadType::JoyconRight:
+    case Core::HID::NpadStyleIndex::JoyconRight:
         shared_memory.style_set.joycon_right.Assign(1);
         shared_memory.device_type.joycon_right.Assign(1);
         shared_memory.system_properties.is_horizontal.Assign(1);
@@ -219,14 +219,14 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
         shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
         break;
-    case Core::HID::NpadType::GameCube:
+    case Core::HID::NpadStyleIndex::GameCube:
         shared_memory.style_set.gamecube.Assign(1);
         // The GC Controller behaves like a wired Pro Controller
         shared_memory.device_type.fullkey.Assign(1);
         shared_memory.system_properties.is_vertical.Assign(1);
         shared_memory.system_properties.use_plus.Assign(1);
         break;
-    case Core::HID::NpadType::Pokeball:
+    case Core::HID::NpadStyleIndex::Pokeball:
         shared_memory.style_set.palma.Assign(1);
         shared_memory.device_type.palma.Assign(1);
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
@@ -307,7 +307,7 @@ void Controller_NPad::OnInit() {
         const auto& device = controller.device;
         if (device->IsConnected()) {
             const std::size_t index = Core::HID::NpadIdTypeToIndex(device->GetNpadIdType());
-            AddNewControllerAt(device->GetNpadType(), index);
+            AddNewControllerAt(device->GetNpadStyleIndex(), index);
         }
     }
 }
@@ -347,7 +347,7 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
     std::lock_guard lock{mutex};
     const auto controller_idx = NPadIdToIndex(npad_id);
     auto& controller = controller_data[controller_idx];
-    const auto controller_type = controller.device->GetNpadType();
+    const auto controller_type = controller.device->GetNpadStyleIndex();
     if (!controller.device->IsConnected()) {
         return;
     }
@@ -359,7 +359,7 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
 
     using btn = Core::HID::NpadButton;
     pad_entry.npad_buttons.raw = btn::None;
-    if (controller_type != Core::HID::NpadType::JoyconLeft) {
+    if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) {
         constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R |
                                           btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp |
                                           btn::StickRRight | btn::StickRDown;
@@ -367,7 +367,7 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
         pad_entry.r_stick = stick_state.right;
     }
 
-    if (controller_type != Core::HID::NpadType::JoyconRight) {
+    if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) {
         constexpr btn left_button_mask =
             btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL |
             btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown;
@@ -375,17 +375,17 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
         pad_entry.l_stick = stick_state.left;
     }
 
-    if (controller_type == Core::HID::NpadType::JoyconLeft) {
+    if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft) {
         pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
         pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
     }
 
-    if (controller_type == Core::HID::NpadType::JoyconRight) {
+    if (controller_type == Core::HID::NpadStyleIndex::JoyconRight) {
         pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
         pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
     }
 
-    if (controller_type == Core::HID::NpadType::GameCube) {
+    if (controller_type == Core::HID::NpadStyleIndex::GameCube) {
         const auto& trigger_state = controller.device->GetTriggers();
         trigger_entry.l_analog = trigger_state.left;
         trigger_entry.r_analog = trigger_state.right;
@@ -406,9 +406,10 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
         auto& controller = controller_data[i];
         auto& npad = controller.shared_memory_entry;
 
-        const auto& controller_type = controller.device->GetNpadType();
+        const auto& controller_type = controller.device->GetNpadStyleIndex();
 
-        if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) {
+        if (controller_type == Core::HID::NpadStyleIndex::None ||
+            !controller.device->IsConnected()) {
             // Refresh shared memory
             std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
                         &controller.shared_memory_entry, sizeof(NpadInternalState));
@@ -426,10 +427,10 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
         libnx_state.connection_status.raw = 0;
         libnx_state.connection_status.is_connected.Assign(1);
         switch (controller_type) {
-        case Core::HID::NpadType::None:
+        case Core::HID::NpadStyleIndex::None:
             UNREACHABLE();
             break;
-        case Core::HID::NpadType::ProController:
+        case Core::HID::NpadStyleIndex::ProController:
             pad_state.connection_status.raw = 0;
             pad_state.connection_status.is_connected.Assign(1);
             pad_state.connection_status.is_wired.Assign(1);
@@ -439,7 +440,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
                 npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
             npad.fullkey_lifo.WriteNextEntry(pad_state);
             break;
-        case Core::HID::NpadType::Handheld:
+        case Core::HID::NpadStyleIndex::Handheld:
             pad_state.connection_status.raw = 0;
             pad_state.connection_status.is_connected.Assign(1);
             pad_state.connection_status.is_wired.Assign(1);
@@ -457,7 +458,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
                 npad.handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
             npad.handheld_lifo.WriteNextEntry(pad_state);
             break;
-        case Core::HID::NpadType::JoyconDual:
+        case Core::HID::NpadStyleIndex::JoyconDual:
             pad_state.connection_status.raw = 0;
             pad_state.connection_status.is_connected.Assign(1);
             pad_state.connection_status.is_left_connected.Assign(1);
@@ -469,7 +470,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
                 npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
             npad.joy_dual_lifo.WriteNextEntry(pad_state);
             break;
-        case Core::HID::NpadType::JoyconLeft:
+        case Core::HID::NpadStyleIndex::JoyconLeft:
             pad_state.connection_status.raw = 0;
             pad_state.connection_status.is_connected.Assign(1);
             pad_state.connection_status.is_left_connected.Assign(1);
@@ -479,7 +480,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
                 npad.joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
             npad.joy_left_lifo.WriteNextEntry(pad_state);
             break;
-        case Core::HID::NpadType::JoyconRight:
+        case Core::HID::NpadStyleIndex::JoyconRight:
             pad_state.connection_status.raw = 0;
             pad_state.connection_status.is_connected.Assign(1);
             pad_state.connection_status.is_right_connected.Assign(1);
@@ -489,7 +490,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
                 npad.joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
             npad.joy_right_lifo.WriteNextEntry(pad_state);
             break;
-        case Core::HID::NpadType::GameCube:
+        case Core::HID::NpadStyleIndex::GameCube:
             pad_state.connection_status.raw = 0;
             pad_state.connection_status.is_connected.Assign(1);
             pad_state.connection_status.is_wired.Assign(1);
@@ -502,7 +503,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             npad.fullkey_lifo.WriteNextEntry(pad_state);
             npad.gc_trigger_lifo.WriteNextEntry(trigger_state);
             break;
-        case Core::HID::NpadType::Pokeball:
+        case Core::HID::NpadStyleIndex::Pokeball:
             pad_state.connection_status.raw = 0;
             pad_state.connection_status.is_connected.Assign(1);
             pad_state.sampling_number =
@@ -534,9 +535,10 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
     for (std::size_t i = 0; i < controller_data.size(); ++i) {
         auto& controller = controller_data[i];
 
-        const auto& controller_type = controller.device->GetNpadType();
+        const auto& controller_type = controller.device->GetNpadStyleIndex();
 
-        if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) {
+        if (controller_type == Core::HID::NpadStyleIndex::None ||
+            !controller.device->IsConnected()) {
             continue;
         }
 
@@ -557,10 +559,10 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
         }
 
         switch (controller_type) {
-        case Core::HID::NpadType::None:
+        case Core::HID::NpadStyleIndex::None:
             UNREACHABLE();
             break;
-        case Core::HID::NpadType::ProController:
+        case Core::HID::NpadStyleIndex::ProController:
             sixaxis_fullkey_state.attribute.raw = 0;
             if (sixaxis_sensors_enabled) {
                 sixaxis_fullkey_state.attribute.is_connected.Assign(1);
@@ -570,7 +572,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
                 sixaxis_fullkey_state.orientation = motion_state[0].orientation;
             }
             break;
-        case Core::HID::NpadType::Handheld:
+        case Core::HID::NpadStyleIndex::Handheld:
             sixaxis_handheld_state.attribute.raw = 0;
             if (sixaxis_sensors_enabled) {
                 sixaxis_handheld_state.attribute.is_connected.Assign(1);
@@ -580,7 +582,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
                 sixaxis_handheld_state.orientation = motion_state[0].orientation;
             }
             break;
-        case Core::HID::NpadType::JoyconDual:
+        case Core::HID::NpadStyleIndex::JoyconDual:
             sixaxis_dual_left_state.attribute.raw = 0;
             sixaxis_dual_right_state.attribute.raw = 0;
             if (sixaxis_sensors_enabled) {
@@ -600,7 +602,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
                 sixaxis_dual_right_state.orientation = motion_state[1].orientation;
             }
             break;
-        case Core::HID::NpadType::JoyconLeft:
+        case Core::HID::NpadStyleIndex::JoyconLeft:
             sixaxis_left_lifo_state.attribute.raw = 0;
             if (sixaxis_sensors_enabled) {
                 sixaxis_left_lifo_state.attribute.is_connected.Assign(1);
@@ -610,7 +612,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
                 sixaxis_left_lifo_state.orientation = motion_state[0].orientation;
             }
             break;
-        case Core::HID::NpadType::JoyconRight:
+        case Core::HID::NpadStyleIndex::JoyconRight:
             sixaxis_right_lifo_state.attribute.raw = 0;
             if (sixaxis_sensors_enabled) {
                 sixaxis_right_lifo_state.attribute.is_connected.Assign(1);
@@ -779,11 +781,11 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han
     }
 
     // Some games try to send mismatched parameters in the device handle, block these.
-    if ((controller.device->GetNpadType() == Core::HID::NpadType::JoyconLeft &&
-         (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconRight ||
+    if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
+         (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight ||
           vibration_device_handle.device_index == DeviceIndex::Right)) ||
-        (controller.device->GetNpadType() == Core::HID::NpadType::JoyconRight &&
-         (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconLeft ||
+        (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight &&
+         (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft ||
           vibration_device_handle.device_index == DeviceIndex::Left))) {
         return;
     }
@@ -876,11 +878,12 @@ void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const {
     controller.styleset_changed_event->GetWritableEvent().Signal();
 }
 
-void Controller_NPad::AddNewControllerAt(Core::HID::NpadType controller, std::size_t npad_index) {
+void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller,
+                                         std::size_t npad_index) {
     UpdateControllerAt(controller, npad_index, true);
 }
 
-void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t npad_index,
+void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, std::size_t npad_index,
                                          bool connected) {
     auto& controller = controller_data[npad_index];
     if (!connected) {
@@ -888,7 +891,7 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t n
         return;
     }
 
-    controller.device->SetNpadType(type);
+    controller.device->SetNpadStyleIndex(type);
     InitNewlyAddedController(npad_index);
 }
 
@@ -971,13 +974,13 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
 
     // If the controllers at both npad indices form a pair of left and right joycons, merge them.
     // Otherwise, do nothing.
-    if ((controller_1->GetNpadType() == Core::HID::NpadType::JoyconLeft &&
-         controller_2->GetNpadType() == Core::HID::NpadType::JoyconRight) ||
-        (controller_2->GetNpadType() == Core::HID::NpadType::JoyconLeft &&
-         controller_1->GetNpadType() == Core::HID::NpadType::JoyconRight)) {
+    if ((controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
+         controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) ||
+        (controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
+         controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight)) {
         // Disconnect the joycon at the second id and connect the dual joycon at the first index.
         DisconnectNpad(npad_id_2);
-        AddNewControllerAt(Core::HID::NpadType::JoyconDual, npad_index_1);
+        AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_index_1);
     }
 }
 
@@ -1000,8 +1003,8 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
     const auto npad_index_2 = NPadIdToIndex(npad_id_2);
     const auto& controller_1 = controller_data[npad_index_1].device;
     const auto& controller_2 = controller_data[npad_index_2].device;
-    const auto type_index_1 = controller_1->GetNpadType();
-    const auto type_index_2 = controller_2->GetNpadType();
+    const auto type_index_1 = controller_1->GetNpadStyleIndex();
+    const auto type_index_2 = controller_2->GetNpadStyleIndex();
 
     if (!IsControllerSupported(type_index_1) || !IsControllerSupported(type_index_2)) {
         return false;
@@ -1039,9 +1042,9 @@ void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
 void Controller_NPad::ClearAllConnectedControllers() {
     for (auto& controller : controller_data) {
         if (controller.device->IsConnected() &&
-            controller.device->GetNpadType() != Core::HID::NpadType::None) {
-            controller.device->SetNpadType(Core::HID::NpadType::None);
+            controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) {
             controller.device->Disconnect();
+            controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
         }
     }
 }
@@ -1054,7 +1057,7 @@ void Controller_NPad::DisconnectAllConnectedControllers() {
 
 void Controller_NPad::ConnectAllDisconnectedControllers() {
     for (auto& controller : controller_data) {
-        if (controller.device->GetNpadType() != Core::HID::NpadType::None &&
+        if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None &&
             !controller.device->IsConnected()) {
             controller.device->Connect();
         }
@@ -1063,8 +1066,8 @@ void Controller_NPad::ConnectAllDisconnectedControllers() {
 
 void Controller_NPad::ClearAllControllers() {
     for (auto& controller : controller_data) {
-        controller.device->SetNpadType(Core::HID::NpadType::None);
         controller.device->Disconnect();
+        controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
     }
 }
 
@@ -1072,8 +1075,8 @@ u32 Controller_NPad::GetAndResetPressState() {
     return press_state.exchange(0);
 }
 
-bool Controller_NPad::IsControllerSupported(Core::HID::NpadType controller) const {
-    if (controller == Core::HID::NpadType::Handheld) {
+bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
+    if (controller == Core::HID::NpadStyleIndex::Handheld) {
         const bool support_handheld =
             std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
                       NPAD_HANDHELD) != supported_npad_id_types.end();
@@ -1093,17 +1096,17 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadType controller) cons
                     [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
         Core::HID::NpadStyleTag style = GetSupportedStyleSet();
         switch (controller) {
-        case Core::HID::NpadType::ProController:
+        case Core::HID::NpadStyleIndex::ProController:
             return style.fullkey;
-        case Core::HID::NpadType::JoyconDual:
+        case Core::HID::NpadStyleIndex::JoyconDual:
             return style.joycon_dual;
-        case Core::HID::NpadType::JoyconLeft:
+        case Core::HID::NpadStyleIndex::JoyconLeft:
             return style.joycon_left;
-        case Core::HID::NpadType::JoyconRight:
+        case Core::HID::NpadStyleIndex::JoyconRight:
             return style.joycon_right;
-        case Core::HID::NpadType::GameCube:
+        case Core::HID::NpadStyleIndex::GameCube:
             return style.gamecube;
-        case Core::HID::NpadType::Pokeball:
+        case Core::HID::NpadStyleIndex::Pokeball:
             return style.palma;
         default:
             return false;
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 871d245fd8..512fb5afcd 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -96,7 +96,7 @@ public:
     };
 
     struct DeviceHandle {
-        Core::HID::NpadType npad_type;
+        Core::HID::NpadStyleIndex npad_type;
         u8 npad_id;
         DeviceIndex device_index;
         INSERT_PADDING_BYTES_NOINIT(1);
@@ -160,9 +160,10 @@ public:
     void SignalStyleSetChangedEvent(u32 npad_id) const;
 
     // Adds a new controller at an index.
-    void AddNewControllerAt(Core::HID::NpadType controller, std::size_t npad_index);
+    void AddNewControllerAt(Core::HID::NpadStyleIndex controller, std::size_t npad_index);
     // Adds a new controller at an index with connection status.
-    void UpdateControllerAt(Core::HID::NpadType controller, std::size_t npad_index, bool connected);
+    void UpdateControllerAt(Core::HID::NpadStyleIndex controller, std::size_t npad_index,
+                            bool connected);
 
     void DisconnectNpad(u32 npad_id);
     void DisconnectNpadAtIndex(std::size_t index);
@@ -496,7 +497,7 @@ private:
         std::array<VibrationData, 2> vibration{};
         bool unintended_home_button_input_protection{};
         bool is_connected{};
-        Core::HID::NpadType npad_type{Core::HID::NpadType::None};
+        Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None};
 
         // Current pad state
         NPadGenericState npad_pad_state{};
@@ -513,7 +514,7 @@ private:
 
     void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx);
     void InitNewlyAddedController(std::size_t controller_idx);
-    bool IsControllerSupported(Core::HID::NpadType controller) const;
+    bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const;
     void RequestPadStateUpdate(u32 npad_id);
     void WriteEmptyEntry(NpadInternalState& npad);
 
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index ac48f96d3b..648e69de9f 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1131,18 +1131,18 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
     Core::HID::VibrationDeviceInfo vibration_device_info;
 
     switch (vibration_device_handle.npad_type) {
-    case Core::HID::NpadType::ProController:
-    case Core::HID::NpadType::Handheld:
-    case Core::HID::NpadType::JoyconDual:
-    case Core::HID::NpadType::JoyconLeft:
-    case Core::HID::NpadType::JoyconRight:
+    case Core::HID::NpadStyleIndex::ProController:
+    case Core::HID::NpadStyleIndex::Handheld:
+    case Core::HID::NpadStyleIndex::JoyconDual:
+    case Core::HID::NpadStyleIndex::JoyconLeft:
+    case Core::HID::NpadStyleIndex::JoyconRight:
     default:
         vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator;
         break;
-    case Core::HID::NpadType::GameCube:
+    case Core::HID::NpadStyleIndex::GameCube:
         vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm;
         break;
-    case Core::HID::NpadType::Pokeball:
+    case Core::HID::NpadStyleIndex::Pokeball:
         vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown;
         break;
     }
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 9c6377cf0a..6a2cdda634 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -28,31 +28,31 @@
 namespace {
 
 void UpdateController(Core::HID::EmulatedController* controller,
-                      Core::HID::NpadType controller_type, bool connected) {
+                      Core::HID::NpadStyleIndex controller_type, bool connected) {
     if (controller->IsConnected()) {
         controller->Disconnect();
     }
-    controller->SetNpadType(controller_type);
+    controller->SetNpadStyleIndex(controller_type);
     if (connected) {
         controller->Connect();
     }
 }
 
 // Returns true if the given controller type is compatible with the given parameters.
-bool IsControllerCompatible(Core::HID::NpadType controller_type,
+bool IsControllerCompatible(Core::HID::NpadStyleIndex controller_type,
                             Core::Frontend::ControllerParameters parameters) {
     switch (controller_type) {
-    case Core::HID::NpadType::ProController:
+    case Core::HID::NpadStyleIndex::ProController:
         return parameters.allow_pro_controller;
-    case Core::HID::NpadType::JoyconDual:
+    case Core::HID::NpadStyleIndex::JoyconDual:
         return parameters.allow_dual_joycons;
-    case Core::HID::NpadType::JoyconLeft:
+    case Core::HID::NpadStyleIndex::JoyconLeft:
         return parameters.allow_left_joycon;
-    case Core::HID::NpadType::JoyconRight:
+    case Core::HID::NpadStyleIndex::JoyconRight:
         return parameters.allow_right_joycon;
-    case Core::HID::NpadType::Handheld:
+    case Core::HID::NpadStyleIndex::Handheld:
         return parameters.enable_single_mode && parameters.allow_handheld;
-    case Core::HID::NpadType::GameCube:
+    case Core::HID::NpadStyleIndex::GameCube:
         return parameters.allow_gamecube_controller;
     default:
         return false;
@@ -183,7 +183,7 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
             connect(emulated_controllers[i], qOverload<int>(&QComboBox::currentIndexChanged),
                     [this, i](int index) {
                         UpdateDockedState(GetControllerTypeFromIndex(index, i) ==
-                                          Core::HID::NpadType::Handheld);
+                                          Core::HID::NpadStyleIndex::Handheld);
                     });
         }
     }
@@ -243,7 +243,7 @@ void QtControllerSelectorDialog::LoadConfiguration() {
         player_groupboxes[index]->setChecked(connected);
         connected_controller_checkboxes[index]->setChecked(connected);
         emulated_controllers[index]->setCurrentIndex(
-            GetIndexFromControllerType(controller->GetNpadType(), index));
+            GetIndexFromControllerType(controller->GetNpadStyleIndex(), index));
     }
 
     UpdateDockedState(handheld->IsConnected());
@@ -402,32 +402,33 @@ void QtControllerSelectorDialog::SetEmulatedControllers(std::size_t player_index
     emulated_controllers[player_index]->clear();
 
     pairs.emplace_back(emulated_controllers[player_index]->count(),
-                       Core::HID::NpadType::ProController);
+                       Core::HID::NpadStyleIndex::ProController);
     emulated_controllers[player_index]->addItem(tr("Pro Controller"));
 
     pairs.emplace_back(emulated_controllers[player_index]->count(),
-                       Core::HID::NpadType::JoyconDual);
+                       Core::HID::NpadStyleIndex::JoyconDual);
     emulated_controllers[player_index]->addItem(tr("Dual Joycons"));
 
     pairs.emplace_back(emulated_controllers[player_index]->count(),
-                       Core::HID::NpadType::JoyconLeft);
+                       Core::HID::NpadStyleIndex::JoyconLeft);
     emulated_controllers[player_index]->addItem(tr("Left Joycon"));
 
     pairs.emplace_back(emulated_controllers[player_index]->count(),
-                       Core::HID::NpadType::JoyconRight);
+                       Core::HID::NpadStyleIndex::JoyconRight);
     emulated_controllers[player_index]->addItem(tr("Right Joycon"));
 
     if (player_index == 0) {
         pairs.emplace_back(emulated_controllers[player_index]->count(),
-                           Core::HID::NpadType::Handheld);
+                           Core::HID::NpadStyleIndex::Handheld);
         emulated_controllers[player_index]->addItem(tr("Handheld"));
     }
 
-    pairs.emplace_back(emulated_controllers[player_index]->count(), Core::HID::NpadType::GameCube);
+    pairs.emplace_back(emulated_controllers[player_index]->count(),
+                       Core::HID::NpadStyleIndex::GameCube);
     emulated_controllers[player_index]->addItem(tr("GameCube Controller"));
 }
 
-Core::HID::NpadType QtControllerSelectorDialog::GetControllerTypeFromIndex(
+Core::HID::NpadStyleIndex QtControllerSelectorDialog::GetControllerTypeFromIndex(
     int index, std::size_t player_index) const {
     const auto& pairs = index_controller_type_pairs[player_index];
 
@@ -435,13 +436,13 @@ Core::HID::NpadType QtControllerSelectorDialog::GetControllerTypeFromIndex(
                                  [index](const auto& pair) { return pair.first == index; });
 
     if (it == pairs.end()) {
-        return Core::HID::NpadType::ProController;
+        return Core::HID::NpadStyleIndex::ProController;
     }
 
     return it->second;
 }
 
-int QtControllerSelectorDialog::GetIndexFromControllerType(Core::HID::NpadType type,
+int QtControllerSelectorDialog::GetIndexFromControllerType(Core::HID::NpadStyleIndex type,
                                                            std::size_t player_index) const {
     const auto& pairs = index_controller_type_pairs[player_index];
 
@@ -465,16 +466,16 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
     const QString stylesheet = [this, player_index] {
         switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(),
                                            player_index)) {
-        case Core::HID::NpadType::ProController:
-        case Core::HID::NpadType::GameCube:
+        case Core::HID::NpadStyleIndex::ProController:
+        case Core::HID::NpadStyleIndex::GameCube:
             return QStringLiteral("image: url(:/controller/applet_pro_controller%0); ");
-        case Core::HID::NpadType::JoyconDual:
+        case Core::HID::NpadStyleIndex::JoyconDual:
             return QStringLiteral("image: url(:/controller/applet_dual_joycon%0); ");
-        case Core::HID::NpadType::JoyconLeft:
+        case Core::HID::NpadStyleIndex::JoyconLeft:
             return QStringLiteral("image: url(:/controller/applet_joycon_left%0); ");
-        case Core::HID::NpadType::JoyconRight:
+        case Core::HID::NpadStyleIndex::JoyconRight:
             return QStringLiteral("image: url(:/controller/applet_joycon_right%0); ");
-        case Core::HID::NpadType::Handheld:
+        case Core::HID::NpadStyleIndex::Handheld:
             return QStringLiteral("image: url(:/controller/applet_handheld%0); ");
         default:
             return QString{};
@@ -507,9 +508,9 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index)
     const auto controller_type = GetControllerTypeFromIndex(
         emulated_controllers[player_index]->currentIndex(), player_index);
     const auto player_connected = player_groupboxes[player_index]->isChecked() &&
-                                  controller_type != Core::HID::NpadType::Handheld;
+                                  controller_type != Core::HID::NpadStyleIndex::Handheld;
 
-    if (controller->GetNpadType() == controller_type &&
+    if (controller->GetNpadStyleIndex() == controller_type &&
         controller->IsConnected() == player_connected) {
         // Set vibration devices in the event that the input device has changed.
         ConfigureVibration::SetVibrationDevices(player_index);
@@ -523,10 +524,10 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index)
 
     // Handheld
     if (player_index == 0) {
-        if (controller_type == Core::HID::NpadType::Handheld) {
+        if (controller_type == Core::HID::NpadStyleIndex::Handheld) {
             auto* handheld =
                 system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
-            UpdateController(handheld, Core::HID::NpadType::Handheld,
+            UpdateController(handheld, Core::HID::NpadStyleIndex::Handheld,
                              player_groupboxes[player_index]->isChecked());
         }
     }
@@ -537,7 +538,7 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index)
 void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) {
     if (!player_groupboxes[player_index]->isChecked() ||
         GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(),
-                                   player_index) == Core::HID::NpadType::Handheld) {
+                                   player_index) == Core::HID::NpadStyleIndex::Handheld) {
         led_patterns_boxes[player_index][0]->setChecked(false);
         led_patterns_boxes[player_index][1]->setChecked(false);
         led_patterns_boxes[player_index][2]->setChecked(false);
@@ -632,7 +633,7 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
     for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) {
         auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index);
         // Disconnect any unsupported players here and disable or hide them if applicable.
-        UpdateController(controller, controller->GetNpadType(), false);
+        UpdateController(controller, controller->GetNpadStyleIndex(), false);
         // Hide the player widgets when max_supported_controllers is less than or equal to 4.
         if (max_supported_players <= 4) {
             player_widgets[index]->hide();
diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h
index dd981f4795..cc343e5aea 100644
--- a/src/yuzu/applets/qt_controller.h
+++ b/src/yuzu/applets/qt_controller.h
@@ -32,7 +32,7 @@ class System;
 }
 
 namespace Core::HID {
-enum class NpadType : u8;
+enum class NpadStyleIndex : u8;
 }
 
 class QtControllerSelectorDialog final : public QDialog {
@@ -74,10 +74,10 @@ private:
     void SetEmulatedControllers(std::size_t player_index);
 
     // Gets the Controller Type for a given controller combobox index per player.
-    Core::HID::NpadType GetControllerTypeFromIndex(int index, std::size_t player_index) const;
+    Core::HID::NpadStyleIndex GetControllerTypeFromIndex(int index, std::size_t player_index) const;
 
     // Gets the controller combobox index for a given Controller Type per player.
-    int GetIndexFromControllerType(Core::HID::NpadType type, std::size_t player_index) const;
+    int GetIndexFromControllerType(Core::HID::NpadStyleIndex type, std::size_t player_index) const;
 
     // Updates the controller icons per player.
     void UpdateControllerIcon(std::size_t player_index);
@@ -139,7 +139,7 @@ private:
     std::array<QComboBox*, NUM_PLAYERS> emulated_controllers;
 
     /// Pairs of emulated controller index and Controller Type enum per player.
-    std::array<std::vector<std::pair<int, Core::HID::NpadType>>, NUM_PLAYERS>
+    std::array<std::vector<std::pair<int, Core::HID::NpadStyleIndex>>, NUM_PLAYERS>
         index_controller_type_pairs;
 
     // Labels representing the number of connected controllers
diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp
index 3d91f80341..de7f98c4f3 100644
--- a/src/yuzu/applets/qt_software_keyboard.cpp
+++ b/src/yuzu/applets/qt_software_keyboard.cpp
@@ -801,7 +801,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
     const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
     const auto* player_1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
     const auto controller_type =
-        handheld->IsConnected() ? handheld->GetNpadType() : player_1->GetNpadType();
+        handheld->IsConnected() ? handheld->GetNpadStyleIndex() : player_1->GetNpadStyleIndex();
 
     const QString theme = [] {
         if (QIcon::themeName().contains(QStringLiteral("dark")) ||
@@ -813,8 +813,8 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
     }();
 
     switch (controller_type) {
-    case Core::HID::NpadType::ProController:
-    case Core::HID::NpadType::GameCube:
+    case Core::HID::NpadStyleIndex::ProController:
+    case Core::HID::NpadStyleIndex::GameCube:
         ui->icon_controller->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme));
         ui->icon_controller_shift->setStyleSheet(
@@ -822,7 +822,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
         ui->icon_controller_num->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme));
         break;
-    case Core::HID::NpadType::JoyconDual:
+    case Core::HID::NpadStyleIndex::JoyconDual:
         ui->icon_controller->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme));
         ui->icon_controller_shift->setStyleSheet(
@@ -830,7 +830,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
         ui->icon_controller_num->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme));
         break;
-    case Core::HID::NpadType::JoyconLeft:
+    case Core::HID::NpadStyleIndex::JoyconLeft:
         ui->icon_controller->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);")
                 .arg(theme));
@@ -841,7 +841,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
             QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);")
                 .arg(theme));
         break;
-    case Core::HID::NpadType::JoyconRight:
+    case Core::HID::NpadStyleIndex::JoyconRight:
         ui->icon_controller->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);")
                 .arg(theme));
@@ -852,7 +852,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
             QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);")
                 .arg(theme));
         break;
-    case Core::HID::NpadType::Handheld:
+    case Core::HID::NpadStyleIndex::Handheld:
         ui->icon_controller->setStyleSheet(
             QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme));
         ui->icon_controller_shift->setStyleSheet(
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 8d6289d8e6..95a9b86146 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -455,7 +455,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
         connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged),
                 [this](int index) {
                     emit HandheldStateChanged(GetControllerTypeFromIndex(index) ==
-                                              Core::HID::NpadType::Handheld);
+                                              Core::HID::NpadStyleIndex::Handheld);
                 });
     }
 
@@ -482,7 +482,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
                 UpdateControllerEnabledButtons();
                 UpdateControllerButtonNames();
                 UpdateMotionButtons();
-                const Core::HID::NpadType type =
+                const Core::HID::NpadStyleIndex type =
                     GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
 
                 if (player_index == 0) {
@@ -492,10 +492,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
                         system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
                     bool is_connected = emulated_controller->IsConnected(true);
 
-                    emulated_controller_p1->SetNpadType(type);
-                    emulated_controller_hanheld->SetNpadType(type);
+                    emulated_controller_p1->SetNpadStyleIndex(type);
+                    emulated_controller_hanheld->SetNpadStyleIndex(type);
                     if (is_connected) {
-                        if (type == Core::HID::NpadType::Handheld) {
+                        if (type == Core::HID::NpadStyleIndex::Handheld) {
                             emulated_controller_p1->Disconnect();
                             emulated_controller_hanheld->Connect();
                             emulated_controller = emulated_controller_hanheld;
@@ -507,7 +507,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
                     }
                     ui->controllerFrame->SetController(emulated_controller);
                 }
-                emulated_controller->SetNpadType(type);
+                emulated_controller->SetNpadStyleIndex(type);
             });
 
     connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
@@ -607,7 +607,8 @@ void ConfigureInputPlayer::LoadConfiguration() {
         return;
     }
 
-    const int comboBoxIndex = GetIndexFromControllerType(emulated_controller->GetNpadType(true));
+    const int comboBoxIndex =
+        GetIndexFromControllerType(emulated_controller->GetNpadStyleIndex(true));
     ui->comboControllerType->setCurrentIndex(comboBoxIndex);
     ui->groupConnectedController->setChecked(emulated_controller->IsConnected(true));
 }
@@ -810,37 +811,37 @@ void ConfigureInputPlayer::SetConnectableControllers() {
 
         if (enable_all || npad_style_set.fullkey == 1) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Core::HID::NpadType::ProController);
+                                                     Core::HID::NpadStyleIndex::ProController);
             ui->comboControllerType->addItem(tr("Pro Controller"));
         }
 
         if (enable_all || npad_style_set.joycon_dual == 1) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Core::HID::NpadType::JoyconDual);
+                                                     Core::HID::NpadStyleIndex::JoyconDual);
             ui->comboControllerType->addItem(tr("Dual Joycons"));
         }
 
         if (enable_all || npad_style_set.joycon_left == 1) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Core::HID::NpadType::JoyconLeft);
+                                                     Core::HID::NpadStyleIndex::JoyconLeft);
             ui->comboControllerType->addItem(tr("Left Joycon"));
         }
 
         if (enable_all || npad_style_set.joycon_right == 1) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Core::HID::NpadType::JoyconRight);
+                                                     Core::HID::NpadStyleIndex::JoyconRight);
             ui->comboControllerType->addItem(tr("Right Joycon"));
         }
 
         if (player_index == 0 && (enable_all || npad_style_set.handheld == 1)) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Core::HID::NpadType::Handheld);
+                                                     Core::HID::NpadStyleIndex::Handheld);
             ui->comboControllerType->addItem(tr("Handheld"));
         }
 
         if (enable_all || npad_style_set.gamecube == 1) {
             index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
-                                                     Core::HID::NpadType::GameCube);
+                                                     Core::HID::NpadStyleIndex::GameCube);
             ui->comboControllerType->addItem(tr("GameCube Controller"));
         }
     };
@@ -853,19 +854,19 @@ void ConfigureInputPlayer::SetConnectableControllers() {
     add_controllers(false, system.HIDCore().GetSupportedStyleTag());
 }
 
-Core::HID::NpadType ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const {
+Core::HID::NpadStyleIndex ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const {
     const auto it =
         std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(),
                      [index](const auto& pair) { return pair.first == index; });
 
     if (it == index_controller_type_pairs.end()) {
-        return Core::HID::NpadType::ProController;
+        return Core::HID::NpadStyleIndex::ProController;
     }
 
     return it->second;
 }
 
-int ConfigureInputPlayer::GetIndexFromControllerType(Core::HID::NpadType type) const {
+int ConfigureInputPlayer::GetIndexFromControllerType(Core::HID::NpadStyleIndex type) const {
     const auto it =
         std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(),
                      [type](const auto& pair) { return pair.second == type; });
@@ -888,7 +889,7 @@ void ConfigureInputPlayer::UpdateInputDevices() {
 void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
     auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
     if (debug) {
-        layout = Core::HID::NpadType::ProController;
+        layout = Core::HID::NpadStyleIndex::ProController;
     }
 
     // List of all the widgets that will be hidden by any of the following layouts that need
@@ -913,15 +914,15 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
 
     std::vector<QWidget*> layout_hidden;
     switch (layout) {
-    case Core::HID::NpadType::ProController:
-    case Core::HID::NpadType::JoyconDual:
-    case Core::HID::NpadType::Handheld:
+    case Core::HID::NpadStyleIndex::ProController:
+    case Core::HID::NpadStyleIndex::JoyconDual:
+    case Core::HID::NpadStyleIndex::Handheld:
         layout_hidden = {
             ui->buttonShoulderButtonsSLSR,
             ui->horizontalSpacerShoulderButtonsWidget2,
         };
         break;
-    case Core::HID::NpadType::JoyconLeft:
+    case Core::HID::NpadStyleIndex::JoyconLeft:
         layout_hidden = {
             ui->horizontalSpacerShoulderButtonsWidget2,
             ui->buttonShoulderButtonsRight,
@@ -929,7 +930,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
             ui->bottomRight,
         };
         break;
-    case Core::HID::NpadType::JoyconRight:
+    case Core::HID::NpadStyleIndex::JoyconRight:
         layout_hidden = {
             ui->horizontalSpacerShoulderButtonsWidget,
             ui->buttonShoulderButtonsLeft,
@@ -937,7 +938,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
             ui->bottomLeft,
         };
         break;
-    case Core::HID::NpadType::GameCube:
+    case Core::HID::NpadStyleIndex::GameCube:
         layout_hidden = {
             ui->buttonShoulderButtonsSLSR,
             ui->horizontalSpacerShoulderButtonsWidget2,
@@ -957,7 +958,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
 void ConfigureInputPlayer::UpdateControllerEnabledButtons() {
     auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
     if (debug) {
-        layout = Core::HID::NpadType::ProController;
+        layout = Core::HID::NpadStyleIndex::ProController;
     }
 
     // List of all the widgets that will be disabled by any of the following layouts that need
@@ -974,13 +975,13 @@ void ConfigureInputPlayer::UpdateControllerEnabledButtons() {
 
     std::vector<QWidget*> layout_disable;
     switch (layout) {
-    case Core::HID::NpadType::ProController:
-    case Core::HID::NpadType::JoyconDual:
-    case Core::HID::NpadType::Handheld:
-    case Core::HID::NpadType::JoyconLeft:
-    case Core::HID::NpadType::JoyconRight:
+    case Core::HID::NpadStyleIndex::ProController:
+    case Core::HID::NpadStyleIndex::JoyconDual:
+    case Core::HID::NpadStyleIndex::Handheld:
+    case Core::HID::NpadStyleIndex::JoyconLeft:
+    case Core::HID::NpadStyleIndex::JoyconRight:
         break;
-    case Core::HID::NpadType::GameCube:
+    case Core::HID::NpadStyleIndex::GameCube:
         layout_disable = {
             ui->buttonHome,
             ui->buttonLStickPressedGroup,
@@ -1007,24 +1008,24 @@ void ConfigureInputPlayer::UpdateMotionButtons() {
 
     // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller.
     switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) {
-    case Core::HID::NpadType::ProController:
-    case Core::HID::NpadType::JoyconLeft:
-    case Core::HID::NpadType::Handheld:
+    case Core::HID::NpadStyleIndex::ProController:
+    case Core::HID::NpadStyleIndex::JoyconLeft:
+    case Core::HID::NpadStyleIndex::Handheld:
         // Show "Motion 1" and hide "Motion 2".
         ui->buttonMotionLeftGroup->show();
         ui->buttonMotionRightGroup->hide();
         break;
-    case Core::HID::NpadType::JoyconRight:
+    case Core::HID::NpadStyleIndex::JoyconRight:
         // Show "Motion 2" and hide "Motion 1".
         ui->buttonMotionLeftGroup->hide();
         ui->buttonMotionRightGroup->show();
         break;
-    case Core::HID::NpadType::GameCube:
+    case Core::HID::NpadStyleIndex::GameCube:
         // Hide both "Motion 1/2".
         ui->buttonMotionLeftGroup->hide();
         ui->buttonMotionRightGroup->hide();
         break;
-    case Core::HID::NpadType::JoyconDual:
+    case Core::HID::NpadStyleIndex::JoyconDual:
     default:
         // Show both "Motion 1/2".
         ui->buttonMotionLeftGroup->show();
@@ -1036,15 +1037,15 @@ void ConfigureInputPlayer::UpdateMotionButtons() {
 void ConfigureInputPlayer::UpdateControllerButtonNames() {
     auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
     if (debug) {
-        layout = Core::HID::NpadType::ProController;
+        layout = Core::HID::NpadStyleIndex::ProController;
     }
 
     switch (layout) {
-    case Core::HID::NpadType::ProController:
-    case Core::HID::NpadType::JoyconDual:
-    case Core::HID::NpadType::Handheld:
-    case Core::HID::NpadType::JoyconLeft:
-    case Core::HID::NpadType::JoyconRight:
+    case Core::HID::NpadStyleIndex::ProController:
+    case Core::HID::NpadStyleIndex::JoyconDual:
+    case Core::HID::NpadStyleIndex::Handheld:
+    case Core::HID::NpadStyleIndex::JoyconLeft:
+    case Core::HID::NpadStyleIndex::JoyconRight:
         ui->buttonMiscButtonsPlusGroup->setTitle(tr("Plus"));
         ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("ZL"));
         ui->buttonShoulderButtonsZRGroup->setTitle(tr("ZR"));
@@ -1052,7 +1053,7 @@ void ConfigureInputPlayer::UpdateControllerButtonNames() {
         ui->LStick->setTitle(tr("Left Stick"));
         ui->RStick->setTitle(tr("Right Stick"));
         break;
-    case Core::HID::NpadType::GameCube:
+    case Core::HID::NpadStyleIndex::GameCube:
         ui->buttonMiscButtonsPlusGroup->setTitle(tr("Start / Pause"));
         ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("L"));
         ui->buttonShoulderButtonsZRGroup->setTitle(tr("R"));
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index 02d6920f1e..7bff4b1963 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -51,7 +51,7 @@ class System;
 
 namespace Core::HID {
 class EmulatedController;
-enum class NpadType : u8;
+enum class NpadStyleIndex : u8;
 } // namespace Core::HID
 
 class ConfigureInputPlayer : public QWidget {
@@ -134,10 +134,10 @@ private:
     void SetConnectableControllers();
 
     /// Gets the Controller Type for a given controller combobox index.
-    Core::HID::NpadType GetControllerTypeFromIndex(int index) const;
+    Core::HID::NpadStyleIndex GetControllerTypeFromIndex(int index) const;
 
     /// Gets the controller combobox index for a given Controller Type.
-    int GetIndexFromControllerType(Core::HID::NpadType type) const;
+    int GetIndexFromControllerType(Core::HID::NpadStyleIndex type) const;
 
     /// Update the available input devices.
     void UpdateInputDevices();
@@ -182,7 +182,7 @@ private:
     std::unique_ptr<QTimer> poll_timer;
 
     /// Stores a pair of "Connected Controllers" combobox index and Controller Type enum.
-    std::vector<std::pair<int, Core::HID::NpadType>> index_controller_type_pairs;
+    std::vector<std::pair<int, Core::HID::NpadStyleIndex>> index_controller_type_pairs;
 
     static constexpr int PLAYER_COUNT = 8;
     std::array<QCheckBox*, PLAYER_COUNT> player_connected_checkbox;
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 7e71a0f58a..e63c25e70d 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -147,7 +147,7 @@ void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType typ
         needs_redraw = true;
         break;
     case Core::HID::ControllerTriggerType::Type:
-        controller_type = controller->GetNpadType(true);
+        controller_type = controller->GetNpadStyleIndex(true);
         needs_redraw = true;
         break;
     case Core::HID::ControllerTriggerType::Color:
@@ -221,22 +221,22 @@ void PlayerControlPreview::paintEvent(QPaintEvent* event) {
     const QPointF center = rect().center();
 
     switch (controller_type) {
-    case Core::HID::NpadType::Handheld:
+    case Core::HID::NpadStyleIndex::Handheld:
         DrawHandheldController(p, center);
         break;
-    case Core::HID::NpadType::JoyconDual:
+    case Core::HID::NpadStyleIndex::JoyconDual:
         DrawDualController(p, center);
         break;
-    case Core::HID::NpadType::JoyconLeft:
+    case Core::HID::NpadStyleIndex::JoyconLeft:
         DrawLeftController(p, center);
         break;
-    case Core::HID::NpadType::JoyconRight:
+    case Core::HID::NpadStyleIndex::JoyconRight:
         DrawRightController(p, center);
         break;
-    case Core::HID::NpadType::GameCube:
+    case Core::HID::NpadStyleIndex::GameCube:
         DrawGCController(p, center);
         break;
-    case Core::HID::NpadType::ProController:
+    case Core::HID::NpadStyleIndex::ProController:
     default:
         DrawProController(p, center);
         break;
@@ -2394,7 +2394,7 @@ void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center,
 
 void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right) {
     using namespace Settings::NativeAnalog;
-    if (controller_type != Core::HID::NpadType::JoyconLeft) {
+    if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) {
         DrawJoystickProperties(p, center_right, stick_values[RStick].x.properties);
         p.setPen(colors.indicator);
         p.setBrush(colors.indicator);
@@ -2404,7 +2404,7 @@ void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPo
         DrawJoystickDot(p, center_right, stick_values[RStick], false);
     }
 
-    if (controller_type != Core::HID::NpadType::JoyconRight) {
+    if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) {
         DrawJoystickProperties(p, center_left, stick_values[LStick].x.properties);
         p.setPen(colors.indicator);
         p.setBrush(colors.indicator);
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index acc53a9e30..ee217f3c92 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -203,7 +203,7 @@ private:
     bool is_controller_set{};
     bool is_connected{};
     bool needs_redraw{};
-    Core::HID::NpadType controller_type;
+    Core::HID::NpadStyleIndex controller_type;
 
     bool mapping_active{};
     int blink_counter{};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 7c95851b37..a10522f5fb 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -841,7 +841,7 @@ void GMainWindow::InitializeWidgets() {
                                  tr("Handheld controller can't be used on docked mode. Pro "
                                     "controller will be selected."));
             handheld->Disconnect();
-            player_1->SetNpadType(Core::HID::NpadType::ProController);
+            player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
             player_1->Connect();
         }
 

From d14e74132ceaa8b5efef8a7d543cb50429cb4fb3 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Thu, 4 Nov 2021 13:08:30 -0600
Subject: [PATCH 69/88] settings: Fix controller preview not displaying the
 correct controller

---
 src/core/hid/emulated_controller.cpp                     | 4 ++--
 src/yuzu/configuration/configure_input_player_widget.cpp | 4 ++--
 src/yuzu/main.cpp                                        | 3 +++
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index a200992f2f..a9038e06f6 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -880,7 +880,7 @@ void EmulatedController::Disconnect() {
 }
 
 bool EmulatedController::IsConnected(bool get_temporary_value) const {
-    if (get_temporary_value) {
+    if (get_temporary_value && is_configuring) {
         return tmp_is_connected;
     }
     return is_connected;
@@ -897,7 +897,7 @@ NpadIdType EmulatedController::GetNpadIdType() const {
 }
 
 NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const {
-    if (get_temporary_value) {
+    if (get_temporary_value && is_configuring) {
         return tmp_npad_type;
     }
     return npad_type;
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index e63c25e70d..af65cf64cd 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -2394,7 +2394,7 @@ void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center,
 
 void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right) {
     using namespace Settings::NativeAnalog;
-    if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) {
+    if (center_right != QPointF(0, 0)) {
         DrawJoystickProperties(p, center_right, stick_values[RStick].x.properties);
         p.setPen(colors.indicator);
         p.setBrush(colors.indicator);
@@ -2404,7 +2404,7 @@ void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPo
         DrawJoystickDot(p, center_right, stick_values[RStick], false);
     }
 
-    if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) {
+    if (center_left != QPointF(0, 0)) {
         DrawJoystickProperties(p, center_left, stick_values[LStick].x.properties);
         p.setPen(colors.indicator);
         p.setBrush(colors.indicator);
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index a10522f5fb..baf7b38b41 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -230,6 +230,7 @@ GMainWindow::GMainWindow()
     ConnectWidgetEvents();
 
     system->HIDCore().ReloadInputDevices();
+    controller_dialog->refreshConfiguration();
 
     const auto branch_name = std::string(Common::g_scm_branch);
     const auto description = std::string(Common::g_scm_desc);
@@ -843,6 +844,7 @@ void GMainWindow::InitializeWidgets() {
             handheld->Disconnect();
             player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
             player_1->Connect();
+            controller_dialog->refreshConfiguration();
         }
 
         Settings::values.use_docked_mode.SetValue(!is_docked);
@@ -2744,6 +2746,7 @@ void GMainWindow::OnConfigure() {
     }
 
     UpdateStatusButtons();
+    controller_dialog->refreshConfiguration();
 }
 
 void GMainWindow::OnConfigureTas() {

From b21fcd952721af357d50d487ffba9580e5a6bf00 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Thu, 4 Nov 2021 14:43:08 -0600
Subject: [PATCH 70/88] service/hid: Add support for new controllers

---
 src/core/hid/hid_types.h                      |  2 +-
 src/core/hle/service/hid/controllers/npad.cpp | 31 ++++++++++++++++++-
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 7e4f6a804e..22177b5ed8 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -89,13 +89,13 @@ enum class NpadStyleIndex : u8 {
     None = 0,
     ProController = 3,
     Handheld = 4,
+    HandheldNES = 4,
     JoyconDual = 5,
     JoyconLeft = 6,
     JoyconRight = 7,
     GameCube = 8,
     Pokeball = 9,
     NES = 10,
-    HandheldNES = 11,
     SNES = 12,
     N64 = 13,
     SegaGenesis = 14,
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index e4a3d91634..fcc36bbc16 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -221,7 +221,6 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         break;
     case Core::HID::NpadStyleIndex::GameCube:
         shared_memory.style_set.gamecube.Assign(1);
-        // The GC Controller behaves like a wired Pro Controller
         shared_memory.device_type.fullkey.Assign(1);
         shared_memory.system_properties.is_vertical.Assign(1);
         shared_memory.system_properties.use_plus.Assign(1);
@@ -231,6 +230,24 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.device_type.palma.Assign(1);
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
         break;
+    case Core::HID::NpadStyleIndex::NES:
+        shared_memory.style_set.lark.Assign(1);
+        shared_memory.device_type.fullkey.Assign(1);
+        break;
+    case Core::HID::NpadStyleIndex::SNES:
+        shared_memory.style_set.lucia.Assign(1);
+        shared_memory.device_type.fullkey.Assign(1);
+        shared_memory.applet_footer.type = AppletFooterUiType::Lucia;
+        break;
+    case Core::HID::NpadStyleIndex::N64:
+        shared_memory.style_set.lagoon.Assign(1);
+        shared_memory.device_type.fullkey.Assign(1);
+        shared_memory.applet_footer.type = AppletFooterUiType::Lagon;
+        break;
+    case Core::HID::NpadStyleIndex::SegaGenesis:
+        shared_memory.style_set.lager.Assign(1);
+        shared_memory.device_type.fullkey.Assign(1);
+        break;
     default:
         break;
     }
@@ -431,6 +448,10 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             UNREACHABLE();
             break;
         case Core::HID::NpadStyleIndex::ProController:
+        case Core::HID::NpadStyleIndex::NES:
+        case Core::HID::NpadStyleIndex::SNES:
+        case Core::HID::NpadStyleIndex::N64:
+        case Core::HID::NpadStyleIndex::SegaGenesis:
             pad_state.connection_status.raw = 0;
             pad_state.connection_status.is_connected.Assign(1);
             pad_state.connection_status.is_wired.Assign(1);
@@ -1108,6 +1129,14 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
             return style.gamecube;
         case Core::HID::NpadStyleIndex::Pokeball:
             return style.palma;
+        case Core::HID::NpadStyleIndex::NES:
+            return style.lark;
+        case Core::HID::NpadStyleIndex::SNES:
+            return style.lucia;
+        case Core::HID::NpadStyleIndex::N64:
+            return style.lagoon;
+        case Core::HID::NpadStyleIndex::SegaGenesis:
+            return style.lager;
         default:
             return false;
         }

From 690013b342e6d9a9561017b2e94f42acfde25147 Mon Sep 17 00:00:00 2001
From: Levi Behunin <l3ehunin@gmail.com>
Date: Thu, 4 Nov 2021 16:09:57 -0600
Subject: [PATCH 71/88]  UI nits Set top margin to 6 on Right Stick, LeftStick,
 Face Buttons, D-Pad. Change property on Input Device QComboBox from
 minimumSize to minimumContentsLength.

---
 src/yuzu/configuration/configure_input_player.ui | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui
index 958a892290..756a414b58 100644
--- a/src/yuzu/configuration/configure_input_player.ui
+++ b/src/yuzu/configuration/configure_input_player.ui
@@ -117,11 +117,8 @@
           </property>
           <item>
            <widget class="QComboBox" name="comboDevices">
-            <property name="minimumSize">
-             <size>
-              <width>0</width>
-              <height>21</height>
-             </size>
+            <property name="minimumContentsLength">
+             <number>60</number>
             </property>
            </widget>
           </item>
@@ -307,7 +304,7 @@
                <number>3</number>
               </property>
               <property name="topMargin">
-               <number>0</number>
+               <number>6</number>
               </property>
               <property name="rightMargin">
                <number>3</number>
@@ -883,7 +880,7 @@
                <number>3</number>
               </property>
               <property name="topMargin">
-               <number>0</number>
+               <number>6</number>
               </property>
               <property name="rightMargin">
                <number>3</number>
@@ -2186,7 +2183,7 @@
                <number>3</number>
               </property>
               <property name="topMargin">
-               <number>0</number>
+               <number>6</number>
               </property>
               <property name="rightMargin">
                <number>3</number>
@@ -2535,7 +2532,7 @@
                <number>3</number>
               </property>
               <property name="topMargin">
-               <number>0</number>
+               <number>6</number>
               </property>
               <property name="rightMargin">
                <number>3</number>

From e7eee36d52259321b938c350cb37a3b115953229 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Thu, 4 Nov 2021 19:05:58 -0600
Subject: [PATCH 72/88] service/hid: Remove includes of core.h and settings.h

---
 src/core/hid/emulated_console.cpp                 |  1 +
 src/core/hid/emulated_console.h                   |  1 -
 src/core/hid/emulated_devices.h                   |  3 +--
 .../service/hid/controllers/console_sixaxis.cpp   |  8 ++++----
 .../hle/service/hid/controllers/console_sixaxis.h |  8 ++++++--
 .../service/hid/controllers/controller_base.cpp   |  2 +-
 .../hle/service/hid/controllers/controller_base.h |  8 ++++----
 .../hle/service/hid/controllers/debug_pad.cpp     |  6 +++---
 src/core/hle/service/hid/controllers/debug_pad.h  |  3 +--
 src/core/hle/service/hid/controllers/gesture.cpp  |  5 ++---
 src/core/hle/service/hid/controllers/gesture.h    |  2 +-
 src/core/hle/service/hid/controllers/keyboard.cpp |  6 +++---
 src/core/hle/service/hid/controllers/keyboard.h   |  3 +--
 src/core/hle/service/hid/controllers/mouse.cpp    |  5 ++---
 src/core/hle/service/hid/controllers/mouse.h      |  3 +--
 src/core/hle/service/hid/controllers/npad.cpp     | 15 +++++++--------
 src/core/hle/service/hid/controllers/npad.h       |  3 +--
 src/core/hle/service/hid/controllers/stubbed.cpp  |  3 ++-
 src/core/hle/service/hid/controllers/stubbed.h    |  2 +-
 .../hle/service/hid/controllers/touchscreen.cpp   |  7 +++++--
 .../hle/service/hid/controllers/touchscreen.h     |  8 +++++---
 src/core/hle/service/hid/controllers/xpad.cpp     |  3 ++-
 src/core/hle/service/hid/controllers/xpad.h       |  2 +-
 src/core/hle/service/hid/hid.cpp                  |  1 +
 src/core/hle/service/hid/hid.h                    |  4 ++--
 src/yuzu/bootmanager.cpp                          |  1 -
 src/yuzu/debugger/controller.cpp                  | 10 +++++-----
 src/yuzu/debugger/controller.h                    |  9 +++------
 src/yuzu/main.cpp                                 |  2 +-
 29 files changed, 67 insertions(+), 67 deletions(-)

diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index b51c72eae0..864481f527 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -2,6 +2,7 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included
 
+#include "common/settings.h"
 #include "core/hid/emulated_console.h"
 #include "core/hid/input_converter.h"
 
diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h
index 9aec482a6d..25c183eee5 100644
--- a/src/core/hid/emulated_console.h
+++ b/src/core/hid/emulated_console.h
@@ -15,7 +15,6 @@
 #include "common/param_package.h"
 #include "common/point.h"
 #include "common/quaternion.h"
-#include "common/settings.h"
 #include "common/vector_math.h"
 #include "core/hid/hid_types.h"
 #include "core/hid/motion_input.h"
diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h
index 418b2f9b55..d49d6d78a5 100644
--- a/src/core/hid/emulated_devices.h
+++ b/src/core/hid/emulated_devices.h
@@ -15,7 +15,6 @@
 #include "common/param_package.h"
 #include "common/settings.h"
 #include "core/hid/hid_types.h"
-#include "core/hid/motion_input.h"
 
 namespace Core::HID {
 
@@ -103,7 +102,7 @@ public:
     /// Reverts any mapped changes made that weren't saved
     void RestoreConfig();
 
-    /// Returns the current mapped motion device
+    /// Returns the current mapped mouse button device
     Common::ParamPackage GetMouseButtonParam(std::size_t index) const;
 
     /**
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
index 2bebcf0d0b..ea7e8f18fd 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
@@ -3,17 +3,17 @@
 // Refer to the license.txt file included.
 
 #include "common/settings.h"
-#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/hid/emulated_console.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/service/hid/controllers/console_sixaxis.h"
 
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
 
-Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::System& system_)
-    : ControllerBase{system_} {
-    console = system.HIDCore().GetEmulatedConsole();
+Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_)
+    : ControllerBase{hid_core_} {
+    console = hid_core.GetEmulatedConsole();
 }
 
 Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default;
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h
index 95729e6b23..7c92413e8d 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.h
@@ -5,16 +5,20 @@
 #pragma once
 
 #include <array>
+
 #include "common/common_types.h"
 #include "common/quaternion.h"
-#include "core/hid/hid_core.h"
 #include "core/hid/hid_types.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
 
+namespace Core::HID {
+class EmulatedConsole;
+} // namespace Core::HID
+
 namespace Service::HID {
 class Controller_ConsoleSixAxis final : public ControllerBase {
 public:
-    explicit Controller_ConsoleSixAxis(Core::System& system_);
+    explicit Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_);
     ~Controller_ConsoleSixAxis() override;
 
     // Called when the controller is initialized
diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp
index 74a3947842..788ae9ae7a 100644
--- a/src/core/hle/service/hid/controllers/controller_base.cpp
+++ b/src/core/hle/service/hid/controllers/controller_base.cpp
@@ -6,7 +6,7 @@
 
 namespace Service::HID {
 
-ControllerBase::ControllerBase(Core::System& system_) : system(system_) {}
+ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {}
 ControllerBase::~ControllerBase() = default;
 
 void ControllerBase::ActivateController() {
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h
index 4ba2eda1a9..8125bbc842 100644
--- a/src/core/hle/service/hid/controllers/controller_base.h
+++ b/src/core/hle/service/hid/controllers/controller_base.h
@@ -11,14 +11,14 @@ namespace Core::Timing {
 class CoreTiming;
 }
 
-namespace Core {
-class System;
+namespace Core::HID {
+class HIDCore;
 }
 
 namespace Service::HID {
 class ControllerBase {
 public:
-    explicit ControllerBase(Core::System& system_);
+    explicit ControllerBase(Core::HID::HIDCore& hid_core_);
     virtual ~ControllerBase();
 
     // Called when the controller is initialized
@@ -44,6 +44,6 @@ public:
 protected:
     bool is_activated{false};
 
-    Core::System& system;
+    Core::HID::HIDCore& hid_core;
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index 86b95f2c8b..6a6fb9cab3 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -5,7 +5,6 @@
 #include <cstring>
 #include "common/common_types.h"
 #include "common/settings.h"
-#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/hid/emulated_controller.h"
 #include "core/hid/hid_core.h"
@@ -15,8 +14,9 @@
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
 
-Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} {
-    controller = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Other);
+Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_)
+    : ControllerBase{hid_core_} {
+    controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
 }
 
 Controller_DebugPad::~Controller_DebugPad() = default;
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index bd0f15eaa6..15b3afb7a3 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -8,7 +8,6 @@
 #include "common/bit_field.h"
 #include "common/common_funcs.h"
 #include "common/common_types.h"
-#include "common/settings.h"
 #include "common/swap.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
 #include "core/hle/service/hid/ring_lifo.h"
@@ -22,7 +21,7 @@ struct AnalogStickState;
 namespace Service::HID {
 class Controller_DebugPad final : public ControllerBase {
 public:
-    explicit Controller_DebugPad(Core::System& system_);
+    explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_);
     ~Controller_DebugPad() override;
 
     // Called when the controller is initialized
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 00df50f323..fe895c4f67 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -5,7 +5,6 @@
 #include "common/logging/log.h"
 #include "common/math_util.h"
 #include "common/settings.h"
-#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/frontend/emu_window.h"
 #include "core/hid/hid_core.h"
@@ -25,8 +24,8 @@ constexpr f32 Square(s32 num) {
     return static_cast<f32>(num * num);
 }
 
-Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) {
-    console = system.HIDCore().GetEmulatedConsole();
+Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_) : ControllerBase(hid_core_) {
+    console = hid_core.GetEmulatedConsole();
 }
 Controller_Gesture::~Controller_Gesture() = default;
 
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 9bffde438e..f924464e0d 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -15,7 +15,7 @@
 namespace Service::HID {
 class Controller_Gesture final : public ControllerBase {
 public:
-    explicit Controller_Gesture(Core::System& system_);
+    explicit Controller_Gesture(Core::HID::HIDCore& hid_core_);
     ~Controller_Gesture() override;
 
     // Called when the controller is initialized
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index acea68e24e..1dc219bf59 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -5,7 +5,6 @@
 #include <cstring>
 #include "common/common_types.h"
 #include "common/settings.h"
-#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/hid/emulated_devices.h"
 #include "core/hid/hid_core.h"
@@ -14,8 +13,9 @@
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
 
-Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} {
-    emulated_devices = system.HIDCore().GetEmulatedDevices();
+Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_)
+    : ControllerBase{hid_core_} {
+    emulated_devices = hid_core.GetEmulatedDevices();
 }
 
 Controller_Keyboard::~Controller_Keyboard() = default;
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index aba4f123ec..ec5dd607cb 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -8,7 +8,6 @@
 #include "common/bit_field.h"
 #include "common/common_funcs.h"
 #include "common/common_types.h"
-#include "common/settings.h"
 #include "common/swap.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
 #include "core/hle/service/hid/ring_lifo.h"
@@ -22,7 +21,7 @@ struct KeyboardKey;
 namespace Service::HID {
 class Controller_Keyboard final : public ControllerBase {
 public:
-    explicit Controller_Keyboard(Core::System& system_);
+    explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_);
     ~Controller_Keyboard() override;
 
     // Called when the controller is initialized
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 21f7e48bb6..83e69ca94f 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -4,7 +4,6 @@
 
 #include <cstring>
 #include "common/common_types.h"
-#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/frontend/emu_window.h"
 #include "core/hid/emulated_devices.h"
@@ -14,8 +13,8 @@
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
 
-Controller_Mouse::Controller_Mouse(Core::System& system_) : ControllerBase{system_} {
-    emulated_devices = system.HIDCore().GetEmulatedDevices();
+Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {
+    emulated_devices = hid_core.GetEmulatedDevices();
 }
 
 Controller_Mouse::~Controller_Mouse() = default;
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index ce868a2471..25017f1173 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -7,7 +7,6 @@
 #include <array>
 #include "common/bit_field.h"
 #include "common/common_types.h"
-#include "common/settings.h"
 #include "common/swap.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
 #include "core/hle/service/hid/ring_lifo.h"
@@ -20,7 +19,7 @@ struct MouseState;
 namespace Service::HID {
 class Controller_Mouse final : public ControllerBase {
 public:
-    explicit Controller_Mouse(Core::System& system_);
+    explicit Controller_Mouse(Core::HID::HIDCore& hid_core_);
     ~Controller_Mouse() override;
 
     // Called when the controller is initialized
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index fcc36bbc16..b97e575f39 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -10,7 +10,6 @@
 #include "common/common_types.h"
 #include "common/logging/log.h"
 #include "common/settings.h"
-#include "core/core.h"
 #include "core/core_timing.h"
 #include "core/hid/emulated_controller.h"
 #include "core/hid/hid_core.h"
@@ -97,12 +96,12 @@ bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) {
            device_handle.device_index < DeviceIndex::MaxDeviceIndex;
 }
 
-Controller_NPad::Controller_NPad(Core::System& system_,
+Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
                                  KernelHelpers::ServiceContext& service_context_)
-    : ControllerBase{system_}, service_context{service_context_} {
+    : ControllerBase{hid_core_}, service_context{service_context_} {
     for (std::size_t i = 0; i < controller_data.size(); ++i) {
         auto& controller = controller_data[i];
-        controller.device = system.HIDCore().GetEmulatedControllerByIndex(i);
+        controller.device = hid_core.GetEmulatedControllerByIndex(i);
         controller.vibration[Core::HID::DeviceIndex::LeftIndex].latest_vibration_value =
             DEFAULT_VIBRATION_VALUE;
         controller.vibration[Core::HID::DeviceIndex::RightIndex].latest_vibration_value =
@@ -284,7 +283,7 @@ void Controller_NPad::OnInit() {
             service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
     }
 
-    if (system.HIDCore().GetSupportedStyleTag().raw == 0) {
+    if (hid_core.GetSupportedStyleTag().raw == 0) {
         // We want to support all controllers
         Core::HID::NpadStyleTag style{};
         style.handheld.Assign(1);
@@ -294,7 +293,7 @@ void Controller_NPad::OnInit() {
         style.fullkey.Assign(1);
         style.gamecube.Assign(1);
         style.palma.Assign(1);
-        system.HIDCore().SetSupportedStyleTag(style);
+        hid_core.SetSupportedStyleTag(style);
     }
 
     supported_npad_id_types.resize(npad_id_list.size());
@@ -678,11 +677,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
 }
 
 void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
-    system.HIDCore().SetSupportedStyleTag(style_set);
+    hid_core.SetSupportedStyleTag(style_set);
 }
 
 Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
-    return system.HIDCore().GetSupportedStyleTag();
+    return hid_core.GetSupportedStyleTag();
 }
 
 void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 512fb5afcd..a996755ed5 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -11,7 +11,6 @@
 #include "common/bit_field.h"
 #include "common/common_types.h"
 #include "common/quaternion.h"
-#include "common/settings.h"
 #include "core/hid/hid_types.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
 #include "core/hle/service/hid/ring_lifo.h"
@@ -37,7 +36,7 @@ constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this?
 
 class Controller_NPad final : public ControllerBase {
 public:
-    explicit Controller_NPad(Core::System& system_,
+    explicit Controller_NPad(Core::HID::HIDCore& hid_core_,
                              KernelHelpers::ServiceContext& service_context_);
     ~Controller_NPad() override;
 
diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp
index a8c93909dd..b7d7a57560 100644
--- a/src/core/hle/service/hid/controllers/stubbed.cpp
+++ b/src/core/hle/service/hid/controllers/stubbed.cpp
@@ -5,11 +5,12 @@
 #include <cstring>
 #include "common/common_types.h"
 #include "core/core_timing.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/service/hid/controllers/stubbed.h"
 
 namespace Service::HID {
 
-Controller_Stubbed::Controller_Stubbed(Core::System& system_) : ControllerBase{system_} {}
+Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {}
 Controller_Stubbed::~Controller_Stubbed() = default;
 
 void Controller_Stubbed::OnInit() {}
diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h
index 10aecad4ca..0044a4efaa 100644
--- a/src/core/hle/service/hid/controllers/stubbed.h
+++ b/src/core/hle/service/hid/controllers/stubbed.h
@@ -10,7 +10,7 @@
 namespace Service::HID {
 class Controller_Stubbed final : public ControllerBase {
 public:
-    explicit Controller_Stubbed(Core::System& system_);
+    explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_);
     ~Controller_Stubbed() override;
 
     // Called when the controller is initialized
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index 9ae2bf2b15..48978e5c6a 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -10,13 +10,16 @@
 #include "core/core.h"
 #include "core/core_timing.h"
 #include "core/frontend/emu_window.h"
+#include "core/hid/emulated_console.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/service/hid/controllers/touchscreen.h"
 
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
 
-Controller_Touchscreen::Controller_Touchscreen(Core::System& system_) : ControllerBase{system_} {
-    console = system.HIDCore().GetEmulatedConsole();
+Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_)
+    : ControllerBase{hid_core_} {
+    console = hid_core.GetEmulatedConsole();
 }
 
 Controller_Touchscreen::~Controller_Touchscreen() = default;
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index 50dadd25f5..135c2bf138 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -9,12 +9,14 @@
 #include "common/common_types.h"
 #include "common/point.h"
 #include "common/swap.h"
-#include "core/hid/emulated_console.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/ring_lifo.h"
 
+namespace Core::HID {
+class EmulatedConsole;
+} // namespace Core::HID
+
 namespace Service::HID {
 class Controller_Touchscreen final : public ControllerBase {
 public:
@@ -34,7 +36,7 @@ public:
     static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17,
                   "TouchScreenConfigurationForNx is an invalid size");
 
-    explicit Controller_Touchscreen(Core::System& system_);
+    explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_);
     ~Controller_Touchscreen() override;
 
     // Called when the controller is initialized
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp
index a2ed1e7c2c..e4da164665 100644
--- a/src/core/hle/service/hid/controllers/xpad.cpp
+++ b/src/core/hle/service/hid/controllers/xpad.cpp
@@ -5,12 +5,13 @@
 #include <cstring>
 #include "common/common_types.h"
 #include "core/core_timing.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/service/hid/controllers/xpad.h"
 
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00;
 
-Controller_XPad::Controller_XPad(Core::System& system_) : ControllerBase{system_} {}
+Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {}
 Controller_XPad::~Controller_XPad() = default;
 
 void Controller_XPad::OnInit() {}
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index 75e0d29116..54dae0be1b 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -15,7 +15,7 @@
 namespace Service::HID {
 class Controller_XPad final : public ControllerBase {
 public:
-    explicit Controller_XPad(Core::System& system_);
+    explicit Controller_XPad(Core::HID::HIDCore& hid_core_);
     ~Controller_XPad() override;
 
     // Called when the controller is initialized
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 648e69de9f..96e8fb7e1c 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -8,6 +8,7 @@
 #include "common/settings.h"
 #include "core/core.h"
 #include "core/core_timing.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_shared_memory.h"
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 2e0c33c1cf..973e6a8acf 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -60,12 +60,12 @@ public:
 private:
     template <typename T>
     void MakeController(HidController controller) {
-        controllers[static_cast<std::size_t>(controller)] = std::make_unique<T>(system);
+        controllers[static_cast<std::size_t>(controller)] = std::make_unique<T>(system.HIDCore());
     }
     template <typename T>
     void MakeControllerWithServiceContext(HidController controller) {
         controllers[static_cast<std::size_t>(controller)] =
-            std::make_unique<T>(system, service_context);
+            std::make_unique<T>(system.HIDCore(), service_context);
     }
 
     void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 4b3cd9f3e4..3c5590a017 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -27,7 +27,6 @@
 
 #include "common/assert.h"
 #include "common/microprofile.h"
-#include "common/param_package.h"
 #include "common/scm_rev.h"
 #include "common/scope_exit.h"
 #include "common/settings.h"
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
index aaca494b8d..6b834c42e9 100644
--- a/src/yuzu/debugger/controller.cpp
+++ b/src/yuzu/debugger/controller.cpp
@@ -6,17 +6,17 @@
 #include <QLayout>
 #include <QString>
 #include "common/settings.h"
-#include "core/core.h"
 #include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
 #include "input_common/drivers/tas_input.h"
 #include "input_common/main.h"
 #include "yuzu/configuration/configure_input_player_widget.h"
 #include "yuzu/debugger/controller.h"
 
-ControllerDialog::ControllerDialog(Core::System& system_,
+ControllerDialog::ControllerDialog(Core::HID::HIDCore& hid_core_,
                                    std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
                                    QWidget* parent)
-    : QWidget(parent, Qt::Dialog), system{system_}, input_subsystem{input_subsystem_} {
+    : QWidget(parent, Qt::Dialog), hid_core{hid_core_}, input_subsystem{input_subsystem_} {
     setObjectName(QStringLiteral("Controller"));
     setWindowTitle(tr("Controller P1"));
     resize(500, 350);
@@ -41,8 +41,8 @@ ControllerDialog::ControllerDialog(Core::System& system_,
 
 void ControllerDialog::refreshConfiguration() {
     UnloadController();
-    auto* player_1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
-    auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+    auto* player_1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
+    auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
     // Display the correct controller
     controller = handheld->IsConnected() ? handheld : player_1;
 
diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h
index d08643baaf..52cea33265 100644
--- a/src/yuzu/debugger/controller.h
+++ b/src/yuzu/debugger/controller.h
@@ -15,11 +15,8 @@ namespace InputCommon {
 class InputSubsystem;
 }
 
-namespace Core {
-class System;
-}
-
 namespace Core::HID {
+class HIDCore;
 class EmulatedController;
 enum class ControllerTriggerType;
 } // namespace Core::HID
@@ -28,7 +25,7 @@ class ControllerDialog : public QWidget {
     Q_OBJECT
 
 public:
-    explicit ControllerDialog(Core::System& system_,
+    explicit ControllerDialog(Core::HID::HIDCore& hid_core_,
                               std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
                               QWidget* parent = nullptr);
 
@@ -55,6 +52,6 @@ private:
 
     QAction* toggle_view_action = nullptr;
     PlayerControlPreview* widget;
-    Core::System& system;
+    Core::HID::HIDCore& hid_core;
     std::shared_ptr<InputCommon::InputSubsystem> input_subsystem;
 };
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index baf7b38b41..cd8ea221d7 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -928,7 +928,7 @@ void GMainWindow::InitializeDebugWidgets() {
     waitTreeWidget->hide();
     debug_menu->addAction(waitTreeWidget->toggleViewAction());
 
-    controller_dialog = new ControllerDialog(*system, input_subsystem, this);
+    controller_dialog = new ControllerDialog(system->HIDCore(), input_subsystem, this);
     controller_dialog->hide();
     debug_menu->addAction(controller_dialog->toggleViewAction());
 

From a17550be9855a32a62a1358b23babab929a39cbb Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Thu, 4 Nov 2021 21:54:22 -0600
Subject: [PATCH 73/88] settings: Remove includes of core.h

---
 .../configure_debug_controller.cpp            |  9 ++---
 .../configure_debug_controller.h              |  7 ++--
 src/yuzu/configuration/configure_dialog.cpp   |  2 +-
 src/yuzu/configuration/configure_input.cpp    | 29 ++++++++-------
 src/yuzu/configuration/configure_input.h      |  3 +-
 .../configuration/configure_input_player.cpp  | 35 +++++++++----------
 .../configuration/configure_input_player.h    | 16 +++------
 .../configure_input_player_widget.cpp         |  3 +-
 .../configure_input_player_widget.h           |  4 +--
 .../configure_input_profile_dialog.cpp        |  4 +--
 10 files changed, 55 insertions(+), 57 deletions(-)

diff --git a/src/yuzu/configuration/configure_debug_controller.cpp b/src/yuzu/configuration/configure_debug_controller.cpp
index 31ec483840..9a8de92a1e 100644
--- a/src/yuzu/configuration/configure_debug_controller.cpp
+++ b/src/yuzu/configuration/configure_debug_controller.cpp
@@ -2,17 +2,18 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include "core/core.h"
+#include "core/hid/hid_core.h"
 #include "ui_configure_debug_controller.h"
 #include "yuzu/configuration/configure_debug_controller.h"
 #include "yuzu/configuration/configure_input_player.h"
 
 ConfigureDebugController::ConfigureDebugController(QWidget* parent,
                                                    InputCommon::InputSubsystem* input_subsystem,
-                                                   InputProfiles* profiles, Core::System& system)
+                                                   InputProfiles* profiles,
+                                                   Core::HID::HIDCore& hid_core, bool is_powered_on)
     : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()),
-      debug_controller(
-          new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, system, true)) {
+      debug_controller(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles,
+                                                hid_core, is_powered_on, true)) {
     ui->setupUi(this);
 
     ui->controllerLayout->addWidget(debug_controller);
diff --git a/src/yuzu/configuration/configure_debug_controller.h b/src/yuzu/configuration/configure_debug_controller.h
index 6e17c5aa07..d716edbc24 100644
--- a/src/yuzu/configuration/configure_debug_controller.h
+++ b/src/yuzu/configuration/configure_debug_controller.h
@@ -13,8 +13,8 @@ class ConfigureInputPlayer;
 
 class InputProfiles;
 
-namespace Core {
-class System;
+namespace Core::HID {
+class HIDCore;
 }
 
 namespace InputCommon {
@@ -30,7 +30,8 @@ class ConfigureDebugController : public QDialog {
 
 public:
     explicit ConfigureDebugController(QWidget* parent, InputCommon::InputSubsystem* input_subsystem,
-                                      InputProfiles* profiles, Core::System& system);
+                                      InputProfiles* profiles, Core::HID::HIDCore& hid_core,
+                                      bool is_powered_on);
     ~ConfigureDebugController() override;
 
     void ApplyConfiguration();
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 1eb9d70e53..642a5f9660 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -74,7 +74,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry,
     hotkeys_tab->Populate(registry);
     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
 
-    input_tab->Initialize(input_subsystem, system_);
+    input_tab->Initialize(input_subsystem);
 
     general_tab->SetResetCallback([&] { this->close(); });
 
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index dece27fdeb..99450bc7d1 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -10,6 +10,8 @@
 #include <QTimer>
 
 #include "core/core.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applet_ae.h"
 #include "core/hle/service/am/applet_oe.h"
@@ -73,25 +75,27 @@ ConfigureInput::ConfigureInput(Core::System& system_, QWidget* parent)
 
 ConfigureInput::~ConfigureInput() = default;
 
-void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, Core::System& system,
+void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
                                 std::size_t max_players) {
+    const bool is_powered_on = system.IsPoweredOn();
+    auto& hid_core = system.HIDCore();
     player_controllers = {
         new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem, profiles.get(),
-                                 system),
+                                 hid_core, is_powered_on),
         new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem, profiles.get(),
-                                 system),
+                                 hid_core, is_powered_on),
         new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem, profiles.get(),
-                                 system),
+                                 hid_core, is_powered_on),
         new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem, profiles.get(),
-                                 system),
+                                 hid_core, is_powered_on),
         new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem, profiles.get(),
-                                 system),
+                                 hid_core, is_powered_on),
         new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem, profiles.get(),
-                                 system),
+                                 hid_core, is_powered_on),
         new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem, profiles.get(),
-                                 system),
+                                 hid_core, is_powered_on),
         new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem, profiles.get(),
-                                 system),
+                                 hid_core, is_powered_on),
     };
 
     player_tabs = {
@@ -147,10 +151,11 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, Co
     advanced = new ConfigureInputAdvanced(this);
     ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced));
     ui->tabAdvanced->layout()->addWidget(advanced);
+
     connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog,
-            [this, input_subsystem, &system] {
-                CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem,
-                                                              profiles.get(), system);
+            [this, input_subsystem, &hid_core, is_powered_on] {
+                CallConfigureDialog<ConfigureDebugController>(
+                    *this, input_subsystem, profiles.get(), hid_core, is_powered_on);
             });
     connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] {
         CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem);
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h
index 6e5edad589..4cafa3dab7 100644
--- a/src/yuzu/configuration/configure_input.h
+++ b/src/yuzu/configuration/configure_input.h
@@ -42,8 +42,7 @@ public:
     ~ConfigureInput() override;
 
     /// Initializes the input dialog with the given input subsystem.
-    void Initialize(InputCommon::InputSubsystem* input_subsystem_, Core::System& system,
-                    std::size_t max_players = 8);
+    void Initialize(InputCommon::InputSubsystem* input_subsystem_, std::size_t max_players = 8);
 
     /// Save all button configurations to settings file.
     void ApplyConfiguration();
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 95a9b86146..76f55eb54b 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -12,7 +12,6 @@
 #include <QMessageBox>
 #include <QTimer>
 #include "common/param_package.h"
-#include "core/core.h"
 #include "core/hid/emulated_controller.h"
 #include "core/hid/hid_core.h"
 #include "core/hid/hid_types.h"
@@ -134,18 +133,17 @@ QString ConfigureInputPlayer::AnalogToText(const Common::ParamPackage& param,
 ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index,
                                            QWidget* bottom_row,
                                            InputCommon::InputSubsystem* input_subsystem_,
-                                           InputProfiles* profiles_, Core::System& system_,
-                                           bool debug)
+                                           InputProfiles* profiles_, Core::HID::HIDCore& hid_core_,
+                                           bool is_powered_on_, bool debug)
     : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index),
-      debug(debug), input_subsystem{input_subsystem_}, profiles(profiles_),
-      timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()),
-      bottom_row(bottom_row), system{system_} {
-
+      debug(debug), is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_},
+      profiles(profiles_), timeout_timer(std::make_unique<QTimer>()),
+      poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row), hid_core{hid_core_} {
     if (player_index == 0) {
         auto* emulated_controller_p1 =
-            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+            hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
         auto* emulated_controller_hanheld =
-            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+            hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
         emulated_controller_p1->SaveCurrentConfig();
         emulated_controller_p1->EnableConfiguration();
         emulated_controller_hanheld->SaveCurrentConfig();
@@ -157,7 +155,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
             emulated_controller = emulated_controller_p1;
         }
     } else {
-        emulated_controller = system_.HIDCore().GetEmulatedControllerByIndex(player_index);
+        emulated_controller = hid_core.GetEmulatedControllerByIndex(player_index);
         emulated_controller->SaveCurrentConfig();
         emulated_controller->EnableConfiguration();
     }
@@ -487,9 +485,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
 
                 if (player_index == 0) {
                     auto* emulated_controller_p1 =
-                        system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+                        hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
                     auto* emulated_controller_hanheld =
-                        system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+                        hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
                     bool is_connected = emulated_controller->IsConnected(true);
 
                     emulated_controller_p1->SetNpadStyleIndex(type);
@@ -547,9 +545,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
 ConfigureInputPlayer::~ConfigureInputPlayer() {
     if (player_index == 0) {
         auto* emulated_controller_p1 =
-            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+            hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
         auto* emulated_controller_hanheld =
-            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+            hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
         emulated_controller_p1->DisableConfiguration();
         emulated_controller_hanheld->DisableConfiguration();
     } else {
@@ -560,9 +558,9 @@ ConfigureInputPlayer::~ConfigureInputPlayer() {
 void ConfigureInputPlayer::ApplyConfiguration() {
     if (player_index == 0) {
         auto* emulated_controller_p1 =
-            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+            hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
         auto* emulated_controller_hanheld =
-            system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+            hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
         emulated_controller_p1->DisableConfiguration();
         emulated_controller_p1->SaveCurrentConfig();
         emulated_controller_p1->EnableConfiguration();
@@ -846,12 +844,11 @@ void ConfigureInputPlayer::SetConnectableControllers() {
         }
     };
 
-    if (!system.IsPoweredOn()) {
+    if (!is_powered_on) {
         add_controllers(true);
-        return;
     }
 
-    add_controllers(false, system.HIDCore().GetSupportedStyleTag());
+    add_controllers(false, hid_core.GetSupportedStyleTag());
 }
 
 Core::HID::NpadStyleIndex ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const {
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index 7bff4b1963..47df6b3d33 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -29,10 +29,6 @@ class QWidget;
 
 class InputProfiles;
 
-namespace Core {
-class System;
-}
-
 namespace InputCommon {
 class InputSubsystem;
 }
@@ -45,11 +41,8 @@ namespace Ui {
 class ConfigureInputPlayer;
 }
 
-namespace Core {
-class System;
-}
-
 namespace Core::HID {
+class HIDCore;
 class EmulatedController;
 enum class NpadStyleIndex : u8;
 } // namespace Core::HID
@@ -60,8 +53,8 @@ class ConfigureInputPlayer : public QWidget {
 public:
     explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row,
                                   InputCommon::InputSubsystem* input_subsystem_,
-                                  InputProfiles* profiles_, Core::System& system_,
-                                  bool debug = false);
+                                  InputProfiles* profiles_, Core::HID::HIDCore& hid_core_,
+                                  bool is_powered_on_, bool debug = false);
     ~ConfigureInputPlayer() override;
 
     /// Save all button configurations to settings file.
@@ -173,6 +166,7 @@ private:
 
     std::size_t player_index;
     bool debug;
+    bool is_powered_on;
 
     InputCommon::InputSubsystem* input_subsystem;
 
@@ -228,5 +222,5 @@ private:
     /// parent of the widget to this widget (but thats fine).
     QWidget* bottom_row;
 
-    Core::System& system;
+    Core::HID::HIDCore& hid_core;
 };
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index af65cf64cd..ff40f57f55 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -6,7 +6,8 @@
 #include <QMenu>
 #include <QPainter>
 #include <QTimer>
-#include "core/core.h"
+
+#include "core/hid/emulated_controller.h"
 #include "yuzu/configuration/configure_input_player_widget.h"
 
 PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) {
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index ee217f3c92..4cd5c3be05 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -7,10 +7,10 @@
 #include <array>
 #include <QFrame>
 #include <QPointer>
+
 #include "common/input.h"
-#include "common/settings.h"
+#include "common/settings_input.h"
 #include "core/hid/emulated_controller.h"
-#include "core/hid/hid_core.h"
 #include "core/hid/hid_types.h"
 
 class QLabel;
diff --git a/src/yuzu/configuration/configure_input_profile_dialog.cpp b/src/yuzu/configuration/configure_input_profile_dialog.cpp
index cd5a88cea4..17bbe6b61f 100644
--- a/src/yuzu/configuration/configure_input_profile_dialog.cpp
+++ b/src/yuzu/configuration/configure_input_profile_dialog.cpp
@@ -11,8 +11,8 @@ ConfigureInputProfileDialog::ConfigureInputProfileDialog(
     QWidget* parent, InputCommon::InputSubsystem* input_subsystem, InputProfiles* profiles,
     Core::System& system)
     : QDialog(parent), ui(std::make_unique<Ui::ConfigureInputProfileDialog>()),
-      profile_widget(
-          new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, system, false)) {
+      profile_widget(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles,
+                                              system.HIDCore(), system.IsPoweredOn(), false)) {
     ui->setupUi(this);
 
     ui->controllerLayout->addWidget(profile_widget);

From 71f9b90dd90c442425900ee16af8b4e39ac54aed Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Mon, 8 Nov 2021 20:28:09 -0600
Subject: [PATCH 74/88] core/hid: Remove usage of native types, fix a couple of
 errors with motion

---
 src/core/hid/emulated_console.cpp             |   2 +-
 src/core/hid/emulated_controller.cpp          |   4 +-
 src/core/hid/emulated_controller.h            |   4 +-
 src/core/hid/hid_types.h                      |  67 ++-
 .../service/am/applets/applet_controller.cpp  |   1 +
 .../service/am/applets/applet_controller.h    |   6 +-
 src/core/hle/service/hid/controllers/npad.cpp | 498 +++++++++++-------
 src/core/hle/service/hid/controllers/npad.h   | 159 +++---
 src/core/hle/service/hid/hid.cpp              | 289 +++++-----
 .../configuration/configure_input_player.cpp  |   4 +-
 .../configure_input_player_widget.cpp         |  24 +-
 11 files changed, 631 insertions(+), 427 deletions(-)

diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index 864481f527..374dd5d41b 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -152,7 +152,7 @@ void EmulatedConsole::SetMotion(Common::Input::CallbackStatus callback) {
     motion.rotation = emulated.GetGyroscope();
     motion.orientation = emulated.GetOrientation();
     motion.quaternion = emulated.GetQuaternion();
-    motion.is_at_rest = emulated.IsMoving(motion_sensitivity);
+    motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
 
     TriggerOnChange(ConsoleTriggerType::Motion);
 }
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index a9038e06f6..54c1a23243 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -347,7 +347,7 @@ void EmulatedController::RestoreConfig() {
 }
 
 std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices(
-    DeviceIndex device_index) const {
+    EmulatedDeviceIndex device_index) const {
     std::vector<Common::ParamPackage> devices;
     for (const auto& param : button_params) {
         if (!param.Has("engine")) {
@@ -704,7 +704,7 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std::
     motion.gyro = emulated.GetGyroscope();
     motion.rotation = emulated.GetRotations();
     motion.orientation = emulated.GetOrientation();
-    motion.is_at_rest = emulated.IsMoving(motion_sensitivity);
+    motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
 
     TriggerOnChange(ControllerTriggerType::Motion, true);
 }
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index fa2e89c0b8..2c5d51bc8f 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -81,7 +81,7 @@ struct ControllerMotion {
     bool is_at_rest{};
 };
 
-enum DeviceIndex : u8 {
+enum EmulatedDeviceIndex : u8 {
     LeftIndex,
     RightIndex,
     DualIndex,
@@ -202,7 +202,7 @@ public:
     void RestoreConfig();
 
     /// Returns a vector of mapped devices from the mapped button and stick parameters
-    std::vector<Common::ParamPackage> GetMappedDevices(DeviceIndex device_index) const;
+    std::vector<Common::ParamPackage> GetMappedDevices(EmulatedDeviceIndex device_index) const;
 
     // Returns the current mapped button device
     Common::ParamPackage GetButtonParam(std::size_t index) const;
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 22177b5ed8..f224cb7443 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -13,7 +13,7 @@
 namespace Core::HID {
 
 // This is nn::hid::NpadIdType
-enum class NpadIdType : u8 {
+enum class NpadIdType : u32 {
     Player1 = 0x0,
     Player2 = 0x1,
     Player3 = 0x2,
@@ -25,7 +25,7 @@ enum class NpadIdType : u8 {
     Other = 0x10,
     Handheld = 0x20,
 
-    Invalid = 0xFF,
+    Invalid = 0xFFFFFFFF,
 };
 
 /// Converts a NpadIdType to an array index.
@@ -104,10 +104,30 @@ enum class NpadStyleIndex : u8 {
     MaxNpadType = 34,
 };
 
+// This is nn::hid::NpadStyleSet
+enum class NpadStyleSet : u32 {
+    None = 0,
+    Fullkey = 1U << 0,
+    Handheld = 1U << 1,
+    JoyDual = 1U << 2,
+    JoyLeft = 1U << 3,
+    JoyRight = 1U << 4,
+    Gc = 1U << 5,
+    Palma = 1U << 6,
+    Lark = 1U << 7,
+    HandheldLark = 1U << 8,
+    Lucia = 1U << 9,
+    Lagoon = 1U << 10,
+    Lager = 1U << 11,
+    SystemExt = 1U << 29,
+    System = 1U << 30,
+};
+static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
+
 // This is nn::hid::NpadStyleTag
 struct NpadStyleTag {
     union {
-        u32 raw{};
+        NpadStyleSet raw{};
 
         BitField<0, 1, u32> fullkey;
         BitField<1, 1, u32> handheld;
@@ -322,6 +342,47 @@ struct DebugPadButton {
 };
 static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size");
 
+enum class DeviceIndex : u8 {
+    Left = 0,
+    Right = 1,
+    None = 2,
+    MaxDeviceIndex = 3,
+};
+
+// This is nn::hid::ConsoleSixAxisSensorHandle
+struct ConsoleSixAxisSensorHandle {
+    u8 unknown_1;
+    u8 unknown_2;
+    INSERT_PADDING_BYTES_NOINIT(2);
+};
+static_assert(sizeof(ConsoleSixAxisSensorHandle) == 4,
+              "ConsoleSixAxisSensorHandle is an invalid size");
+
+// This is nn::hid::SixAxisSensorHandle
+struct SixAxisSensorHandle {
+    NpadStyleIndex npad_type;
+    u8 npad_id;
+    DeviceIndex device_index;
+    INSERT_PADDING_BYTES_NOINIT(1);
+};
+static_assert(sizeof(SixAxisSensorHandle) == 4, "SixAxisSensorHandle is an invalid size");
+
+struct SixAxisSensorFusionParameters {
+    f32 parameter1;
+    f32 parameter2;
+};
+static_assert(sizeof(SixAxisSensorFusionParameters) == 8,
+              "SixAxisSensorFusionParameters is an invalid size");
+
+// This is nn::hid::VibrationDeviceHandle
+struct VibrationDeviceHandle {
+    NpadStyleIndex npad_type;
+    u8 npad_id;
+    DeviceIndex device_index;
+    INSERT_PADDING_BYTES_NOINIT(1);
+};
+static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size");
+
 // This is nn::hid::VibrationDeviceType
 enum class VibrationDeviceType : u32 {
     Unknown = 0,
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index 374e0c7f46..d073f22108 100644
--- a/src/core/hle/service/am/applets/applet_controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -12,6 +12,7 @@
 #include "core/frontend/applets/controller.h"
 #include "core/hid/emulated_controller.h"
 #include "core/hid/hid_core.h"
+#include "core/hid/hid_types.h"
 #include "core/hle/result.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applet_controller.h"
diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/applets/applet_controller.h
index 0a34c4fc0c..1a832505eb 100644
--- a/src/core/hle/service/am/applets/applet_controller.h
+++ b/src/core/hle/service/am/applets/applet_controller.h
@@ -16,6 +16,10 @@ namespace Core {
 class System;
 }
 
+namespace Core::HID {
+enum class NpadStyleSet : u32;
+}
+
 namespace Service::AM::Applets {
 
 using IdentificationColor = std::array<u8, 4>;
@@ -52,7 +56,7 @@ struct ControllerSupportArgPrivate {
     bool flag_1{};
     ControllerSupportMode mode{};
     ControllerSupportCaller caller{};
-    u32 style_set{};
+    Core::HID::NpadStyleSet style_set{};
     u32 joy_hold_type{};
 };
 static_assert(sizeof(ControllerSupportArgPrivate) == 0x14,
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index b97e575f39..eaec791399 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -21,68 +21,25 @@
 
 namespace Service::HID {
 constexpr std::size_t NPAD_OFFSET = 0x9A00;
-constexpr u32 MAX_NPAD_ID = 7;
-constexpr std::size_t HANDHELD_INDEX = 8;
-constexpr std::array<u32, 10> npad_id_list{
-    0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN,
+constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
+    Core::HID::NpadIdType::Player1,  Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3,
+    Core::HID::NpadIdType::Player4,  Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6,
+    Core::HID::NpadIdType::Player7,  Core::HID::NpadIdType::Player8, Core::HID::NpadIdType::Other,
+    Core::HID::NpadIdType::Handheld,
 };
 
-std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) {
+bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) {
     switch (npad_id) {
-    case 0:
-    case 1:
-    case 2:
-    case 3:
-    case 4:
-    case 5:
-    case 6:
-    case 7:
-        return npad_id;
-    case HANDHELD_INDEX:
-    case NPAD_HANDHELD:
-        return HANDHELD_INDEX;
-    case 9:
-    case NPAD_UNKNOWN:
-        return 9;
-    default:
-        UNIMPLEMENTED_MSG("Unknown npad id {}", npad_id);
-        return 0;
-    }
-}
-
-u32 Controller_NPad::IndexToNPad(std::size_t index) {
-    switch (index) {
-    case 0:
-    case 1:
-    case 2:
-    case 3:
-    case 4:
-    case 5:
-    case 6:
-    case 7:
-        return static_cast<u32>(index);
-    case HANDHELD_INDEX:
-        return NPAD_HANDHELD;
-    case 9:
-        return NPAD_UNKNOWN;
-    default:
-        UNIMPLEMENTED_MSG("Unknown npad index {}", index);
-        return 0;
-    }
-}
-
-bool Controller_NPad::IsNpadIdValid(u32 npad_id) {
-    switch (npad_id) {
-    case 0:
-    case 1:
-    case 2:
-    case 3:
-    case 4:
-    case 5:
-    case 6:
-    case 7:
-    case NPAD_UNKNOWN:
-    case NPAD_HANDHELD:
+    case Core::HID::NpadIdType::Player1:
+    case Core::HID::NpadIdType::Player2:
+    case Core::HID::NpadIdType::Player3:
+    case Core::HID::NpadIdType::Player4:
+    case Core::HID::NpadIdType::Player5:
+    case Core::HID::NpadIdType::Player6:
+    case Core::HID::NpadIdType::Player7:
+    case Core::HID::NpadIdType::Player8:
+    case Core::HID::NpadIdType::Other:
+    case Core::HID::NpadIdType::Handheld:
         return true;
     default:
         LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
@@ -90,10 +47,16 @@ bool Controller_NPad::IsNpadIdValid(u32 npad_id) {
     }
 }
 
-bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) {
-    return IsNpadIdValid(device_handle.npad_id) &&
+bool Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) {
+    return IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)) &&
            device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType &&
-           device_handle.device_index < DeviceIndex::MaxDeviceIndex;
+           device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
+}
+
+bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle) {
+    return IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)) &&
+           device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType &&
+           device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
 }
 
 Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
@@ -102,9 +65,9 @@ Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
     for (std::size_t i = 0; i < controller_data.size(); ++i) {
         auto& controller = controller_data[i];
         controller.device = hid_core.GetEmulatedControllerByIndex(i);
-        controller.vibration[Core::HID::DeviceIndex::LeftIndex].latest_vibration_value =
+        controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
             DEFAULT_VIBRATION_VALUE;
-        controller.vibration[Core::HID::DeviceIndex::RightIndex].latest_vibration_value =
+        controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value =
             DEFAULT_VIBRATION_VALUE;
         Core::HID::ControllerUpdateCallback engine_callback{
             .on_change = [this,
@@ -130,17 +93,21 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
         ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
         return;
     }
+    if (controller_idx >= controller_data.size()) {
+        return;
+    }
 
     auto& controller = controller_data[controller_idx];
     const auto is_connected = controller.device->IsConnected();
     const auto npad_type = controller.device->GetNpadStyleIndex();
+    const auto npad_id = controller.device->GetNpadIdType();
     switch (type) {
     case Core::HID::ControllerTriggerType::Connected:
     case Core::HID::ControllerTriggerType::Disconnected:
         if (is_connected == controller.is_connected) {
             return;
         }
-        UpdateControllerAt(npad_type, controller_idx, is_connected);
+        UpdateControllerAt(npad_type, npad_id, is_connected);
         break;
     case Core::HID::ControllerTriggerType::Battery: {
         if (!controller.is_connected) {
@@ -158,15 +125,16 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
     }
 }
 
-void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
-    auto& controller = controller_data[controller_idx];
+void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
+    LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
+    auto& controller = GetControllerFromNpadIdType(npad_id);
     const auto controller_type = controller.device->GetNpadStyleIndex();
     auto& shared_memory = controller.shared_memory_entry;
     if (controller_type == Core::HID::NpadStyleIndex::None) {
         controller.styleset_changed_event->GetWritableEvent().Signal();
         return;
     }
-    shared_memory.style_set.raw = 0; // Zero out
+    shared_memory.style_tag.raw = Core::HID::NpadStyleSet::None;
     shared_memory.device_type.raw = 0;
     shared_memory.system_properties.raw = 0;
     switch (controller_type) {
@@ -174,7 +142,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         UNREACHABLE();
         break;
     case Core::HID::NpadStyleIndex::ProController:
-        shared_memory.style_set.fullkey.Assign(1);
+        shared_memory.style_tag.fullkey.Assign(1);
         shared_memory.device_type.fullkey.Assign(1);
         shared_memory.system_properties.is_vertical.Assign(1);
         shared_memory.system_properties.use_plus.Assign(1);
@@ -183,7 +151,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController;
         break;
     case Core::HID::NpadStyleIndex::Handheld:
-        shared_memory.style_set.handheld.Assign(1);
+        shared_memory.style_tag.handheld.Assign(1);
         shared_memory.device_type.handheld_left.Assign(1);
         shared_memory.device_type.handheld_right.Assign(1);
         shared_memory.system_properties.is_vertical.Assign(1);
@@ -193,7 +161,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
         break;
     case Core::HID::NpadStyleIndex::JoyconDual:
-        shared_memory.style_set.joycon_dual.Assign(1);
+        shared_memory.style_tag.joycon_dual.Assign(1);
         shared_memory.device_type.joycon_left.Assign(1);
         shared_memory.device_type.joycon_right.Assign(1);
         shared_memory.system_properties.is_vertical.Assign(1);
@@ -203,7 +171,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
         break;
     case Core::HID::NpadStyleIndex::JoyconLeft:
-        shared_memory.style_set.joycon_left.Assign(1);
+        shared_memory.style_tag.joycon_left.Assign(1);
         shared_memory.device_type.joycon_left.Assign(1);
         shared_memory.system_properties.is_horizontal.Assign(1);
         shared_memory.system_properties.use_minus.Assign(1);
@@ -211,7 +179,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
         break;
     case Core::HID::NpadStyleIndex::JoyconRight:
-        shared_memory.style_set.joycon_right.Assign(1);
+        shared_memory.style_tag.joycon_right.Assign(1);
         shared_memory.device_type.joycon_right.Assign(1);
         shared_memory.system_properties.is_horizontal.Assign(1);
         shared_memory.system_properties.use_plus.Assign(1);
@@ -219,32 +187,32 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
         shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
         break;
     case Core::HID::NpadStyleIndex::GameCube:
-        shared_memory.style_set.gamecube.Assign(1);
+        shared_memory.style_tag.gamecube.Assign(1);
         shared_memory.device_type.fullkey.Assign(1);
         shared_memory.system_properties.is_vertical.Assign(1);
         shared_memory.system_properties.use_plus.Assign(1);
         break;
     case Core::HID::NpadStyleIndex::Pokeball:
-        shared_memory.style_set.palma.Assign(1);
+        shared_memory.style_tag.palma.Assign(1);
         shared_memory.device_type.palma.Assign(1);
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
         break;
     case Core::HID::NpadStyleIndex::NES:
-        shared_memory.style_set.lark.Assign(1);
+        shared_memory.style_tag.lark.Assign(1);
         shared_memory.device_type.fullkey.Assign(1);
         break;
     case Core::HID::NpadStyleIndex::SNES:
-        shared_memory.style_set.lucia.Assign(1);
+        shared_memory.style_tag.lucia.Assign(1);
         shared_memory.device_type.fullkey.Assign(1);
         shared_memory.applet_footer.type = AppletFooterUiType::Lucia;
         break;
     case Core::HID::NpadStyleIndex::N64:
-        shared_memory.style_set.lagoon.Assign(1);
+        shared_memory.style_tag.lagoon.Assign(1);
         shared_memory.device_type.fullkey.Assign(1);
         shared_memory.applet_footer.type = AppletFooterUiType::Lagon;
         break;
     case Core::HID::NpadStyleIndex::SegaGenesis:
-        shared_memory.style_set.lager.Assign(1);
+        shared_memory.style_tag.lager.Assign(1);
         shared_memory.device_type.fullkey.Assign(1);
         break;
     default:
@@ -268,7 +236,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
 
     controller.is_connected = true;
     controller.device->Connect();
-    SignalStyleSetChangedEvent(IndexToNPad(controller_idx));
+    SignalStyleSetChangedEvent(npad_id);
     WriteEmptyEntry(controller.shared_memory_entry);
 }
 
@@ -283,7 +251,7 @@ void Controller_NPad::OnInit() {
             service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
     }
 
-    if (hid_core.GetSupportedStyleTag().raw == 0) {
+    if (hid_core.GetSupportedStyleTag().raw == Core::HID::NpadStyleSet::None) {
         // We want to support all controllers
         Core::HID::NpadStyleTag style{};
         style.handheld.Assign(1);
@@ -298,7 +266,7 @@ void Controller_NPad::OnInit() {
 
     supported_npad_id_types.resize(npad_id_list.size());
     std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
-                npad_id_list.size() * sizeof(u32));
+                npad_id_list.size() * sizeof(Core::HID::NpadIdType));
 
     // Prefill controller buffers
     for (auto& controller : controller_data) {
@@ -322,8 +290,7 @@ void Controller_NPad::OnInit() {
     for (auto& controller : controller_data) {
         const auto& device = controller.device;
         if (device->IsConnected()) {
-            const std::size_t index = Core::HID::NpadIdTypeToIndex(device->GetNpadIdType());
-            AddNewControllerAt(device->GetNpadStyleIndex(), index);
+            AddNewControllerAt(device->GetNpadStyleIndex(), device->GetNpadIdType());
         }
     }
 }
@@ -354,15 +321,14 @@ void Controller_NPad::OnRelease() {
         auto& controller = controller_data[i];
         service_context.CloseEvent(controller.styleset_changed_event);
         for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
-            VibrateControllerAtIndex(i, device_idx, {});
+            VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_idx, {});
         }
     }
 }
 
-void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
+void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
     std::lock_guard lock{mutex};
-    const auto controller_idx = NPadIdToIndex(npad_id);
-    auto& controller = controller_data[controller_idx];
+    auto& controller = GetControllerFromNpadIdType(npad_id);
     const auto controller_type = controller.device->GetNpadStyleIndex();
     if (!controller.device->IsConnected()) {
         return;
@@ -431,9 +397,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
                         &controller.shared_memory_entry, sizeof(NpadInternalState));
             continue;
         }
-        const u32 npad_index = static_cast<u32>(i);
 
-        RequestPadStateUpdate(npad_index);
+        RequestPadStateUpdate(controller.device->GetNpadIdType());
         auto& pad_state = controller.npad_pad_state;
         auto& libnx_state = controller.npad_libnx_state;
         auto& trigger_state = controller.npad_trigger_state;
@@ -571,10 +536,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
         auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
         auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
 
-        if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) {
-            sixaxis_at_rest = true;
+        if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
+            controller.sixaxis_at_rest = true;
             for (std::size_t e = 0; e < motion_state.size(); ++e) {
-                sixaxis_at_rest = sixaxis_at_rest && motion_state[e].is_at_rest;
+                controller.sixaxis_at_rest =
+                    controller.sixaxis_at_rest && motion_state[e].is_at_rest;
             }
         }
 
@@ -584,7 +550,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
             break;
         case Core::HID::NpadStyleIndex::ProController:
             sixaxis_fullkey_state.attribute.raw = 0;
-            if (sixaxis_sensors_enabled) {
+            if (controller.sixaxis_sensor_enabled) {
                 sixaxis_fullkey_state.attribute.is_connected.Assign(1);
                 sixaxis_fullkey_state.accel = motion_state[0].accel;
                 sixaxis_fullkey_state.gyro = motion_state[0].gyro;
@@ -594,7 +560,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
             break;
         case Core::HID::NpadStyleIndex::Handheld:
             sixaxis_handheld_state.attribute.raw = 0;
-            if (sixaxis_sensors_enabled) {
+            if (controller.sixaxis_sensor_enabled) {
                 sixaxis_handheld_state.attribute.is_connected.Assign(1);
                 sixaxis_handheld_state.accel = motion_state[0].accel;
                 sixaxis_handheld_state.gyro = motion_state[0].gyro;
@@ -605,7 +571,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
         case Core::HID::NpadStyleIndex::JoyconDual:
             sixaxis_dual_left_state.attribute.raw = 0;
             sixaxis_dual_right_state.attribute.raw = 0;
-            if (sixaxis_sensors_enabled) {
+            if (controller.sixaxis_sensor_enabled) {
                 // Set motion for the left joycon
                 sixaxis_dual_left_state.attribute.is_connected.Assign(1);
                 sixaxis_dual_left_state.accel = motion_state[0].accel;
@@ -613,7 +579,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
                 sixaxis_dual_left_state.rotation = motion_state[0].rotation;
                 sixaxis_dual_left_state.orientation = motion_state[0].orientation;
             }
-            if (sixaxis_sensors_enabled) {
+            if (controller.sixaxis_sensor_enabled) {
                 // Set motion for the right joycon
                 sixaxis_dual_right_state.attribute.is_connected.Assign(1);
                 sixaxis_dual_right_state.accel = motion_state[1].accel;
@@ -624,7 +590,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
             break;
         case Core::HID::NpadStyleIndex::JoyconLeft:
             sixaxis_left_lifo_state.attribute.raw = 0;
-            if (sixaxis_sensors_enabled) {
+            if (controller.sixaxis_sensor_enabled) {
                 sixaxis_left_lifo_state.attribute.is_connected.Assign(1);
                 sixaxis_left_lifo_state.accel = motion_state[0].accel;
                 sixaxis_left_lifo_state.gyro = motion_state[0].gyro;
@@ -634,7 +600,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
             break;
         case Core::HID::NpadStyleIndex::JoyconRight:
             sixaxis_right_lifo_state.attribute.raw = 0;
-            if (sixaxis_sensors_enabled) {
+            if (controller.sixaxis_sensor_enabled) {
                 sixaxis_right_lifo_state.attribute.is_connected.Assign(1);
                 sixaxis_right_lifo_state.accel = motion_state[1].accel;
                 sixaxis_right_lifo_state.gyro = motion_state[1].gyro;
@@ -724,26 +690,30 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
     return communication_mode;
 }
 
-void Controller_NPad::SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode) {
-    const std::size_t npad_index = NPadIdToIndex(npad_id);
-    ASSERT(npad_index < controller_data.size());
-    auto& controller = controller_data[npad_index];
+void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id,
+                                  NpadJoyAssignmentMode assignment_mode) {
+    if (!IsNpadIdValid(npad_id)) {
+        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
+        return;
+    }
+
+    auto& controller = GetControllerFromNpadIdType(npad_id);
     if (controller.shared_memory_entry.assignment_mode != assignment_mode) {
         controller.shared_memory_entry.assignment_mode = assignment_mode;
     }
 }
 
-bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index,
-                                               const VibrationValue& vibration_value) {
-    auto& controller = controller_data[npad_index];
-
+bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
+                                               std::size_t device_index,
+                                               const Core::HID::VibrationValue& vibration_value) {
+    auto& controller = GetControllerFromNpadIdType(npad_id);
     if (!controller.device->IsConnected()) {
         return false;
     }
 
     if (!controller.device->IsVibrationEnabled()) {
-        if (controller.vibration[device_index].latest_vibration_value.amp_low != 0.0f ||
-            controller.vibration[device_index].latest_vibration_value.amp_high != 0.0f) {
+        if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f ||
+            controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) {
             // Send an empty vibration to stop any vibrations.
             Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
             controller.device->SetVibration(device_index, vibration);
@@ -762,7 +732,7 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size
         const auto now = steady_clock::now();
 
         // Filter out non-zero vibrations that are within 10ms of each other.
-        if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) &&
+        if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) &&
             duration_cast<milliseconds>(
                 now - controller.vibration[device_index].last_vibration_timepoint) <
                 milliseconds(10)) {
@@ -772,13 +742,15 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size
         controller.vibration[device_index].last_vibration_timepoint = now;
     }
 
-    Core::HID::VibrationValue vibration{vibration_value.amp_low, vibration_value.freq_low,
-                                        vibration_value.amp_high, vibration_value.freq_high};
+    Core::HID::VibrationValue vibration{
+        vibration_value.low_amplitude, vibration_value.low_frequency,
+        vibration_value.high_amplitude, vibration_value.high_frequency};
     return controller.device->SetVibration(device_index, vibration);
 }
 
-void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle,
-                                        const VibrationValue& vibration_value) {
+void Controller_NPad::VibrateController(
+    const Core::HID::VibrationDeviceHandle& vibration_device_handle,
+    const Core::HID::VibrationValue& vibration_value) {
     if (!IsDeviceHandleValid(vibration_device_handle)) {
         return;
     }
@@ -787,15 +759,14 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han
         return;
     }
 
-    const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
-    auto& controller = controller_data[npad_index];
+    auto& controller = GetControllerFromHandle(vibration_device_handle);
     const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
 
     if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) {
         return;
     }
 
-    if (vibration_device_handle.device_index == DeviceIndex::None) {
+    if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) {
         UNREACHABLE_MSG("DeviceIndex should never be None!");
         return;
     }
@@ -803,28 +774,30 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han
     // Some games try to send mismatched parameters in the device handle, block these.
     if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
          (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight ||
-          vibration_device_handle.device_index == DeviceIndex::Right)) ||
+          vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) ||
         (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight &&
          (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft ||
-          vibration_device_handle.device_index == DeviceIndex::Left))) {
+          vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) {
         return;
     }
 
     // Filter out vibrations with equivalent values to reduce unnecessary state changes.
-    if (vibration_value.amp_low ==
-            controller.vibration[device_index].latest_vibration_value.amp_low &&
-        vibration_value.amp_high ==
-            controller.vibration[device_index].latest_vibration_value.amp_high) {
+    if (vibration_value.low_amplitude ==
+            controller.vibration[device_index].latest_vibration_value.low_amplitude &&
+        vibration_value.high_amplitude ==
+            controller.vibration[device_index].latest_vibration_value.high_amplitude) {
         return;
     }
 
-    if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) {
+    if (VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_index,
+                                 vibration_value)) {
         controller.vibration[device_index].latest_vibration_value = vibration_value;
     }
 }
 
-void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles,
-                                         const std::vector<VibrationValue>& vibration_values) {
+void Controller_NPad::VibrateControllers(
+    const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles,
+    const std::vector<Core::HID::VibrationValue>& vibration_values) {
     if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
         return;
     }
@@ -839,31 +812,31 @@ void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibrat
     }
 }
 
-Controller_NPad::VibrationValue Controller_NPad::GetLastVibration(
-    const DeviceHandle& vibration_device_handle) const {
+Core::HID::VibrationValue Controller_NPad::GetLastVibration(
+    const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
     if (!IsDeviceHandleValid(vibration_device_handle)) {
         return {};
     }
 
-    const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
-    const auto& controller = controller_data[npad_index];
+    const auto& controller = GetControllerFromHandle(vibration_device_handle);
     const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
     return controller.vibration[device_index].latest_vibration_value;
 }
 
-void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) {
+void Controller_NPad::InitializeVibrationDevice(
+    const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
     if (!IsDeviceHandleValid(vibration_device_handle)) {
         return;
     }
 
-    const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
+    const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id);
     const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
     InitializeVibrationDeviceAtIndex(npad_index, device_index);
 }
 
-void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index,
+void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
                                                        std::size_t device_index) {
-    auto& controller = controller_data[npad_index];
+    auto& controller = GetControllerFromNpadIdType(npad_id);
     if (!Settings::values.vibration_enabled.GetValue()) {
         controller.vibration[device_index].device_mounted = false;
         return;
@@ -877,58 +850,67 @@ void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
     permit_vibration_session_enabled = permit_vibration_session;
 }
 
-bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const {
+bool Controller_NPad::IsVibrationDeviceMounted(
+    const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
     if (!IsDeviceHandleValid(vibration_device_handle)) {
         return false;
     }
 
-    const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
-    const auto& controller = controller_data[npad_index];
+    const auto& controller = GetControllerFromHandle(vibration_device_handle);
     const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
     return controller.vibration[device_index].device_mounted;
 }
 
-Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) {
-    const auto& controller = controller_data[NPadIdToIndex(npad_id)];
+Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
+    if (!IsNpadIdValid(npad_id)) {
+        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
+        // Fallback to player 1
+        const auto& controller = GetControllerFromNpadIdType(Core::HID::NpadIdType::Player1);
+        return controller.styleset_changed_event->GetReadableEvent();
+    }
+
+    const auto& controller = GetControllerFromNpadIdType(npad_id);
     return controller.styleset_changed_event->GetReadableEvent();
 }
 
-void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const {
-    const auto& controller = controller_data[NPadIdToIndex(npad_id)];
+void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
+    const auto& controller = GetControllerFromNpadIdType(npad_id);
     controller.styleset_changed_event->GetWritableEvent().Signal();
 }
 
 void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller,
-                                         std::size_t npad_index) {
-    UpdateControllerAt(controller, npad_index, true);
+                                         Core::HID::NpadIdType npad_id) {
+    UpdateControllerAt(controller, npad_id, true);
 }
 
-void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, std::size_t npad_index,
-                                         bool connected) {
-    auto& controller = controller_data[npad_index];
+void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
+                                         Core::HID::NpadIdType npad_id, bool connected) {
+    auto& controller = GetControllerFromNpadIdType(npad_id);
     if (!connected) {
-        DisconnectNpadAtIndex(npad_index);
+        DisconnectNpad(npad_id);
         return;
     }
 
     controller.device->SetNpadStyleIndex(type);
-    InitNewlyAddedController(npad_index);
+    InitNewlyAddedController(npad_id);
 }
 
-void Controller_NPad::DisconnectNpad(u32 npad_id) {
-    DisconnectNpadAtIndex(NPadIdToIndex(npad_id));
-}
+void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
+    if (!IsNpadIdValid(npad_id)) {
+        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
+        return;
+    }
 
-void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
-    auto& controller = controller_data[npad_index];
+    LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id);
+    auto& controller = GetControllerFromNpadIdType(npad_id);
     for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
         // Send an empty vibration to stop any vibrations.
-        VibrateControllerAtIndex(npad_index, device_idx, {});
+        VibrateControllerAtIndex(npad_id, device_idx, {});
         controller.vibration[device_idx].device_mounted = false;
     }
 
     auto& shared_memory_entry = controller.shared_memory_entry;
-    shared_memory_entry.style_set.raw = 0; // Zero out
+    shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out
     shared_memory_entry.device_type.raw = 0;
     shared_memory_entry.system_properties.raw = 0;
     shared_memory_entry.button_properties.raw = 0;
@@ -949,48 +931,102 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
 
     controller.is_connected = false;
     controller.device->Disconnect();
-    SignalStyleSetChangedEvent(IndexToNPad(npad_index));
+    SignalStyleSetChangedEvent(npad_id);
     WriteEmptyEntry(controller.shared_memory_entry);
 }
 
-void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) {
-    gyroscope_zero_drift_mode = drift_mode;
+void Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
+                                                GyroscopeZeroDriftMode drift_mode) {
+    if (!IsDeviceHandleValid(sixaxis_handle)) {
+        LOG_ERROR(Service_HID, "Invalid handle");
+        return;
+    }
+    auto& controller = GetControllerFromHandle(sixaxis_handle);
+    controller.gyroscope_zero_drift_mode = drift_mode;
 }
 
-Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode() const {
-    return gyroscope_zero_drift_mode;
+Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode(
+    Core::HID::SixAxisSensorHandle sixaxis_handle) const {
+    if (!IsDeviceHandleValid(sixaxis_handle)) {
+        LOG_ERROR(Service_HID, "Invalid handle");
+        // Return the default value
+        return GyroscopeZeroDriftMode::Standard;
+    }
+    const auto& controller = GetControllerFromHandle(sixaxis_handle);
+    return controller.gyroscope_zero_drift_mode;
 }
 
-bool Controller_NPad::IsSixAxisSensorAtRest() const {
-    return sixaxis_at_rest;
+bool Controller_NPad::IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle) const {
+    if (!IsDeviceHandleValid(sixaxis_handle)) {
+        LOG_ERROR(Service_HID, "Invalid handle");
+        // Return the default value
+        return true;
+    }
+    const auto& controller = GetControllerFromHandle(sixaxis_handle);
+    return controller.sixaxis_at_rest;
 }
 
-void Controller_NPad::SetSixAxisEnabled(bool six_axis_status) {
-    sixaxis_sensors_enabled = six_axis_status;
+void Controller_NPad::SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
+                                        bool sixaxis_status) {
+    if (!IsDeviceHandleValid(sixaxis_handle)) {
+        LOG_ERROR(Service_HID, "Invalid handle");
+        return;
+    }
+    auto& controller = GetControllerFromHandle(sixaxis_handle);
+    controller.sixaxis_sensor_enabled = sixaxis_status;
 }
 
-void Controller_NPad::SetSixAxisFusionParameters(f32 parameter1, f32 parameter2) {
-    sixaxis_fusion_parameter1 = parameter1;
-    sixaxis_fusion_parameter2 = parameter2;
+void Controller_NPad::SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
+                                              bool sixaxis_fusion_status) {
+    if (!IsDeviceHandleValid(sixaxis_handle)) {
+        LOG_ERROR(Service_HID, "Invalid handle");
+        return;
+    }
+    auto& controller = GetControllerFromHandle(sixaxis_handle);
+    controller.sixaxis_fusion_enabled = sixaxis_fusion_status;
 }
 
-std::pair<f32, f32> Controller_NPad::GetSixAxisFusionParameters() {
-    return {
-        sixaxis_fusion_parameter1,
-        sixaxis_fusion_parameter2,
-    };
+void Controller_NPad::SetSixAxisFusionParameters(
+    Core::HID::SixAxisSensorHandle sixaxis_handle,
+    Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
+    if (!IsDeviceHandleValid(sixaxis_handle)) {
+        LOG_ERROR(Service_HID, "Invalid handle");
+        return;
+    }
+    auto& controller = GetControllerFromHandle(sixaxis_handle);
+    controller.sixaxis_fusion = sixaxis_fusion_parameters;
 }
 
-void Controller_NPad::ResetSixAxisFusionParameters() {
-    sixaxis_fusion_parameter1 = 0.0f;
-    sixaxis_fusion_parameter2 = 0.0f;
+Core::HID::SixAxisSensorFusionParameters Controller_NPad::GetSixAxisFusionParameters(
+    Core::HID::SixAxisSensorHandle sixaxis_handle) {
+    if (!IsDeviceHandleValid(sixaxis_handle)) {
+        LOG_ERROR(Service_HID, "Invalid handle");
+        // Since these parameters are unknow just return zeros
+        return {};
+    }
+    auto& controller = GetControllerFromHandle(sixaxis_handle);
+    return controller.sixaxis_fusion;
 }
 
-void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
-    const auto npad_index_1 = NPadIdToIndex(npad_id_1);
-    const auto npad_index_2 = NPadIdToIndex(npad_id_2);
-    const auto& controller_1 = controller_data[npad_index_1].device;
-    const auto& controller_2 = controller_data[npad_index_2].device;
+void Controller_NPad::ResetSixAxisFusionParameters(Core::HID::SixAxisSensorHandle sixaxis_handle) {
+    if (!IsDeviceHandleValid(sixaxis_handle)) {
+        LOG_ERROR(Service_HID, "Invalid handle");
+        return;
+    }
+    auto& controller = GetControllerFromHandle(sixaxis_handle);
+    // Since these parameters are unknow just fill with zeros
+    controller.sixaxis_fusion = {};
+}
+
+void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
+                                              Core::HID::NpadIdType npad_id_2) {
+    if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
+        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
+                  npad_id_2);
+        return;
+    }
+    auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
+    auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
 
     // If the controllers at both npad indices form a pair of left and right joycons, merge them.
     // Otherwise, do nothing.
@@ -1000,7 +1036,7 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
          controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight)) {
         // Disconnect the joycon at the second id and connect the dual joycon at the first index.
         DisconnectNpad(npad_id_2);
-        AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_index_1);
+        AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
     }
 }
 
@@ -1014,15 +1050,20 @@ void Controller_NPad::StopLRAssignmentMode() {
     is_in_lr_assignment_mode = false;
 }
 
-bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
-    if (npad_id_1 == NPAD_HANDHELD || npad_id_2 == NPAD_HANDHELD || npad_id_1 == NPAD_UNKNOWN ||
-        npad_id_2 == NPAD_UNKNOWN) {
+bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
+                                         Core::HID::NpadIdType npad_id_2) {
+    if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
+        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
+                  npad_id_2);
+        return false;
+    }
+    if (npad_id_1 == Core::HID::NpadIdType::Handheld ||
+        npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other ||
+        npad_id_2 == Core::HID::NpadIdType::Other) {
         return true;
     }
-    const auto npad_index_1 = NPadIdToIndex(npad_id_1);
-    const auto npad_index_2 = NPadIdToIndex(npad_id_2);
-    const auto& controller_1 = controller_data[npad_index_1].device;
-    const auto& controller_2 = controller_data[npad_index_2].device;
+    const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
+    const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
     const auto type_index_1 = controller_1->GetNpadStyleIndex();
     const auto type_index_2 = controller_2->GetNpadStyleIndex();
 
@@ -1030,28 +1071,39 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
         return false;
     }
 
-    AddNewControllerAt(type_index_2, npad_index_1);
-    AddNewControllerAt(type_index_1, npad_index_2);
+    AddNewControllerAt(type_index_2, npad_id_1);
+    AddNewControllerAt(type_index_1, npad_id_2);
 
     return true;
 }
 
-Core::HID::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
-    if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
-        // These are controllers without led patterns
+Core::HID::LedPattern Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id) {
+    if (!IsNpadIdValid(npad_id)) {
+        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
         return Core::HID::LedPattern{0, 0, 0, 0};
     }
-    return controller_data[npad_id].device->GetLedPattern();
+    const auto& controller = GetControllerFromNpadIdType(npad_id).device;
+    return controller->GetLedPattern();
 }
 
-bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const {
-    auto& controller = controller_data[NPadIdToIndex(npad_id)];
+bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(
+    Core::HID::NpadIdType npad_id) const {
+    if (!IsNpadIdValid(npad_id)) {
+        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
+        // Return the default value
+        return false;
+    }
+    const auto& controller = GetControllerFromNpadIdType(npad_id);
     return controller.unintended_home_button_input_protection;
 }
 
 void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
-                                                                    u32 npad_id) {
-    auto& controller = controller_data[NPadIdToIndex(npad_id)];
+                                                                    Core::HID::NpadIdType npad_id) {
+    if (!IsNpadIdValid(npad_id)) {
+        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
+        return;
+    }
+    auto& controller = GetControllerFromNpadIdType(npad_id);
     controller.unintended_home_button_input_protection = is_protection_enabled;
 }
 
@@ -1099,7 +1151,7 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
     if (controller == Core::HID::NpadStyleIndex::Handheld) {
         const bool support_handheld =
             std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
-                      NPAD_HANDHELD) != supported_npad_id_types.end();
+                      Core::HID::NpadIdType::Handheld) != supported_npad_id_types.end();
         // Handheld is not even a supported type, lets stop here
         if (!support_handheld) {
             return false;
@@ -1113,7 +1165,9 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
     }
 
     if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
-                    [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
+                    [](Core::HID::NpadIdType npad_id) {
+                        return npad_id <= Core::HID::NpadIdType::Player8;
+                    })) {
         Core::HID::NpadStyleTag style = GetSupportedStyleSet();
         switch (controller) {
         case Core::HID::NpadStyleIndex::ProController:
@@ -1144,4 +1198,48 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
     return false;
 }
 
+Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
+    const Core::HID::SixAxisSensorHandle& device_handle) {
+    const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
+    return GetControllerFromNpadIdType(npad_id);
+}
+
+const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
+    const Core::HID::SixAxisSensorHandle& device_handle) const {
+    const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
+    return GetControllerFromNpadIdType(npad_id);
+}
+
+Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
+    const Core::HID::VibrationDeviceHandle& device_handle) {
+    const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
+    return GetControllerFromNpadIdType(npad_id);
+}
+
+const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
+    const Core::HID::VibrationDeviceHandle& device_handle) const {
+    const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
+    return GetControllerFromNpadIdType(npad_id);
+}
+
+Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
+    Core::HID::NpadIdType npad_id) {
+    if (!IsNpadIdValid(npad_id)) {
+        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
+        npad_id = Core::HID::NpadIdType::Player1;
+    }
+    const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
+    return controller_data[npad_index];
+}
+
+const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
+    Core::HID::NpadIdType npad_id) const {
+    if (!IsNpadIdValid(npad_id)) {
+        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
+        npad_id = Core::HID::NpadIdType::Player1;
+    }
+    const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
+    return controller_data[npad_index];
+}
+
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index a996755ed5..3798c037fa 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -31,9 +31,6 @@ class ServiceContext;
 
 namespace Service::HID {
 
-constexpr u32 NPAD_HANDHELD = 32;
-constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this?
-
 class Controller_NPad final : public ControllerBase {
 public:
     explicit Controller_NPad(Core::HID::HIDCore& hid_core_,
@@ -53,13 +50,6 @@ public:
     void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                         std::size_t size) override;
 
-    enum class DeviceIndex : u8 {
-        Left = 0,
-        Right = 1,
-        None = 2,
-        MaxDeviceIndex = 3,
-    };
-
     // This is nn::hid::GyroscopeZeroDriftMode
     enum class GyroscopeZeroDriftMode : u32 {
         Loose = 0,
@@ -79,6 +69,12 @@ public:
         Single = 1,
     };
 
+    // This is nn::hid::NpadJoyDeviceType
+    enum class NpadJoyDeviceType : s64 {
+        Left = 0,
+        Right = 1,
+    };
+
     // This is nn::hid::NpadHandheldActivationMode
     enum class NpadHandheldActivationMode : u64 {
         Dual = 0,
@@ -94,28 +90,11 @@ public:
         Default = 3,
     };
 
-    struct DeviceHandle {
-        Core::HID::NpadStyleIndex npad_type;
-        u8 npad_id;
-        DeviceIndex device_index;
-        INSERT_PADDING_BYTES_NOINIT(1);
-    };
-    static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size");
-
-    // This is nn::hid::VibrationValue
-    struct VibrationValue {
-        f32 amp_low;
-        f32 freq_low;
-        f32 amp_high;
-        f32 freq_high;
-    };
-    static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size");
-
-    static constexpr VibrationValue DEFAULT_VIBRATION_VALUE{
-        .amp_low = 0.0f,
-        .freq_low = 160.0f,
-        .amp_high = 0.0f,
-        .freq_high = 320.0f,
+    static constexpr Core::HID::VibrationValue DEFAULT_VIBRATION_VALUE{
+        .low_amplitude = 0.0f,
+        .low_frequency = 160.0f,
+        .high_amplitude = 0.0f,
+        .high_frequency = 320.0f,
     };
 
     void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
@@ -134,68 +113,77 @@ public:
     void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_);
     NpadCommunicationMode GetNpadCommunicationMode() const;
 
-    void SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode);
+    void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyAssignmentMode assignment_mode);
 
-    bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index,
-                                  const VibrationValue& vibration_value);
+    bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
+                                  const Core::HID::VibrationValue& vibration_value);
 
-    void VibrateController(const DeviceHandle& vibration_device_handle,
-                           const VibrationValue& vibration_value);
+    void VibrateController(const Core::HID::VibrationDeviceHandle& vibration_device_handle,
+                           const Core::HID::VibrationValue& vibration_value);
 
-    void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles,
-                            const std::vector<VibrationValue>& vibration_values);
+    void VibrateControllers(
+        const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles,
+        const std::vector<Core::HID::VibrationValue>& vibration_values);
 
-    VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const;
+    Core::HID::VibrationValue GetLastVibration(
+        const Core::HID::VibrationDeviceHandle& vibration_device_handle) const;
 
-    void InitializeVibrationDevice(const DeviceHandle& vibration_device_handle);
+    void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle);
 
-    void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index);
+    void InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index);
 
     void SetPermitVibrationSession(bool permit_vibration_session);
 
-    bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const;
+    bool IsVibrationDeviceMounted(
+        const Core::HID::VibrationDeviceHandle& vibration_device_handle) const;
 
-    Kernel::KReadableEvent& GetStyleSetChangedEvent(u32 npad_id);
-    void SignalStyleSetChangedEvent(u32 npad_id) const;
+    Kernel::KReadableEvent& GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id);
+    void SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const;
 
     // Adds a new controller at an index.
-    void AddNewControllerAt(Core::HID::NpadStyleIndex controller, std::size_t npad_index);
+    void AddNewControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id);
     // Adds a new controller at an index with connection status.
-    void UpdateControllerAt(Core::HID::NpadStyleIndex controller, std::size_t npad_index,
+    void UpdateControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id,
                             bool connected);
 
-    void DisconnectNpad(u32 npad_id);
-    void DisconnectNpadAtIndex(std::size_t index);
+    void DisconnectNpad(Core::HID::NpadIdType npad_id);
 
-    void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode);
-    GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const;
-    bool IsSixAxisSensorAtRest() const;
-    void SetSixAxisEnabled(bool six_axis_status);
-    void SetSixAxisFusionParameters(f32 parameter1, f32 parameter2);
-    std::pair<f32, f32> GetSixAxisFusionParameters();
-    void ResetSixAxisFusionParameters();
-    Core::HID::LedPattern GetLedPattern(u32 npad_id);
-    bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
-    void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
+    void SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
+                                   GyroscopeZeroDriftMode drift_mode);
+    GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode(
+        Core::HID::SixAxisSensorHandle sixaxis_handle) const;
+    bool IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle) const;
+    void SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, bool sixaxis_status);
+    void SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
+                                 bool sixaxis_fusion_status);
+    void SetSixAxisFusionParameters(
+        Core::HID::SixAxisSensorHandle sixaxis_handle,
+        Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
+    Core::HID::SixAxisSensorFusionParameters GetSixAxisFusionParameters(
+        Core::HID::SixAxisSensorHandle sixaxis_handle);
+    void ResetSixAxisFusionParameters(Core::HID::SixAxisSensorHandle sixaxis_handle);
+    Core::HID::LedPattern GetLedPattern(Core::HID::NpadIdType npad_id);
+    bool IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id) const;
+    void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
+                                                       Core::HID::NpadIdType npad_id);
     void SetAnalogStickUseCenterClamp(bool use_center_clamp);
     void ClearAllConnectedControllers();
     void DisconnectAllConnectedControllers();
     void ConnectAllDisconnectedControllers();
     void ClearAllControllers();
 
-    void MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2);
+    void MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2);
     void StartLRAssignmentMode();
     void StopLRAssignmentMode();
-    bool SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2);
+    bool SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2);
 
     // Logical OR for all buttons presses on all controllers
     // Specifically for cheat engine and other features.
     u32 GetAndResetPressState();
 
-    static std::size_t NPadIdToIndex(u32 npad_id);
-    static u32 IndexToNPad(std::size_t index);
-    static bool IsNpadIdValid(u32 npad_id);
-    static bool IsDeviceHandleValid(const DeviceHandle& device_handle);
+    static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
+    static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle);
+    static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
 
 private:
     // This is nn::hid::detail::ColorAttribute
@@ -441,7 +429,7 @@ private:
 
     // This is nn::hid::detail::NpadInternalState
     struct NpadInternalState {
-        Core::HID::NpadStyleTag style_set;
+        Core::HID::NpadStyleTag style_tag;
         NpadJoyAssignmentMode assignment_mode;
         NpadFullKeyColorState fullkey_color;
         NpadJoyColorState joycon_color;
@@ -476,19 +464,19 @@ private:
         NpadLuciaType lucia_type;
         NpadLagonType lagon_type;
         NpadLagerType lager_type;
-        INSERT_PADDING_BYTES(
-            0x4); // FW 13.x Investigate there is some sort of bitflag related to joycons
+        // FW 13.x Investigate there is some sort of bitflag related to joycons
+        INSERT_PADDING_BYTES(0x4);
         INSERT_PADDING_BYTES(0xc08); // Unknown
     };
     static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
 
     struct VibrationData {
         bool device_mounted{};
-        VibrationValue latest_vibration_value{};
+        Core::HID::VibrationValue latest_vibration_value{};
         std::chrono::steady_clock::time_point last_vibration_timepoint{};
     };
 
-    struct ControllerData {
+    struct NpadControllerData {
         Core::HID::EmulatedController* device;
         Kernel::KEvent* styleset_changed_event{};
         NpadInternalState shared_memory_entry{};
@@ -498,6 +486,13 @@ private:
         bool is_connected{};
         Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None};
 
+        // Motion parameters
+        bool sixaxis_at_rest{true};
+        bool sixaxis_sensor_enabled{true};
+        bool sixaxis_fusion_enabled{false};
+        Core::HID::SixAxisSensorFusionParameters sixaxis_fusion{};
+        GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
+
         // Current pad state
         NPadGenericState npad_pad_state{};
         NPadGenericState npad_libnx_state{};
@@ -512,27 +507,33 @@ private:
     };
 
     void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx);
-    void InitNewlyAddedController(std::size_t controller_idx);
+    void InitNewlyAddedController(Core::HID::NpadIdType npad_id);
     bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const;
-    void RequestPadStateUpdate(u32 npad_id);
+    void RequestPadStateUpdate(Core::HID::NpadIdType npad_id);
     void WriteEmptyEntry(NpadInternalState& npad);
 
+    NpadControllerData& GetControllerFromHandle(
+        const Core::HID::SixAxisSensorHandle& device_handle);
+    const NpadControllerData& GetControllerFromHandle(
+        const Core::HID::SixAxisSensorHandle& device_handle) const;
+    NpadControllerData& GetControllerFromHandle(
+        const Core::HID::VibrationDeviceHandle& device_handle);
+    const NpadControllerData& GetControllerFromHandle(
+        const Core::HID::VibrationDeviceHandle& device_handle) const;
+    NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
+    const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
+
     std::atomic<u32> press_state{};
 
-    std::array<ControllerData, 10> controller_data{};
+    std::array<NpadControllerData, 10> controller_data{};
     KernelHelpers::ServiceContext& service_context;
     std::mutex mutex;
-    std::vector<u32> supported_npad_id_types{};
+    std::vector<Core::HID::NpadIdType> supported_npad_id_types{};
     NpadJoyHoldType hold_type{NpadJoyHoldType::Vertical};
     NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
     NpadCommunicationMode communication_mode{NpadCommunicationMode::Default};
     bool permit_vibration_session_enabled{false};
     bool analog_stick_use_center_clamp{};
-    GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
-    bool sixaxis_sensors_enabled{true};
-    f32 sixaxis_fusion_parameter1{};
-    f32 sixaxis_fusion_parameter2{};
-    bool sixaxis_at_rest{true};
     bool is_in_lr_assignment_mode{false};
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 96e8fb7e1c..496b55d0ef 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -161,7 +161,7 @@ public:
 private:
     void InitializeVibrationDevice(Kernel::HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
-        const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()};
+        const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
 
         if (applet_resource != nullptr) {
             applet_resource->GetController<Controller_NPad>(HidController::NPad)
@@ -417,6 +417,7 @@ void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) {
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -443,19 +444,18 @@ void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) {
 void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        u32 basic_xpad_id;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
-    applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true);
+    // This function does nothing on 10.0.0+
 
-    LOG_DEBUG(Service_HID,
-              "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
-              parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
-              parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+    LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}",
+                parameters.basic_xpad_id, parameters.applet_resource_user_id);
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
@@ -464,19 +464,18 @@ void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
 void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        u32 basic_xpad_id;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
-    applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false);
+    // This function does nothing on 10.0.0+
 
-    LOG_DEBUG(Service_HID,
-              "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
-              parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
-              parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+    LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}",
+                parameters.basic_xpad_id, parameters.applet_resource_user_id);
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
@@ -485,14 +484,16 @@ void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
 void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        Core::HID::SixAxisSensorHandle sixaxis_handle;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
-    applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true);
+    applet_resource->GetController<Controller_NPad>(HidController::NPad)
+        .SetSixAxisEnabled(parameters.sixaxis_handle, true);
 
     LOG_DEBUG(Service_HID,
               "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -506,14 +507,16 @@ void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
 void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        Core::HID::SixAxisSensorHandle sixaxis_handle;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
-    applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false);
+    applet_resource->GetController<Controller_NPad>(HidController::NPad)
+        .SetSixAxisEnabled(parameters.sixaxis_handle, false);
 
     LOG_DEBUG(Service_HID,
               "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -529,19 +532,23 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) {
     struct Parameters {
         bool enable_sixaxis_sensor_fusion;
         INSERT_PADDING_BYTES_NOINIT(3);
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        Core::HID::SixAxisSensorHandle sixaxis_handle;
         u64 applet_resource_user_id;
     };
     static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
-    LOG_WARNING(Service_HID,
-                "(STUBBED) called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, "
-                "device_index={}, applet_resource_user_id={}",
-                parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type,
-                parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
-                parameters.applet_resource_user_id);
+    applet_resource->GetController<Controller_NPad>(HidController::NPad)
+        .SetSixAxisFusionEnabled(parameters.sixaxis_handle,
+                                 parameters.enable_sixaxis_sensor_fusion);
+
+    LOG_DEBUG(Service_HID,
+              "called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, "
+              "device_index={}, applet_resource_user_id={}",
+              parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type,
+              parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
+              parameters.applet_resource_user_id);
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
@@ -550,9 +557,9 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) {
 void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
-        f32 parameter1;
-        f32 parameter2;
+        Core::HID::SixAxisSensorHandle sixaxis_handle;
+        Core::HID::SixAxisSensorFusionParameters sixaxis_fusion;
+        INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
     static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
@@ -560,14 +567,14 @@ void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
     const auto parameters{rp.PopRaw<Parameters>()};
 
     applet_resource->GetController<Controller_NPad>(HidController::NPad)
-        .SetSixAxisFusionParameters(parameters.parameter1, parameters.parameter2);
+        .SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion);
 
-    LOG_WARNING(Service_HID,
-                "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, parameter1={}, "
-                "parameter2={}, applet_resource_user_id={}",
-                parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
-                parameters.sixaxis_handle.device_index, parameters.parameter1,
-                parameters.parameter2, parameters.applet_resource_user_id);
+    LOG_DEBUG(Service_HID,
+              "called, npad_type={}, npad_id={}, device_index={}, parameter1={}, "
+              "parameter2={}, applet_resource_user_id={}",
+              parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+              parameters.sixaxis_handle.device_index, parameters.sixaxis_fusion.parameter1,
+              parameters.sixaxis_fusion.parameter2, parameters.applet_resource_user_id);
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
@@ -576,35 +583,33 @@ void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
 void Hid::GetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        Core::HID::SixAxisSensorHandle sixaxis_handle;
+        INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
     static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
-    f32 parameter1 = 0;
-    f32 parameter2 = 0;
     const auto parameters{rp.PopRaw<Parameters>()};
 
-    std::tie(parameter1, parameter2) =
+    const auto sixaxis_fusion_parameters =
         applet_resource->GetController<Controller_NPad>(HidController::NPad)
-            .GetSixAxisFusionParameters();
+            .GetSixAxisFusionParameters(parameters.sixaxis_handle);
 
-    LOG_WARNING(
-        Service_HID,
-        "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
-        parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
-        parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+    LOG_DEBUG(Service_HID,
+              "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+              parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+              parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
 
     IPC::ResponseBuilder rb{ctx, 4};
     rb.Push(ResultSuccess);
-    rb.Push(parameter1);
-    rb.Push(parameter2);
+    rb.PushRaw(sixaxis_fusion_parameters);
 }
 
 void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        Core::HID::SixAxisSensorHandle sixaxis_handle;
+        INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
     static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
@@ -612,13 +617,12 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
     const auto parameters{rp.PopRaw<Parameters>()};
 
     applet_resource->GetController<Controller_NPad>(HidController::NPad)
-        .ResetSixAxisFusionParameters();
+        .ResetSixAxisFusionParameters(parameters.sixaxis_handle);
 
-    LOG_WARNING(
-        Service_HID,
-        "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
-        parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
-        parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+    LOG_DEBUG(Service_HID,
+              "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+              parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+              parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
@@ -626,12 +630,12 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
 
 void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
-    const auto sixaxis_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()};
+    const auto sixaxis_handle{rp.PopRaw<Core::HID::SixAxisSensorHandle>()};
     const auto drift_mode{rp.PopEnum<Controller_NPad::GyroscopeZeroDriftMode>()};
     const auto applet_resource_user_id{rp.Pop<u64>()};
 
     applet_resource->GetController<Controller_NPad>(HidController::NPad)
-        .SetGyroscopeZeroDriftMode(drift_mode);
+        .SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode);
 
     LOG_DEBUG(Service_HID,
               "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, "
@@ -646,10 +650,11 @@ void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
 void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        Core::HID::SixAxisSensorHandle sixaxis_handle;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -661,21 +666,23 @@ void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
     IPC::ResponseBuilder rb{ctx, 3};
     rb.Push(ResultSuccess);
     rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
-                    .GetGyroscopeZeroDriftMode());
+                    .GetGyroscopeZeroDriftMode(parameters.sixaxis_handle));
 }
 
 void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        Core::HID::SixAxisSensorHandle sixaxis_handle;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
+    const auto drift_mode{Controller_NPad::GyroscopeZeroDriftMode::Standard};
 
     applet_resource->GetController<Controller_NPad>(HidController::NPad)
-        .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode::Standard);
+        .SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
 
     LOG_DEBUG(Service_HID,
               "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -689,10 +696,11 @@ void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
 void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        Core::HID::SixAxisSensorHandle sixaxis_handle;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -704,16 +712,17 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
     IPC::ResponseBuilder rb{ctx, 3};
     rb.Push(ResultSuccess);
     rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad)
-                .IsSixAxisSensorAtRest());
+                .IsSixAxisSensorAtRest(parameters.sixaxis_handle));
 }
 
 void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        Core::HID::SixAxisSensorHandle sixaxis_handle;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -735,13 +744,14 @@ void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) {
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
     applet_resource->ActivateController(HidController::Gesture);
 
-    LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown,
-              parameters.applet_resource_user_id);
+    LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}",
+                parameters.unknown, parameters.applet_resource_user_id);
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
@@ -749,12 +759,20 @@ void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) {
 
 void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
-    const auto supported_styleset{rp.Pop<u32>()};
+    struct Parameters {
+        Core::HID::NpadStyleSet supported_styleset;
+        INSERT_PADDING_WORDS_NOINIT(1);
+        u64 applet_resource_user_id;
+    };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+    const auto parameters{rp.PopRaw<Parameters>()};
 
     applet_resource->GetController<Controller_NPad>(HidController::NPad)
-        .SetSupportedStyleSet({supported_styleset});
+        .SetSupportedStyleSet({parameters.supported_styleset});
 
-    LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset);
+    LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}",
+              parameters.supported_styleset, parameters.applet_resource_user_id);
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
@@ -768,9 +786,9 @@ void Hid::GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
 
     IPC::ResponseBuilder rb{ctx, 3};
     rb.Push(ResultSuccess);
-    rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad)
-                .GetSupportedStyleSet()
-                .raw);
+    rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
+                    .GetSupportedStyleSet()
+                    .raw);
 }
 
 void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
@@ -813,11 +831,12 @@ void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) {
 void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        u32 npad_id;
+        Core::HID::NpadIdType npad_id;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
         u64 unknown;
     };
+    static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -833,10 +852,11 @@ void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
 void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        u32 npad_id;
+        Core::HID::NpadIdType npad_id;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -852,7 +872,7 @@ void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) {
 
 void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
-    const auto npad_id{rp.Pop<u32>()};
+    const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
 
     LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
 
@@ -867,16 +887,17 @@ void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) {
     // Should have no effect with how our npad sets up the data
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        u32 unknown;
+        s32 revision;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
     applet_resource->ActivateController(HidController::NPad);
 
-    LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown,
+    LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision,
               parameters.applet_resource_user_id);
 
     IPC::ResponseBuilder rb{ctx, 2};
@@ -911,10 +932,11 @@ void Hid::GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
 void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        u32 npad_id;
+        Core::HID::NpadIdType npad_id;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -932,11 +954,12 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
     // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        u32 npad_id;
+        Core::HID::NpadIdType npad_id;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
         u64 npad_joy_device_type;
     };
+    static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -955,10 +978,11 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
 void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        u32 npad_id;
+        Core::HID::NpadIdType npad_id;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -974,8 +998,8 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
 
 void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
-    const auto npad_id_1{rp.Pop<u32>()};
-    const auto npad_id_2{rp.Pop<u32>()};
+    const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
+    const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
     const auto applet_resource_user_id{rp.Pop<u64>()};
 
     applet_resource->GetController<Controller_NPad>(HidController::NPad)
@@ -1041,8 +1065,8 @@ void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
 
 void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
-    const auto npad_id_1{rp.Pop<u32>()};
-    const auto npad_id_2{rp.Pop<u32>()};
+    const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
+    const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
     const auto applet_resource_user_id{rp.Pop<u64>()};
 
     const bool res = applet_resource->GetController<Controller_NPad>(HidController::NPad)
@@ -1063,10 +1087,11 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
 void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        u32 npad_id;
+        Core::HID::NpadIdType npad_id;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -1084,9 +1109,10 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c
     struct Parameters {
         bool unintended_home_button_input_protection;
         INSERT_PADDING_BYTES_NOINIT(3);
-        u32 npad_id;
+        Core::HID::NpadIdType npad_id;
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -1108,6 +1134,7 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
         bool analog_stick_use_center_clamp;
+        INSERT_PADDING_BYTES_NOINIT(7);
         u64 applet_resource_user_id;
     };
     static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
@@ -1127,7 +1154,7 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
 
 void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
-    const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()};
+    const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
 
     Core::HID::VibrationDeviceInfo vibration_device_info;
 
@@ -1149,13 +1176,13 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
     }
 
     switch (vibration_device_handle.device_index) {
-    case Controller_NPad::DeviceIndex::Left:
+    case Core::HID::DeviceIndex::Left:
         vibration_device_info.position = Core::HID::VibrationDevicePosition::Left;
         break;
-    case Controller_NPad::DeviceIndex::Right:
+    case Core::HID::DeviceIndex::Right:
         vibration_device_info.position = Core::HID::VibrationDevicePosition::Right;
         break;
-    case Controller_NPad::DeviceIndex::None:
+    case Core::HID::DeviceIndex::None:
     default:
         UNREACHABLE_MSG("DeviceIndex should never be None!");
         vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
@@ -1173,11 +1200,12 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
 void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle vibration_device_handle;
-        Controller_NPad::VibrationValue vibration_value;
+        Core::HID::VibrationDeviceHandle vibration_device_handle;
+        Core::HID::VibrationValue vibration_value;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -1197,10 +1225,11 @@ void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
 void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle vibration_device_handle;
+        Core::HID::VibrationDeviceHandle vibration_device_handle;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -1251,10 +1280,10 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
     const auto handles = ctx.ReadBuffer(0);
     const auto vibrations = ctx.ReadBuffer(1);
 
-    std::vector<Controller_NPad::DeviceHandle> vibration_device_handles(
-        handles.size() / sizeof(Controller_NPad::DeviceHandle));
-    std::vector<Controller_NPad::VibrationValue> vibration_values(
-        vibrations.size() / sizeof(Controller_NPad::VibrationValue));
+    std::vector<Core::HID::VibrationDeviceHandle> vibration_device_handles(
+        handles.size() / sizeof(Core::HID::VibrationDeviceHandle));
+    std::vector<Core::HID::VibrationValue> vibration_values(vibrations.size() /
+                                                            sizeof(Core::HID::VibrationValue));
 
     std::memcpy(vibration_device_handles.data(), handles.data(), handles.size());
     std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size());
@@ -1271,7 +1300,8 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
 void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle vibration_device_handle;
+        Core::HID::VibrationDeviceHandle vibration_device_handle;
+        INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
         Core::HID::VibrationGcErmCommand gc_erm_command;
     };
@@ -1288,25 +1318,25 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
     const auto vibration_value = [parameters] {
         switch (parameters.gc_erm_command) {
         case Core::HID::VibrationGcErmCommand::Stop:
-            return Controller_NPad::VibrationValue{
-                .amp_low = 0.0f,
-                .freq_low = 160.0f,
-                .amp_high = 0.0f,
-                .freq_high = 320.0f,
+            return Core::HID::VibrationValue{
+                .low_amplitude = 0.0f,
+                .low_frequency = 160.0f,
+                .high_amplitude = 0.0f,
+                .high_frequency = 320.0f,
             };
         case Core::HID::VibrationGcErmCommand::Start:
-            return Controller_NPad::VibrationValue{
-                .amp_low = 1.0f,
-                .freq_low = 160.0f,
-                .amp_high = 1.0f,
-                .freq_high = 320.0f,
+            return Core::HID::VibrationValue{
+                .low_amplitude = 1.0f,
+                .low_frequency = 160.0f,
+                .high_amplitude = 1.0f,
+                .high_frequency = 320.0f,
             };
         case Core::HID::VibrationGcErmCommand::StopHard:
-            return Controller_NPad::VibrationValue{
-                .amp_low = 0.0f,
-                .freq_low = 0.0f,
-                .amp_high = 0.0f,
-                .freq_high = 0.0f,
+            return Core::HID::VibrationValue{
+                .low_amplitude = 0.0f,
+                .low_frequency = 0.0f,
+                .high_amplitude = 0.0f,
+                .high_frequency = 0.0f,
             };
         default:
             return Controller_NPad::DEFAULT_VIBRATION_VALUE;
@@ -1331,7 +1361,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
 void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle vibration_device_handle;
+        Core::HID::VibrationDeviceHandle vibration_device_handle;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
@@ -1342,7 +1372,7 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
                                     .GetLastVibration(parameters.vibration_device_handle);
 
     const auto gc_erm_command = [last_vibration] {
-        if (last_vibration.amp_low != 0.0f || last_vibration.amp_high != 0.0f) {
+        if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) {
             return Core::HID::VibrationGcErmCommand::Start;
         }
 
@@ -1352,7 +1382,7 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
          * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands.
          * This is done to reuse the controller vibration functions made for regular controllers.
          */
-        if (last_vibration.freq_low == 0.0f && last_vibration.freq_high == 0.0f) {
+        if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) {
             return Core::HID::VibrationGcErmCommand::StopHard;
         }
 
@@ -1396,10 +1426,11 @@ void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) {
 void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle vibration_device_handle;
+        Core::HID::VibrationDeviceHandle vibration_device_handle;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
@@ -1430,18 +1461,18 @@ void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
 void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
-    LOG_WARNING(
-        Service_HID,
-        "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
-        parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
-        parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+    LOG_WARNING(Service_HID,
+                "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
+                parameters.console_sixaxis_handle.unknown_1,
+                parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
@@ -1450,18 +1481,18 @@ void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
 void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     struct Parameters {
-        Controller_NPad::DeviceHandle sixaxis_handle;
+        Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
         INSERT_PADDING_WORDS_NOINIT(1);
         u64 applet_resource_user_id;
     };
+    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 
     const auto parameters{rp.PopRaw<Parameters>()};
 
-    LOG_WARNING(
-        Service_HID,
-        "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
-        parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
-        parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+    LOG_WARNING(Service_HID,
+                "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
+                parameters.console_sixaxis_handle.unknown_1,
+                parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
@@ -1615,10 +1646,8 @@ void Hid::SetNpadCommunicationMode(Kernel::HLERequestContext& ctx) {
 
 void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
-    const auto applet_resource_user_id{rp.Pop<u64>()};
 
-    LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
-                applet_resource_user_id);
+    LOG_WARNING(Service_HID, "(STUBBED) called");
 
     IPC::ResponseBuilder rb{ctx, 4};
     rb.Push(ResultSuccess);
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 76f55eb54b..0254ea6fe1 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -627,7 +627,8 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
         return;
     }
 
-    const auto devices = emulated_controller->GetMappedDevices(Core::HID::DeviceIndex::AllDevices);
+    const auto devices =
+        emulated_controller->GetMappedDevices(Core::HID::EmulatedDeviceIndex::AllDevices);
     UpdateInputDevices();
 
     if (devices.empty()) {
@@ -846,6 +847,7 @@ void ConfigureInputPlayer::SetConnectableControllers() {
 
     if (!is_powered_on) {
         add_controllers(true);
+        return;
     }
 
     add_controllers(false, hid_core.GetSupportedStyleTag());
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index ff40f57f55..6630321cb6 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -357,7 +357,8 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
     DrawCircle(p, center + QPoint(26, 71), 5);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(-170, -140), battery_values[Core::HID::DeviceIndex::LeftIndex]);
+    DrawBattery(p, center + QPoint(-170, -140),
+                battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
 }
 
 void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) {
@@ -483,7 +484,8 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
     DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(110, -140), battery_values[Core::HID::DeviceIndex::RightIndex]);
+    DrawBattery(p, center + QPoint(110, -140),
+                battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
 }
 
 void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) {
@@ -619,8 +621,10 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
     DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(-100, -160), battery_values[Core::HID::DeviceIndex::LeftIndex]);
-    DrawBattery(p, center + QPoint(40, -160), battery_values[Core::HID::DeviceIndex::RightIndex]);
+    DrawBattery(p, center + QPoint(-100, -160),
+                battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
+    DrawBattery(p, center + QPoint(40, -160),
+                battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
 }
 
 void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) {
@@ -721,8 +725,10 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
     DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(-200, 110), battery_values[Core::HID::DeviceIndex::LeftIndex]);
-    DrawBattery(p, center + QPoint(130, 110), battery_values[Core::HID::DeviceIndex::RightIndex]);
+    DrawBattery(p, center + QPoint(-200, 110),
+                battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
+    DrawBattery(p, center + QPoint(130, 110),
+                battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
 }
 
 void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) {
@@ -812,7 +818,8 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
     DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(-30, -160), battery_values[Core::HID::DeviceIndex::LeftIndex]);
+    DrawBattery(p, center + QPoint(-30, -160),
+                battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
 }
 
 void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
@@ -868,7 +875,8 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
     DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8);
 
     // Draw battery
-    DrawBattery(p, center + QPoint(-30, -165), battery_values[Core::HID::DeviceIndex::LeftIndex]);
+    DrawBattery(p, center + QPoint(-30, -165),
+                battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
 }
 
 constexpr std::array<float, 13 * 2> symbol_a = {

From 7fcfe24a3edff903871bee6c249d97e64648ddfa Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sat, 13 Nov 2021 02:39:01 -0600
Subject: [PATCH 75/88] core/hid: Fix keyboard alignment

---
 src/core/hid/hid_types.h                      | 25 ++++++++++---------
 .../hle/service/hid/controllers/keyboard.cpp  |  1 +
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index f224cb7443..41bc65ce20 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -423,20 +423,21 @@ static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incor
 // This is nn::hid::KeyboardModifier
 struct KeyboardModifier {
     union {
-        u32 raw{};
-        BitField<0, 1, u32> control;
-        BitField<1, 1, u32> shift;
-        BitField<2, 1, u32> left_alt;
-        BitField<3, 1, u32> right_alt;
-        BitField<4, 1, u32> gui;
-        BitField<8, 1, u32> caps_lock;
-        BitField<9, 1, u32> scroll_lock;
-        BitField<10, 1, u32> num_lock;
-        BitField<11, 1, u32> katakana;
-        BitField<12, 1, u32> hiragana;
+        u64 raw{};
+        BitField<0, 1, u64> control;
+        BitField<1, 1, u64> shift;
+        BitField<2, 1, u64> left_alt;
+        BitField<3, 1, u64> right_alt;
+        BitField<4, 1, u64> gui;
+        BitField<8, 1, u64> caps_lock;
+        BitField<9, 1, u64> scroll_lock;
+        BitField<10, 1, u64> num_lock;
+        BitField<11, 1, u64> katakana;
+        BitField<12, 1, u64> hiragana;
+        BitField<32, 1, u64> unknown;
     };
 };
-static_assert(sizeof(KeyboardModifier) == 0x4, "KeyboardModifier is an invalid size");
+static_assert(sizeof(KeyboardModifier) == 0x8, "KeyboardModifier is an invalid size");
 
 // This is nn::hid::KeyboardKey
 struct KeyboardKey {
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 1dc219bf59..d6505dbc51 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -42,6 +42,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
 
         next_state.key = keyboard_state;
         next_state.modifier = keyboard_modifier_state;
+        next_state.modifier.unknown.Assign(1);
     }
 
     keyboard_lifo.WriteNextEntry(next_state);

From b673857d7dfc72f38d9242b315cd590b859795ff Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sat, 13 Nov 2021 23:25:45 -0600
Subject: [PATCH 76/88] core/hid: Improve accuracy of the keyboard
 implementation

---
 src/common/settings_input.h                   |  35 +-
 src/core/hid/emulated_devices.cpp             |   3 +-
 src/core/hid/hid_types.h                      | 398 ++++++++++++------
 .../hle/service/hid/controllers/keyboard.cpp  |   1 +
 src/core/hle/service/hid/hid.cpp              |  35 +-
 src/core/hle/service/hid/hid.h                |   2 +
 src/input_common/drivers/keyboard.cpp         |  53 ++-
 src/input_common/drivers/keyboard.h           |   7 +
 src/input_common/main.cpp                     |   9 +
 src/input_common/main.h                       |   3 +
 src/yuzu/bootmanager.cpp                      | 276 +++++++++++-
 src/yuzu/bootmanager.h                        |   6 +
 src/yuzu/configuration/config.cpp             | 167 +-------
 13 files changed, 682 insertions(+), 313 deletions(-)

diff --git a/src/common/settings_input.h b/src/common/settings_input.h
index 2c0eb31d39..a2982fca46 100644
--- a/src/common/settings_input.h
+++ b/src/common/settings_input.h
@@ -129,7 +129,6 @@ extern const std::array<const char*, NumMouseButtons> mapping;
 namespace NativeKeyboard {
 enum Keys {
     None,
-    Error,
 
     A = 4,
     B,
@@ -167,22 +166,22 @@ enum Keys {
     N8,
     N9,
     N0,
-    Enter,
+    Return,
     Escape,
     Backspace,
     Tab,
     Space,
     Minus,
-    Equal,
-    LeftBrace,
-    RightBrace,
-    Backslash,
+    Plus,
+    OpenBracket,
+    CloseBracket,
+    Pipe,
     Tilde,
     Semicolon,
-    Apostrophe,
-    Grave,
+    Quote,
+    Backquote,
     Comma,
-    Dot,
+    Period,
     Slash,
     CapsLockKey,
 
@@ -199,7 +198,7 @@ enum Keys {
     F11,
     F12,
 
-    SystemRequest,
+    PrintScreen,
     ScrollLockKey,
     Pause,
     Insert,
@@ -268,8 +267,18 @@ enum Keys {
     ScrollLockActive,
     KPComma,
 
-    KPLeftParenthesis,
-    KPRightParenthesis,
+    Ro = 0x87,
+    KatakanaHiragana,
+    Yen,
+    Henkan,
+    Muhenkan,
+    NumPadCommaPc98,
+
+    HangulEnglish = 0x90,
+    Hanja,
+    KatakanaKey,
+    HiraganaKey,
+    ZenkakuHankaku,
 
     LeftControlKey = 0xE0,
     LeftShiftKey,
@@ -318,6 +327,8 @@ enum Modifiers {
     CapsLock,
     ScrollLock,
     NumLock,
+    Katakana,
+    Hiragana,
 
     NumKeyboardMods,
 };
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
index e97470240e..0d840a0035 100644
--- a/src/core/hid/emulated_devices.cpp
+++ b/src/core/hid/emulated_devices.cpp
@@ -170,13 +170,14 @@ void EmulatedDevices::SetKeyboardButton(Common::Input::CallbackStatus callback,
         return;
     }
 
+    // Index should be converted from NativeKeyboard to KeyboardKeyIndex
     UpdateKey(index, current_status.value);
 
     TriggerOnChange(DeviceTriggerType::Keyboard);
 }
 
 void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) {
-    constexpr u8 KEYS_PER_BYTE = 8;
+    constexpr std::size_t KEYS_PER_BYTE = 8;
     auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE];
     const u8 mask = static_cast<u8>(1 << (key_index % KEYS_PER_BYTE));
     if (status) {
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 41bc65ce20..af95f3aff9 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -12,6 +12,195 @@
 
 namespace Core::HID {
 
+enum class DeviceIndex : u8 {
+    Left = 0,
+    Right = 1,
+    None = 2,
+    MaxDeviceIndex = 3,
+};
+
+// This is nn::hid::NpadButton
+enum class NpadButton : u64 {
+    None = 0,
+    A = 1U << 0,
+    B = 1U << 1,
+    X = 1U << 2,
+    Y = 1U << 3,
+    StickL = 1U << 4,
+    StickR = 1U << 5,
+    L = 1U << 6,
+    R = 1U << 7,
+    ZL = 1U << 8,
+    ZR = 1U << 9,
+    Plus = 1U << 10,
+    Minus = 1U << 11,
+
+    Left = 1U << 12,
+    Up = 1U << 13,
+    Right = 1U << 14,
+    Down = 1U << 15,
+
+    StickLLeft = 1U << 16,
+    StickLUp = 1U << 17,
+    StickLRight = 1U << 18,
+    StickLDown = 1U << 19,
+
+    StickRLeft = 1U << 20,
+    StickRUp = 1U << 21,
+    StickRRight = 1U << 22,
+    StickRDown = 1U << 23,
+
+    LeftSL = 1U << 24,
+    LeftSR = 1U << 25,
+
+    RightSL = 1U << 26,
+    RightSR = 1U << 27,
+
+    Palma = 1U << 28,
+    Verification = 1U << 29,
+    HandheldLeftB = 1U << 30,
+    LagonCLeft = 1U << 31,
+    LagonCUp = 1ULL << 32,
+    LagonCRight = 1ULL << 33,
+    LagonCDown = 1ULL << 34,
+};
+DECLARE_ENUM_FLAG_OPERATORS(NpadButton);
+
+enum class KeyboardKeyIndex : u32 {
+    A = 4,
+    B = 5,
+    C = 6,
+    D = 7,
+    E = 8,
+    F = 9,
+    G = 10,
+    H = 11,
+    I = 12,
+    J = 13,
+    K = 14,
+    L = 15,
+    M = 16,
+    N = 17,
+    O = 18,
+    P = 19,
+    Q = 20,
+    R = 21,
+    S = 22,
+    T = 23,
+    U = 24,
+    V = 25,
+    W = 26,
+    X = 27,
+    Y = 28,
+    Z = 29,
+    D1 = 30,
+    D2 = 31,
+    D3 = 32,
+    D4 = 33,
+    D5 = 34,
+    D6 = 35,
+    D7 = 36,
+    D8 = 37,
+    D9 = 38,
+    D0 = 39,
+    Return = 40,
+    Escape = 41,
+    Backspace = 42,
+    Tab = 43,
+    Space = 44,
+    Minus = 45,
+    Plus = 46,
+    OpenBracket = 47,
+    CloseBracket = 48,
+    Pipe = 49,
+    Tilde = 50,
+    Semicolon = 51,
+    Quote = 52,
+    Backquote = 53,
+    Comma = 54,
+    Period = 55,
+    Slash = 56,
+    CapsLock = 57,
+    F1 = 58,
+    F2 = 59,
+    F3 = 60,
+    F4 = 61,
+    F5 = 62,
+    F6 = 63,
+    F7 = 64,
+    F8 = 65,
+    F9 = 66,
+    F10 = 67,
+    F11 = 68,
+    F12 = 69,
+    PrintScreen = 70,
+    ScrollLock = 71,
+    Pause = 72,
+    Insert = 73,
+    Home = 74,
+    PageUp = 75,
+    Delete = 76,
+    End = 77,
+    PageDown = 78,
+    RightArrow = 79,
+    LeftArrow = 80,
+    DownArrow = 81,
+    UpArrow = 82,
+    NumLock = 83,
+    NumPadDivide = 84,
+    NumPadMultiply = 85,
+    NumPadSubtract = 86,
+    NumPadAdd = 87,
+    NumPadEnter = 88,
+    NumPad1 = 89,
+    NumPad2 = 90,
+    NumPad3 = 91,
+    NumPad4 = 92,
+    NumPad5 = 93,
+    NumPad6 = 94,
+    NumPad7 = 95,
+    NumPad8 = 96,
+    NumPad9 = 97,
+    NumPad0 = 98,
+    NumPadDot = 99,
+    Backslash = 100,
+    Application = 101,
+    Power = 102,
+    NumPadEquals = 103,
+    F13 = 104,
+    F14 = 105,
+    F15 = 106,
+    F16 = 107,
+    F17 = 108,
+    F18 = 109,
+    F19 = 110,
+    F20 = 111,
+    F21 = 112,
+    F22 = 113,
+    F23 = 114,
+    F24 = 115,
+    NumPadComma = 133,
+    Ro = 135,
+    KatakanaHiragana = 136,
+    Yen = 137,
+    Henkan = 138,
+    Muhenkan = 139,
+    NumPadCommaPc98 = 140,
+    HangulEnglish = 144,
+    Hanja = 145,
+    Katakana = 146,
+    Hiragana = 147,
+    ZenkakuHankaku = 148,
+    LeftControl = 224,
+    LeftShift = 225,
+    LeftAlt = 226,
+    LeftGui = 227,
+    RightControl = 228,
+    RightShift = 229,
+    RightAlt = 230,
+    RightGui = 231,
+};
+
 // This is nn::hid::NpadIdType
 enum class NpadIdType : u32 {
     Player1 = 0x0,
@@ -28,62 +217,6 @@ enum class NpadIdType : u32 {
     Invalid = 0xFFFFFFFF,
 };
 
-/// Converts a NpadIdType to an array index.
-constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
-    switch (npad_id_type) {
-    case NpadIdType::Player1:
-        return 0;
-    case NpadIdType::Player2:
-        return 1;
-    case NpadIdType::Player3:
-        return 2;
-    case NpadIdType::Player4:
-        return 3;
-    case NpadIdType::Player5:
-        return 4;
-    case NpadIdType::Player6:
-        return 5;
-    case NpadIdType::Player7:
-        return 6;
-    case NpadIdType::Player8:
-        return 7;
-    case NpadIdType::Handheld:
-        return 8;
-    case NpadIdType::Other:
-        return 9;
-    default:
-        return 0;
-    }
-}
-
-/// Converts an array index to a NpadIdType
-constexpr NpadIdType IndexToNpadIdType(size_t index) {
-    switch (index) {
-    case 0:
-        return NpadIdType::Player1;
-    case 1:
-        return NpadIdType::Player2;
-    case 2:
-        return NpadIdType::Player3;
-    case 3:
-        return NpadIdType::Player4;
-    case 4:
-        return NpadIdType::Player5;
-    case 5:
-        return NpadIdType::Player6;
-    case 6:
-        return NpadIdType::Player7;
-    case 7:
-        return NpadIdType::Player8;
-    case 8:
-        return NpadIdType::Handheld;
-    case 9:
-        return NpadIdType::Other;
-    default:
-        return NpadIdType::Invalid;
-    }
-}
-
 // This is nn::hid::NpadStyleIndex
 enum class NpadStyleIndex : u8 {
     None = 0,
@@ -124,6 +257,27 @@ enum class NpadStyleSet : u32 {
 };
 static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
 
+// This is nn::hid::VibrationDevicePosition
+enum class VibrationDevicePosition : u32 {
+    None = 0,
+    Left = 1,
+    Right = 2,
+};
+
+// This is nn::hid::VibrationDeviceType
+enum class VibrationDeviceType : u32 {
+    Unknown = 0,
+    LinearResonantActuator = 1,
+    GcErm = 2,
+};
+
+// This is nn::hid::VibrationGcErmCommand
+enum class VibrationGcErmCommand : u64 {
+    Stop = 0,
+    Start = 1,
+    StopHard = 2,
+};
+
 // This is nn::hid::NpadStyleTag
 struct NpadStyleTag {
     union {
@@ -220,53 +374,6 @@ struct LedPattern {
     };
 };
 
-// This is nn::hid::NpadButton
-enum class NpadButton : u64 {
-    None = 0,
-    A = 1U << 0,
-    B = 1U << 1,
-    X = 1U << 2,
-    Y = 1U << 3,
-    StickL = 1U << 4,
-    StickR = 1U << 5,
-    L = 1U << 6,
-    R = 1U << 7,
-    ZL = 1U << 8,
-    ZR = 1U << 9,
-    Plus = 1U << 10,
-    Minus = 1U << 11,
-
-    Left = 1U << 12,
-    Up = 1U << 13,
-    Right = 1U << 14,
-    Down = 1U << 15,
-
-    StickLLeft = 1U << 16,
-    StickLUp = 1U << 17,
-    StickLRight = 1U << 18,
-    StickLDown = 1U << 19,
-
-    StickRLeft = 1U << 20,
-    StickRUp = 1U << 21,
-    StickRRight = 1U << 22,
-    StickRDown = 1U << 23,
-
-    LeftSL = 1U << 24,
-    LeftSR = 1U << 25,
-
-    RightSL = 1U << 26,
-    RightSR = 1U << 27,
-
-    Palma = 1U << 28,
-    Verification = 1U << 29,
-    HandheldLeftB = 1U << 30,
-    LagonCLeft = 1U << 31,
-    LagonCUp = 1ULL << 32,
-    LagonCRight = 1ULL << 33,
-    LagonCDown = 1ULL << 34,
-};
-DECLARE_ENUM_FLAG_OPERATORS(NpadButton);
-
 struct NpadButtonState {
     union {
         NpadButton raw{};
@@ -342,13 +449,6 @@ struct DebugPadButton {
 };
 static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size");
 
-enum class DeviceIndex : u8 {
-    Left = 0,
-    Right = 1,
-    None = 2,
-    MaxDeviceIndex = 3,
-};
-
 // This is nn::hid::ConsoleSixAxisSensorHandle
 struct ConsoleSixAxisSensorHandle {
     u8 unknown_1;
@@ -383,20 +483,6 @@ struct VibrationDeviceHandle {
 };
 static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size");
 
-// This is nn::hid::VibrationDeviceType
-enum class VibrationDeviceType : u32 {
-    Unknown = 0,
-    LinearResonantActuator = 1,
-    GcErm = 2,
-};
-
-// This is nn::hid::VibrationDevicePosition
-enum class VibrationDevicePosition : u32 {
-    None = 0,
-    Left = 1,
-    Right = 2,
-};
-
 // This is nn::hid::VibrationValue
 struct VibrationValue {
     f32 low_amplitude;
@@ -406,13 +492,6 @@ struct VibrationValue {
 };
 static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size.");
 
-// This is nn::hid::VibrationGcErmCommand
-enum class VibrationGcErmCommand : u64 {
-    Stop = 0,
-    Start = 1,
-    StopHard = 2,
-};
-
 // This is nn::hid::VibrationDeviceInfo
 struct VibrationDeviceInfo {
     VibrationDeviceType type{};
@@ -482,4 +561,61 @@ struct MouseState {
     MouseAttribute attribute;
 };
 static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size");
+
+/// Converts a NpadIdType to an array index.
+constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
+    switch (npad_id_type) {
+    case NpadIdType::Player1:
+        return 0;
+    case NpadIdType::Player2:
+        return 1;
+    case NpadIdType::Player3:
+        return 2;
+    case NpadIdType::Player4:
+        return 3;
+    case NpadIdType::Player5:
+        return 4;
+    case NpadIdType::Player6:
+        return 5;
+    case NpadIdType::Player7:
+        return 6;
+    case NpadIdType::Player8:
+        return 7;
+    case NpadIdType::Handheld:
+        return 8;
+    case NpadIdType::Other:
+        return 9;
+    default:
+        return 0;
+    }
+}
+
+/// Converts an array index to a NpadIdType
+constexpr NpadIdType IndexToNpadIdType(size_t index) {
+    switch (index) {
+    case 0:
+        return NpadIdType::Player1;
+    case 1:
+        return NpadIdType::Player2;
+    case 2:
+        return NpadIdType::Player3;
+    case 3:
+        return NpadIdType::Player4;
+    case 4:
+        return NpadIdType::Player5;
+    case 5:
+        return NpadIdType::Player6;
+    case 6:
+        return NpadIdType::Player7;
+    case 7:
+        return NpadIdType::Player8;
+    case 8:
+        return NpadIdType::Handheld;
+    case 9:
+        return NpadIdType::Other;
+    default:
+        return NpadIdType::Invalid;
+    }
+}
+
 } // namespace Core::HID
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index d6505dbc51..0ef8af0e69 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -42,6 +42,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
 
         next_state.key = keyboard_state;
         next_state.modifier = keyboard_modifier_state;
+        // This is always enabled on HW. Check what it actually does
         next_state.modifier.unknown.Assign(1);
     }
 
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 496b55d0ef..e740b43314 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -35,8 +35,9 @@ namespace Service::HID {
 
 // Updating period for each HID device.
 // Period time is obtained by measuring the number of samples in a second on HW using a homebrew
-constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000};    // (4ms, 250Hz)
-constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
+constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000};      // (4ms, 250Hz)
+constexpr auto keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
+constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000};   // (5ms, 200Hz)
 constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
 
 IAppletResource::IAppletResource(Core::System& system_,
@@ -78,14 +79,21 @@ IAppletResource::IAppletResource(Core::System& system_,
             const auto guard = LockService();
             UpdateControllers(user_data, ns_late);
         });
+    keyboard_update_event = Core::Timing::CreateEvent(
+        "HID::UpdatekeyboardCallback",
+        [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
+            const auto guard = LockService();
+            UpdateKeyboard(user_data, ns_late);
+        });
     motion_update_event = Core::Timing::CreateEvent(
-        "HID::MotionPadCallback",
+        "HID::UpdateMotionCallback",
         [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
             const auto guard = LockService();
             UpdateMotion(user_data, ns_late);
         });
 
     system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
+    system.CoreTiming().ScheduleEvent(keyboard_update_ns, keyboard_update_event);
     system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event);
 
     system.HIDCore().ReloadInputDevices();
@@ -101,6 +109,7 @@ void IAppletResource::DeactivateController(HidController controller) {
 
 IAppletResource::~IAppletResource() {
     system.CoreTiming().UnscheduleEvent(pad_update_event, 0);
+    system.CoreTiming().UnscheduleEvent(keyboard_update_event, 0);
     system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
 }
 
@@ -117,18 +126,36 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
     auto& core_timing = system.CoreTiming();
 
     for (const auto& controller : controllers) {
+        // Keyboard has it's own update event
+        if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) {
+            continue;
+        }
         controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(),
                              SHARED_MEMORY_SIZE);
     }
 
     // If ns_late is higher than the update rate ignore the delay
-    if (ns_late > motion_update_ns) {
+    if (ns_late > pad_update_ns) {
         ns_late = {};
     }
 
     core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);
 }
 
+void IAppletResource::UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
+    auto& core_timing = system.CoreTiming();
+
+    controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(
+        core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
+
+    // If ns_late is higher than the update rate ignore the delay
+    if (ns_late > keyboard_update_ns) {
+        ns_late = {};
+    }
+
+    core_timing.ScheduleEvent(keyboard_update_ns - ns_late, keyboard_update_event);
+}
+
 void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
     auto& core_timing = system.CoreTiming();
 
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 973e6a8acf..bbad165f89 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -70,11 +70,13 @@ private:
 
     void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
     void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
+    void UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
     void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
 
     KernelHelpers::ServiceContext& service_context;
 
     std::shared_ptr<Core::Timing::EventType> pad_update_event;
+    std::shared_ptr<Core::Timing::EventType> keyboard_update_event;
     std::shared_ptr<Core::Timing::EventType> motion_update_event;
 
     std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp
index 549704e89a..328fe1ac16 100644
--- a/src/input_common/drivers/keyboard.cpp
+++ b/src/input_common/drivers/keyboard.cpp
@@ -3,26 +3,71 @@
 // Refer to the license.txt file included
 
 #include "common/param_package.h"
+#include "common/settings_input.h"
 #include "input_common/drivers/keyboard.h"
 
 namespace InputCommon {
 
-constexpr PadIdentifier identifier = {
+constexpr PadIdentifier key_identifier = {
     .guid = Common::UUID{Common::INVALID_UUID},
     .port = 0,
     .pad = 0,
 };
+constexpr PadIdentifier modifier_identifier = {
+    .guid = Common::UUID{Common::INVALID_UUID},
+    .port = 0,
+    .pad = 1,
+};
 
 Keyboard::Keyboard(const std::string& input_engine_) : InputEngine(input_engine_) {
-    PreSetController(identifier);
+    PreSetController(key_identifier);
+    PreSetController(modifier_identifier);
 }
 
 void Keyboard::PressKey(int key_code) {
-    SetButton(identifier, key_code, true);
+    SetButton(key_identifier, key_code, true);
 }
 
 void Keyboard::ReleaseKey(int key_code) {
-    SetButton(identifier, key_code, false);
+    SetButton(key_identifier, key_code, false);
+}
+
+void Keyboard::SetModifiers(int key_modifiers) {
+    for (int i = 0; i < 32; ++i) {
+        bool key_value = ((key_modifiers >> i) & 0x1) != 0;
+        SetButton(modifier_identifier, i, key_value);
+        // Use the modifier to press the key button equivalent
+        switch (i) {
+        case Settings::NativeKeyboard::LeftControl:
+            SetButton(key_identifier, Settings::NativeKeyboard::LeftControlKey, key_value);
+            break;
+        case Settings::NativeKeyboard::LeftShift:
+            SetButton(key_identifier, Settings::NativeKeyboard::LeftShiftKey, key_value);
+            break;
+        case Settings::NativeKeyboard::LeftAlt:
+            SetButton(key_identifier, Settings::NativeKeyboard::LeftAltKey, key_value);
+            break;
+        case Settings::NativeKeyboard::LeftMeta:
+            SetButton(key_identifier, Settings::NativeKeyboard::LeftMetaKey, key_value);
+            break;
+        case Settings::NativeKeyboard::RightControl:
+            SetButton(key_identifier, Settings::NativeKeyboard::RightControlKey, key_value);
+            break;
+        case Settings::NativeKeyboard::RightShift:
+            SetButton(key_identifier, Settings::NativeKeyboard::RightShiftKey, key_value);
+            break;
+        case Settings::NativeKeyboard::RightAlt:
+            SetButton(key_identifier, Settings::NativeKeyboard::RightAltKey, key_value);
+            break;
+        case Settings::NativeKeyboard::RightMeta:
+            SetButton(key_identifier, Settings::NativeKeyboard::RightMetaKey, key_value);
+            break;
+        default:
+            // Other modifier keys should be pressed with PressKey since they stay enabled until
+            // next press
+            break;
+        }
+    }
 }
 
 void Keyboard::ReleaseAllKeys() {
diff --git a/src/input_common/drivers/keyboard.h b/src/input_common/drivers/keyboard.h
index 46fe785764..2ab92fd6c2 100644
--- a/src/input_common/drivers/keyboard.h
+++ b/src/input_common/drivers/keyboard.h
@@ -28,6 +28,13 @@ public:
      */
     void ReleaseKey(int key_code);
 
+    /**
+     * Sets the status of all keyboard modifier keys
+     * @param key_modifiers the code of the key to release
+     */
+    void SetModifiers(int key_modifiers);
+
+    /// Sets all keys to the non pressed state
     void ReleaseAllKeys();
 
     /// Used for automapping features
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index df36a337c7..ae2518f53c 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -402,6 +402,15 @@ std::string GenerateKeyboardParam(int key_code) {
     return param.Serialize();
 }
 
+std::string GenerateModdifierKeyboardParam(int key_code) {
+    Common::ParamPackage param;
+    param.Set("engine", "keyboard");
+    param.Set("code", key_code);
+    param.Set("toggle", false);
+    param.Set("pad", 1);
+    return param.Serialize();
+}
+
 std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
                                         int key_modifier, float modifier_scale) {
     Common::ParamPackage circle_pad_param{
diff --git a/src/input_common/main.h b/src/input_common/main.h
index a4a24d076e..9ea3954658 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -134,6 +134,9 @@ private:
 /// Generates a serialized param package for creating a keyboard button device.
 std::string GenerateKeyboardParam(int key_code);
 
+/// Generates a serialized param package for creating a moddifier keyboard button device.
+std::string GenerateModdifierKeyboardParam(int key_code);
+
 /// Generates a serialized param package for creating an analog device taking input from keyboard.
 std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
                                         int key_modifier, float modifier_scale);
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 3c5590a017..61513a5b41 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -392,15 +392,287 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
     QWidget::closeEvent(event);
 }
 
+int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) {
+    switch (qt_key) {
+    case Qt::Key_A:
+        return Settings::NativeKeyboard::A;
+    case Qt::Key_B:
+        return Settings::NativeKeyboard::B;
+    case Qt::Key_C:
+        return Settings::NativeKeyboard::C;
+    case Qt::Key_D:
+        return Settings::NativeKeyboard::D;
+    case Qt::Key_E:
+        return Settings::NativeKeyboard::E;
+    case Qt::Key_F:
+        return Settings::NativeKeyboard::F;
+    case Qt::Key_G:
+        return Settings::NativeKeyboard::G;
+    case Qt::Key_H:
+        return Settings::NativeKeyboard::H;
+    case Qt::Key_I:
+        return Settings::NativeKeyboard::I;
+    case Qt::Key_J:
+        return Settings::NativeKeyboard::J;
+    case Qt::Key_K:
+        return Settings::NativeKeyboard::K;
+    case Qt::Key_L:
+        return Settings::NativeKeyboard::L;
+    case Qt::Key_M:
+        return Settings::NativeKeyboard::M;
+    case Qt::Key_N:
+        return Settings::NativeKeyboard::N;
+    case Qt::Key_O:
+        return Settings::NativeKeyboard::O;
+    case Qt::Key_P:
+        return Settings::NativeKeyboard::P;
+    case Qt::Key_Q:
+        return Settings::NativeKeyboard::Q;
+    case Qt::Key_R:
+        return Settings::NativeKeyboard::R;
+    case Qt::Key_S:
+        return Settings::NativeKeyboard::S;
+    case Qt::Key_T:
+        return Settings::NativeKeyboard::T;
+    case Qt::Key_U:
+        return Settings::NativeKeyboard::U;
+    case Qt::Key_V:
+        return Settings::NativeKeyboard::V;
+    case Qt::Key_W:
+        return Settings::NativeKeyboard::W;
+    case Qt::Key_X:
+        return Settings::NativeKeyboard::X;
+    case Qt::Key_Y:
+        return Settings::NativeKeyboard::Y;
+    case Qt::Key_Z:
+        return Settings::NativeKeyboard::Z;
+    case Qt::Key_1:
+        return Settings::NativeKeyboard::N1;
+    case Qt::Key_2:
+        return Settings::NativeKeyboard::N2;
+    case Qt::Key_3:
+        return Settings::NativeKeyboard::N3;
+    case Qt::Key_4:
+        return Settings::NativeKeyboard::N4;
+    case Qt::Key_5:
+        return Settings::NativeKeyboard::N5;
+    case Qt::Key_6:
+        return Settings::NativeKeyboard::N6;
+    case Qt::Key_7:
+        return Settings::NativeKeyboard::N7;
+    case Qt::Key_8:
+        return Settings::NativeKeyboard::N8;
+    case Qt::Key_9:
+        return Settings::NativeKeyboard::N9;
+    case Qt::Key_0:
+        return Settings::NativeKeyboard::N0;
+    case Qt::Key_Return:
+        return Settings::NativeKeyboard::Return;
+    case Qt::Key_Escape:
+        return Settings::NativeKeyboard::Escape;
+    case Qt::Key_Backspace:
+        return Settings::NativeKeyboard::Backspace;
+    case Qt::Key_Tab:
+        return Settings::NativeKeyboard::Tab;
+    case Qt::Key_Space:
+        return Settings::NativeKeyboard::Space;
+    case Qt::Key_Minus:
+        return Settings::NativeKeyboard::Minus;
+    case Qt::Key_Plus:
+    case Qt::Key_questiondown:
+        return Settings::NativeKeyboard::Plus;
+    case Qt::Key_BracketLeft:
+    case Qt::Key_BraceLeft:
+        return Settings::NativeKeyboard::OpenBracket;
+    case Qt::Key_BracketRight:
+    case Qt::Key_BraceRight:
+        return Settings::NativeKeyboard::CloseBracket;
+    case Qt::Key_Bar:
+        return Settings::NativeKeyboard::Pipe;
+    case Qt::Key_Dead_Tilde:
+        return Settings::NativeKeyboard::Tilde;
+    case Qt::Key_Ntilde:
+    case Qt::Key_Semicolon:
+        return Settings::NativeKeyboard::Semicolon;
+    case Qt::Key_Apostrophe:
+        return Settings::NativeKeyboard::Quote;
+    case Qt::Key_Dead_Grave:
+        return Settings::NativeKeyboard::Backquote;
+    case Qt::Key_Comma:
+        return Settings::NativeKeyboard::Comma;
+    case Qt::Key_Period:
+        return Settings::NativeKeyboard::Period;
+    case Qt::Key_Slash:
+        return Settings::NativeKeyboard::Slash;
+    case Qt::Key_CapsLock:
+        return Settings::NativeKeyboard::CapsLock;
+    case Qt::Key_F1:
+        return Settings::NativeKeyboard::F1;
+    case Qt::Key_F2:
+        return Settings::NativeKeyboard::F2;
+    case Qt::Key_F3:
+        return Settings::NativeKeyboard::F3;
+    case Qt::Key_F4:
+        return Settings::NativeKeyboard::F4;
+    case Qt::Key_F5:
+        return Settings::NativeKeyboard::F5;
+    case Qt::Key_F6:
+        return Settings::NativeKeyboard::F6;
+    case Qt::Key_F7:
+        return Settings::NativeKeyboard::F7;
+    case Qt::Key_F8:
+        return Settings::NativeKeyboard::F8;
+    case Qt::Key_F9:
+        return Settings::NativeKeyboard::F9;
+    case Qt::Key_F10:
+        return Settings::NativeKeyboard::F10;
+    case Qt::Key_F11:
+        return Settings::NativeKeyboard::F11;
+    case Qt::Key_F12:
+        return Settings::NativeKeyboard::F12;
+    case Qt::Key_Print:
+        return Settings::NativeKeyboard::PrintScreen;
+    case Qt::Key_ScrollLock:
+        return Settings::NativeKeyboard::ScrollLock;
+    case Qt::Key_Pause:
+        return Settings::NativeKeyboard::Pause;
+    case Qt::Key_Insert:
+        return Settings::NativeKeyboard::Insert;
+    case Qt::Key_Home:
+        return Settings::NativeKeyboard::Home;
+    case Qt::Key_PageUp:
+        return Settings::NativeKeyboard::PageUp;
+    case Qt::Key_Delete:
+        return Settings::NativeKeyboard::Delete;
+    case Qt::Key_End:
+        return Settings::NativeKeyboard::End;
+    case Qt::Key_PageDown:
+        return Settings::NativeKeyboard::PageDown;
+    case Qt::Key_Right:
+        return Settings::NativeKeyboard::Right;
+    case Qt::Key_Left:
+        return Settings::NativeKeyboard::Left;
+    case Qt::Key_Down:
+        return Settings::NativeKeyboard::Down;
+    case Qt::Key_Up:
+        return Settings::NativeKeyboard::Up;
+    case Qt::Key_NumLock:
+        return Settings::NativeKeyboard::NumLock;
+    // Numpad keys are missing here
+    case Qt::Key_F13:
+        return Settings::NativeKeyboard::F13;
+    case Qt::Key_F14:
+        return Settings::NativeKeyboard::F14;
+    case Qt::Key_F15:
+        return Settings::NativeKeyboard::F15;
+    case Qt::Key_F16:
+        return Settings::NativeKeyboard::F16;
+    case Qt::Key_F17:
+        return Settings::NativeKeyboard::F17;
+    case Qt::Key_F18:
+        return Settings::NativeKeyboard::F18;
+    case Qt::Key_F19:
+        return Settings::NativeKeyboard::F19;
+    case Qt::Key_F20:
+        return Settings::NativeKeyboard::F20;
+    case Qt::Key_F21:
+        return Settings::NativeKeyboard::F21;
+    case Qt::Key_F22:
+        return Settings::NativeKeyboard::F22;
+    case Qt::Key_F23:
+        return Settings::NativeKeyboard::F23;
+    case Qt::Key_F24:
+        return Settings::NativeKeyboard::F24;
+    // case Qt:::
+    //    return Settings::NativeKeyboard::KPComma;
+    // case Qt:::
+    //    return Settings::NativeKeyboard::Ro;
+    case Qt::Key_Hiragana_Katakana:
+        return Settings::NativeKeyboard::KatakanaHiragana;
+    case Qt::Key_yen:
+        return Settings::NativeKeyboard::Yen;
+    case Qt::Key_Henkan:
+        return Settings::NativeKeyboard::Henkan;
+    case Qt::Key_Muhenkan:
+        return Settings::NativeKeyboard::Muhenkan;
+    // case Qt:::
+    //    return Settings::NativeKeyboard::NumPadCommaPc98;
+    case Qt::Key_Hangul:
+        return Settings::NativeKeyboard::HangulEnglish;
+    case Qt::Key_Hangul_Hanja:
+        return Settings::NativeKeyboard::Hanja;
+    case Qt::Key_Katakana:
+        return Settings::NativeKeyboard::KatakanaKey;
+    case Qt::Key_Hiragana:
+        return Settings::NativeKeyboard::HiraganaKey;
+    case Qt::Key_Zenkaku_Hankaku:
+        return Settings::NativeKeyboard::ZenkakuHankaku;
+    // Modifier keys are handled by the modifier property
+    default:
+        return 0;
+    }
+}
+
+int GRenderWindow::QtModifierToSwitchModdifier(quint32 qt_moddifiers) {
+    int moddifier = 0;
+    // The values are obtained through testing, Qt doesn't seem to provide a proper enum
+    if ((qt_moddifiers & 0x1) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::LeftShift;
+    }
+    if ((qt_moddifiers & 0x2) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::LeftControl;
+    }
+    if ((qt_moddifiers & 0x4) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::LeftAlt;
+    }
+    if ((qt_moddifiers & 0x08) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::LeftMeta;
+    }
+    if ((qt_moddifiers & 0x10) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::RightShift;
+    }
+    if ((qt_moddifiers & 0x20) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::RightControl;
+    }
+    if ((qt_moddifiers & 0x40) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::RightAlt;
+    }
+    if ((qt_moddifiers & 0x80) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::RightMeta;
+    }
+    if ((qt_moddifiers & 0x100) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::CapsLock;
+    }
+    if ((qt_moddifiers & 0x200) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::NumLock;
+    }
+    // Verify the last two keys
+    if ((qt_moddifiers & 0x400) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::Katakana;
+    }
+    if ((qt_moddifiers & 0x800) != 0) {
+        moddifier |= 1 << Settings::NativeKeyboard::Hiragana;
+    }
+    return moddifier;
+}
+
 void GRenderWindow::keyPressEvent(QKeyEvent* event) {
     if (!event->isAutoRepeat()) {
-        input_subsystem->GetKeyboard()->PressKey(event->key());
+        const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers());
+        // Replace event->key() with event->nativeVirtualKey() since the second one provides raw key
+        // buttons
+        const auto key = QtKeyToSwitchKey(Qt::Key(event->key()));
+        input_subsystem->GetKeyboard()->SetModifiers(moddifier);
+        input_subsystem->GetKeyboard()->PressKey(key);
     }
 }
 
 void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
     if (!event->isAutoRepeat()) {
-        input_subsystem->GetKeyboard()->ReleaseKey(event->key());
+        const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers());
+        const auto key = QtKeyToSwitchKey(Qt::Key(event->key()));
+        input_subsystem->GetKeyboard()->SetModifiers(moddifier);
+        input_subsystem->GetKeyboard()->ReleaseKey(key);
     }
 }
 
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 95594f81ca..c42d139beb 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -158,6 +158,12 @@ public:
 
     void resizeEvent(QResizeEvent* event) override;
 
+    /// Converts a Qt keybard key into NativeKeyboard key
+    static int QtKeyToSwitchKey(Qt::Key qt_keys);
+
+    /// Converts a Qt modifier keys into NativeKeyboard modifier keys
+    static int QtModifierToSwitchModdifier(quint32 qt_moddifiers);
+
     void keyPressEvent(QKeyEvent* event) override;
     void keyReleaseEvent(QKeyEvent* event) override;
 
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 7669fe4748..ccf274895f 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -65,157 +65,6 @@ const std::array<int, Settings::NativeMouseButton::NumMouseButtons> Config::defa
         Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal,
 };
 
-const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> Config::default_keyboard_keys = {
-    0,
-    0,
-    0,
-    0,
-    Qt::Key_A,
-    Qt::Key_B,
-    Qt::Key_C,
-    Qt::Key_D,
-    Qt::Key_E,
-    Qt::Key_F,
-    Qt::Key_G,
-    Qt::Key_H,
-    Qt::Key_I,
-    Qt::Key_J,
-    Qt::Key_K,
-    Qt::Key_L,
-    Qt::Key_M,
-    Qt::Key_N,
-    Qt::Key_O,
-    Qt::Key_P,
-    Qt::Key_Q,
-    Qt::Key_R,
-    Qt::Key_S,
-    Qt::Key_T,
-    Qt::Key_U,
-    Qt::Key_V,
-    Qt::Key_W,
-    Qt::Key_X,
-    Qt::Key_Y,
-    Qt::Key_Z,
-    Qt::Key_1,
-    Qt::Key_2,
-    Qt::Key_3,
-    Qt::Key_4,
-    Qt::Key_5,
-    Qt::Key_6,
-    Qt::Key_7,
-    Qt::Key_8,
-    Qt::Key_9,
-    Qt::Key_0,
-    Qt::Key_Enter,
-    Qt::Key_Escape,
-    Qt::Key_Backspace,
-    Qt::Key_Tab,
-    Qt::Key_Space,
-    Qt::Key_Minus,
-    Qt::Key_Equal,
-    Qt::Key_BracketLeft,
-    Qt::Key_BracketRight,
-    Qt::Key_Backslash,
-    Qt::Key_Dead_Tilde,
-    Qt::Key_Semicolon,
-    Qt::Key_Apostrophe,
-    Qt::Key_Dead_Grave,
-    Qt::Key_Comma,
-    Qt::Key_Period,
-    Qt::Key_Slash,
-    Qt::Key_CapsLock,
-
-    Qt::Key_F1,
-    Qt::Key_F2,
-    Qt::Key_F3,
-    Qt::Key_F4,
-    Qt::Key_F5,
-    Qt::Key_F6,
-    Qt::Key_F7,
-    Qt::Key_F8,
-    Qt::Key_F9,
-    Qt::Key_F10,
-    Qt::Key_F11,
-    Qt::Key_F12,
-
-    Qt::Key_SysReq,
-    Qt::Key_ScrollLock,
-    Qt::Key_Pause,
-    Qt::Key_Insert,
-    Qt::Key_Home,
-    Qt::Key_PageUp,
-    Qt::Key_Delete,
-    Qt::Key_End,
-    Qt::Key_PageDown,
-    Qt::Key_Right,
-    Qt::Key_Left,
-    Qt::Key_Down,
-    Qt::Key_Up,
-
-    Qt::Key_NumLock,
-    Qt::Key_Slash,
-    Qt::Key_Asterisk,
-    Qt::Key_Minus,
-    Qt::Key_Plus,
-    Qt::Key_Enter,
-    Qt::Key_1,
-    Qt::Key_2,
-    Qt::Key_3,
-    Qt::Key_4,
-    Qt::Key_5,
-    Qt::Key_6,
-    Qt::Key_7,
-    Qt::Key_8,
-    Qt::Key_9,
-    Qt::Key_0,
-    Qt::Key_Period,
-
-    0,
-    0,
-    Qt::Key_PowerOff,
-    Qt::Key_Equal,
-
-    Qt::Key_F13,
-    Qt::Key_F14,
-    Qt::Key_F15,
-    Qt::Key_F16,
-    Qt::Key_F17,
-    Qt::Key_F18,
-    Qt::Key_F19,
-    Qt::Key_F20,
-    Qt::Key_F21,
-    Qt::Key_F22,
-    Qt::Key_F23,
-    Qt::Key_F24,
-
-    Qt::Key_Open,
-    Qt::Key_Help,
-    Qt::Key_Menu,
-    0,
-    Qt::Key_Stop,
-    Qt::Key_AudioRepeat,
-    Qt::Key_Undo,
-    Qt::Key_Cut,
-    Qt::Key_Copy,
-    Qt::Key_Paste,
-    Qt::Key_Find,
-    Qt::Key_VolumeMute,
-    Qt::Key_VolumeUp,
-    Qt::Key_VolumeDown,
-    Qt::Key_CapsLock,
-    Qt::Key_NumLock,
-    Qt::Key_ScrollLock,
-    Qt::Key_Comma,
-
-    Qt::Key_ParenLeft,
-    Qt::Key_ParenRight,
-};
-
-const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default_keyboard_mods = {
-    Qt::Key_Control, Qt::Key_Shift, Qt::Key_Alt,   Qt::Key_ApplicationLeft,
-    Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight,
-};
-
 // This shouldn't have anything except static initializers (no functions). So
 // QKeySequence(...).toString() is NOT ALLOWED HERE.
 // This must be in alphabetical order according to action name as it must have the same order as
@@ -496,14 +345,14 @@ void Config::ReadDebugValues() {
 void Config::ReadKeyboardValues() {
     ReadBasicSetting(Settings::values.keyboard_enabled);
 
-    std::transform(default_keyboard_keys.begin(), default_keyboard_keys.end(),
-                   Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam);
-    std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(),
-                   Settings::values.keyboard_keys.begin() +
-                       Settings::NativeKeyboard::LeftControlKey,
-                   InputCommon::GenerateKeyboardParam);
-    std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(),
-                   Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam);
+    for (std::size_t i = 0; i < Settings::values.keyboard_keys.size(); ++i) {
+        Settings::values.keyboard_keys[i] = InputCommon::GenerateKeyboardParam(static_cast<int>(i));
+    }
+
+    for (std::size_t i = 0; i < Settings::values.keyboard_mods.size(); ++i) {
+        Settings::values.keyboard_mods[i] =
+            InputCommon::GenerateModdifierKeyboardParam(static_cast<int>(i));
+    }
 }
 
 void Config::ReadMouseValues() {

From bca299e8e0489867f7d4bbfd264e221e7e61ae1e Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 14 Nov 2021 10:45:07 -0600
Subject: [PATCH 77/88] input_common: Allow keyboard to be backwards compatible

---
 src/common/settings.h                 |  2 --
 src/core/hid/emulated_devices.cpp     | 28 +++++++++++----
 src/input_common/drivers/keyboard.cpp | 52 ++++++++++++++++++++-------
 src/input_common/drivers/keyboard.h   | 14 +++++++-
 src/input_common/input_mapping.cpp    | 25 +++++++++++++
 src/input_common/input_mapping.h      |  7 ++++
 src/input_common/main.cpp             |  9 -----
 src/input_common/main.h               |  3 --
 src/yuzu/bootmanager.cpp              | 14 +++++---
 src/yuzu/configuration/config.cpp     |  9 -----
 10 files changed, 115 insertions(+), 48 deletions(-)

diff --git a/src/common/settings.h b/src/common/settings.h
index b52d0d1d0f..ee9e0b5a15 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -572,8 +572,6 @@ struct Values {
 
     BasicSetting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};
     BasicSetting<bool> keyboard_enabled{false, "keyboard_enabled"};
-    KeyboardKeysRaw keyboard_keys;
-    KeyboardModsRaw keyboard_mods;
 
     BasicSetting<bool> debug_pad_enabled{false, "debug_pad_enabled"};
     ButtonsRaw debug_pad_buttons;
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
index 0d840a0035..45e0bd80db 100644
--- a/src/core/hid/emulated_devices.cpp
+++ b/src/core/hid/emulated_devices.cpp
@@ -29,13 +29,29 @@ void EmulatedDevices::ReloadInput() {
                    mouse_button_devices.begin(),
                    Common::Input::CreateDevice<Common::Input::InputDevice>);
 
-    std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(),
-                   keyboard_devices.begin(),
-                   Common::Input::CreateDeviceFromString<Common::Input::InputDevice>);
+    std::size_t key_index = 0;
+    for (auto& keyboard_device : keyboard_devices) {
+        // Keyboard keys are only mapped on port 1, pad 0
+        Common::ParamPackage keyboard_params;
+        keyboard_params.Set("engine", "keyboard");
+        keyboard_params.Set("button", static_cast<int>(key_index));
+        keyboard_params.Set("port", 1);
+        keyboard_params.Set("pad", 0);
+        keyboard_device = Common::Input::CreateDevice<Common::Input::InputDevice>(keyboard_params);
+        key_index++;
+    }
 
-    std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(),
-                   keyboard_modifier_devices.begin(),
-                   Common::Input::CreateDeviceFromString<Common::Input::InputDevice>);
+    key_index = 0;
+    for (auto& keyboard_device : keyboard_modifier_devices) {
+        // Keyboard moddifiers are only mapped on port 1, pad 1
+        Common::ParamPackage keyboard_params;
+        keyboard_params.Set("engine", "keyboard");
+        keyboard_params.Set("button", static_cast<int>(key_index));
+        keyboard_params.Set("port", 1);
+        keyboard_params.Set("pad", 1);
+        keyboard_device = Common::Input::CreateDevice<Common::Input::InputDevice>(keyboard_params);
+        key_index++;
+    }
 
     for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) {
         if (!mouse_button_devices[index]) {
diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp
index 328fe1ac16..23b0c0ccf3 100644
--- a/src/input_common/drivers/keyboard.cpp
+++ b/src/input_common/drivers/keyboard.cpp
@@ -13,15 +13,26 @@ constexpr PadIdentifier key_identifier = {
     .port = 0,
     .pad = 0,
 };
-constexpr PadIdentifier modifier_identifier = {
+constexpr PadIdentifier keyboard_key_identifier = {
     .guid = Common::UUID{Common::INVALID_UUID},
-    .port = 0,
+    .port = 1,
+    .pad = 0,
+};
+constexpr PadIdentifier keyboard_modifier_identifier = {
+    .guid = Common::UUID{Common::INVALID_UUID},
+    .port = 1,
     .pad = 1,
 };
 
 Keyboard::Keyboard(const std::string& input_engine_) : InputEngine(input_engine_) {
+    // Keyboard is broken into 3 diferent sets:
+    // key: Unfiltered intended for controllers.
+    // keyboard_key: Allows only Settings::NativeKeyboard::Keys intended for keyboard emulation.
+    // keyboard_modifier: Allows only Settings::NativeKeyboard::Modifiers intended for keyboard
+    // emulation.
     PreSetController(key_identifier);
-    PreSetController(modifier_identifier);
+    PreSetController(keyboard_key_identifier);
+    PreSetController(keyboard_modifier_identifier);
 }
 
 void Keyboard::PressKey(int key_code) {
@@ -32,35 +43,50 @@ void Keyboard::ReleaseKey(int key_code) {
     SetButton(key_identifier, key_code, false);
 }
 
-void Keyboard::SetModifiers(int key_modifiers) {
+void Keyboard::PressKeyboardKey(int key_index) {
+    if (key_index == Settings::NativeKeyboard::None) {
+        return;
+    }
+    SetButton(keyboard_key_identifier, key_index, true);
+}
+
+void Keyboard::ReleaseKeyboardKey(int key_index) {
+    if (key_index == Settings::NativeKeyboard::None) {
+        return;
+    }
+    SetButton(keyboard_key_identifier, key_index, false);
+}
+
+void Keyboard::SetKeyboardModifiers(int key_modifiers) {
     for (int i = 0; i < 32; ++i) {
         bool key_value = ((key_modifiers >> i) & 0x1) != 0;
-        SetButton(modifier_identifier, i, key_value);
+        SetButton(keyboard_modifier_identifier, i, key_value);
         // Use the modifier to press the key button equivalent
         switch (i) {
         case Settings::NativeKeyboard::LeftControl:
-            SetButton(key_identifier, Settings::NativeKeyboard::LeftControlKey, key_value);
+            SetButton(keyboard_key_identifier, Settings::NativeKeyboard::LeftControlKey, key_value);
             break;
         case Settings::NativeKeyboard::LeftShift:
-            SetButton(key_identifier, Settings::NativeKeyboard::LeftShiftKey, key_value);
+            SetButton(keyboard_key_identifier, Settings::NativeKeyboard::LeftShiftKey, key_value);
             break;
         case Settings::NativeKeyboard::LeftAlt:
-            SetButton(key_identifier, Settings::NativeKeyboard::LeftAltKey, key_value);
+            SetButton(keyboard_key_identifier, Settings::NativeKeyboard::LeftAltKey, key_value);
             break;
         case Settings::NativeKeyboard::LeftMeta:
-            SetButton(key_identifier, Settings::NativeKeyboard::LeftMetaKey, key_value);
+            SetButton(keyboard_key_identifier, Settings::NativeKeyboard::LeftMetaKey, key_value);
             break;
         case Settings::NativeKeyboard::RightControl:
-            SetButton(key_identifier, Settings::NativeKeyboard::RightControlKey, key_value);
+            SetButton(keyboard_key_identifier, Settings::NativeKeyboard::RightControlKey,
+                      key_value);
             break;
         case Settings::NativeKeyboard::RightShift:
-            SetButton(key_identifier, Settings::NativeKeyboard::RightShiftKey, key_value);
+            SetButton(keyboard_key_identifier, Settings::NativeKeyboard::RightShiftKey, key_value);
             break;
         case Settings::NativeKeyboard::RightAlt:
-            SetButton(key_identifier, Settings::NativeKeyboard::RightAltKey, key_value);
+            SetButton(keyboard_key_identifier, Settings::NativeKeyboard::RightAltKey, key_value);
             break;
         case Settings::NativeKeyboard::RightMeta:
-            SetButton(key_identifier, Settings::NativeKeyboard::RightMetaKey, key_value);
+            SetButton(keyboard_key_identifier, Settings::NativeKeyboard::RightMetaKey, key_value);
             break;
         default:
             // Other modifier keys should be pressed with PressKey since they stay enabled until
diff --git a/src/input_common/drivers/keyboard.h b/src/input_common/drivers/keyboard.h
index 2ab92fd6c2..ad123b1368 100644
--- a/src/input_common/drivers/keyboard.h
+++ b/src/input_common/drivers/keyboard.h
@@ -28,11 +28,23 @@ public:
      */
     void ReleaseKey(int key_code);
 
+    /**
+     * Sets the status of the keyboard key to pressed
+     * @param key_index index of the key to press
+     */
+    void PressKeyboardKey(int key_index);
+
+    /**
+     * Sets the status of the keyboard key to released
+     * @param key_index index of the key to release
+     */
+    void ReleaseKeyboardKey(int key_index);
+
     /**
      * Sets the status of all keyboard modifier keys
      * @param key_modifiers the code of the key to release
      */
-    void SetModifiers(int key_modifiers);
+    void SetKeyboardModifiers(int key_modifiers);
 
     /// Sets all keys to the non pressed state
     void ReleaseAllKeys();
diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp
index 0ffc710281..0eeeff3725 100644
--- a/src/input_common/input_mapping.cpp
+++ b/src/input_common/input_mapping.cpp
@@ -28,6 +28,10 @@ void MappingFactory::RegisterInput(const MappingData& data) {
     if (!is_enabled) {
         return;
     }
+    if (!IsDriverValid(data)) {
+        return;
+    }
+
     switch (input_type) {
     case Polling::InputType::Button:
         RegisterButton(data);
@@ -168,4 +172,25 @@ void MappingFactory::RegisterMotion(const MappingData& data) {
     input_queue.Push(new_input);
 }
 
+bool MappingFactory::IsDriverValid(const MappingData& data) const {
+    // Only port 0 can be mapped on the keyboard
+    if (data.engine == "keyboard" && data.pad.port != 0) {
+        return false;
+    }
+    // The following drivers don't need to be mapped
+    if (data.engine == "tas") {
+        return false;
+    }
+    if (data.engine == "touch") {
+        return false;
+    }
+    if (data.engine == "touch_from_button") {
+        return false;
+    }
+    if (data.engine == "analog_from_button") {
+        return false;
+    }
+    return true;
+}
+
 } // namespace InputCommon
diff --git a/src/input_common/input_mapping.h b/src/input_common/input_mapping.h
index 2622dba70c..44eb8ad9a3 100644
--- a/src/input_common/input_mapping.h
+++ b/src/input_common/input_mapping.h
@@ -66,6 +66,13 @@ private:
      */
     void RegisterMotion(const MappingData& data);
 
+    /**
+     * Returns true if driver can be mapped
+     * @param "data": An struct containing all the information needed to create a proper
+     * ParamPackage
+     */
+    bool IsDriverValid(const MappingData& data) const;
+
     Common::SPSCQueue<Common::ParamPackage> input_queue;
     Polling::InputType input_type{Polling::InputType::None};
     bool is_enabled{};
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index ae2518f53c..df36a337c7 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -402,15 +402,6 @@ std::string GenerateKeyboardParam(int key_code) {
     return param.Serialize();
 }
 
-std::string GenerateModdifierKeyboardParam(int key_code) {
-    Common::ParamPackage param;
-    param.Set("engine", "keyboard");
-    param.Set("code", key_code);
-    param.Set("toggle", false);
-    param.Set("pad", 1);
-    return param.Serialize();
-}
-
 std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
                                         int key_modifier, float modifier_scale) {
     Common::ParamPackage circle_pad_param{
diff --git a/src/input_common/main.h b/src/input_common/main.h
index 9ea3954658..a4a24d076e 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -134,9 +134,6 @@ private:
 /// Generates a serialized param package for creating a keyboard button device.
 std::string GenerateKeyboardParam(int key_code);
 
-/// Generates a serialized param package for creating a moddifier keyboard button device.
-std::string GenerateModdifierKeyboardParam(int key_code);
-
 /// Generates a serialized param package for creating an analog device taking input from keyboard.
 std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
                                         int key_modifier, float modifier_scale);
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 61513a5b41..9f4d1aac37 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -609,7 +609,7 @@ int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) {
         return Settings::NativeKeyboard::ZenkakuHankaku;
     // Modifier keys are handled by the modifier property
     default:
-        return 0;
+        return Settings::NativeKeyboard::None;
     }
 }
 
@@ -662,8 +662,10 @@ void GRenderWindow::keyPressEvent(QKeyEvent* event) {
         // Replace event->key() with event->nativeVirtualKey() since the second one provides raw key
         // buttons
         const auto key = QtKeyToSwitchKey(Qt::Key(event->key()));
-        input_subsystem->GetKeyboard()->SetModifiers(moddifier);
-        input_subsystem->GetKeyboard()->PressKey(key);
+        input_subsystem->GetKeyboard()->SetKeyboardModifiers(moddifier);
+        input_subsystem->GetKeyboard()->PressKeyboardKey(key);
+        // This is used for gamepads
+        input_subsystem->GetKeyboard()->PressKey(event->key());
     }
 }
 
@@ -671,8 +673,10 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
     if (!event->isAutoRepeat()) {
         const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers());
         const auto key = QtKeyToSwitchKey(Qt::Key(event->key()));
-        input_subsystem->GetKeyboard()->SetModifiers(moddifier);
-        input_subsystem->GetKeyboard()->ReleaseKey(key);
+        input_subsystem->GetKeyboard()->SetKeyboardModifiers(moddifier);
+        input_subsystem->GetKeyboard()->ReleaseKeyboardKey(key);
+        // This is used for gamepads
+        input_subsystem->GetKeyboard()->ReleaseKey(event->key());
     }
 }
 
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index ccf274895f..5865359fe0 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -344,15 +344,6 @@ void Config::ReadDebugValues() {
 
 void Config::ReadKeyboardValues() {
     ReadBasicSetting(Settings::values.keyboard_enabled);
-
-    for (std::size_t i = 0; i < Settings::values.keyboard_keys.size(); ++i) {
-        Settings::values.keyboard_keys[i] = InputCommon::GenerateKeyboardParam(static_cast<int>(i));
-    }
-
-    for (std::size_t i = 0; i < Settings::values.keyboard_mods.size(); ++i) {
-        Settings::values.keyboard_mods[i] =
-            InputCommon::GenerateModdifierKeyboardParam(static_cast<int>(i));
-    }
 }
 
 void Config::ReadMouseValues() {

From 654d76e79e84a3384fa503fac9003a5d0a32f28b Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 14 Nov 2021 14:09:29 -0600
Subject: [PATCH 78/88] core/hid: Fully implement native mouse

---
 src/common/settings.h                         |   1 -
 src/common/settings_input.h                   |  15 +-
 src/core/hid/emulated_console.cpp             |  11 +-
 src/core/hid/emulated_devices.cpp             | 124 +++++--
 src/core/hid/emulated_devices.h               |  56 +--
 src/core/hid/input_converter.cpp              |  21 ++
 src/core/hid/input_converter.h                |   9 +
 .../hle/service/hid/controllers/mouse.cpp     |   9 +-
 src/input_common/drivers/mouse.cpp            |  31 +-
 src/input_common/drivers/mouse.h              |   7 +
 src/yuzu/CMakeLists.txt                       |   3 -
 src/yuzu/bootmanager.cpp                      |   6 +
 src/yuzu/bootmanager.h                        |   1 +
 src/yuzu/configuration/config.cpp             |  30 --
 src/yuzu/configuration/configure_input.cpp    |   4 -
 .../configure_input_advanced.cpp              |   2 -
 .../configuration/configure_input_advanced.ui | 204 +++++------
 .../configure_mouse_advanced.cpp              | 247 -------------
 .../configuration/configure_mouse_advanced.h  |  72 ----
 .../configuration/configure_mouse_advanced.ui | 335 ------------------
 src/yuzu_cmd/config.cpp                       | 174 ---------
 21 files changed, 323 insertions(+), 1039 deletions(-)
 delete mode 100644 src/yuzu/configuration/configure_mouse_advanced.cpp
 delete mode 100644 src/yuzu/configuration/configure_mouse_advanced.h
 delete mode 100644 src/yuzu/configuration/configure_mouse_advanced.ui

diff --git a/src/common/settings.h b/src/common/settings.h
index ee9e0b5a15..d7410fa9b2 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -568,7 +568,6 @@ struct Values {
     BasicSetting<bool> mouse_panning{false, "mouse_panning"};
     BasicRangedSetting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
     BasicSetting<bool> mouse_enabled{false, "mouse_enabled"};
-    MouseButtonsRaw mouse_buttons;
 
     BasicSetting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};
     BasicSetting<bool> keyboard_enabled{false, "keyboard_enabled"};
diff --git a/src/common/settings_input.h b/src/common/settings_input.h
index a2982fca46..9a88044881 100644
--- a/src/common/settings_input.h
+++ b/src/common/settings_input.h
@@ -126,6 +126,17 @@ constexpr int NUM_MOUSE_HID = NumMouseButtons;
 extern const std::array<const char*, NumMouseButtons> mapping;
 } // namespace NativeMouseButton
 
+namespace NativeMouseWheel {
+enum Values {
+    X,
+    Y,
+
+    NumMouseWheels,
+};
+
+extern const std::array<const char*, NumMouseWheels> mapping;
+} // namespace NativeMouseWheel
+
 namespace NativeKeyboard {
 enum Keys {
     None,
@@ -348,10 +359,6 @@ using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
 using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>;
 using VibrationsRaw = std::array<std::string, NativeVibration::NumVibrations>;
 
-using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
-using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
-using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
-
 constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28;
 constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A;
 constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6;
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index 374dd5d41b..b224932dc5 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -24,7 +24,10 @@ void EmulatedConsole::SetTouchParams() {
     std::size_t index = 0;
 
     // Hardcode mouse, touchscreen and cemuhook parameters
-    touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};
+    if (!Settings::values.mouse_enabled) {
+        // We can't use mouse as touch if native mouse is enabled
+        touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};
+    }
     touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"};
     touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"};
     touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:0,axis_y:1,button:0"};
@@ -36,6 +39,9 @@ void EmulatedConsole::SetTouchParams() {
 
     // Map the rest of the fingers from touch from button configuration
     for (const auto& config_entry : touch_buttons) {
+        if (index >= touch_params.size()) {
+            continue;
+        }
         Common::ParamPackage params{config_entry};
         Common::ParamPackage touch_button_params;
         const int x = params.Get("x", 0);
@@ -49,9 +55,6 @@ void EmulatedConsole::SetTouchParams() {
         touch_button_params.Set("touch_id", static_cast<int>(index));
         touch_params[index] = touch_button_params;
         index++;
-        if (index >= touch_params.size()) {
-            return;
-        }
     }
 }
 
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
index 45e0bd80db..70a494097a 100644
--- a/src/core/hid/emulated_devices.cpp
+++ b/src/core/hid/emulated_devices.cpp
@@ -15,21 +15,34 @@ EmulatedDevices::EmulatedDevices() = default;
 EmulatedDevices::~EmulatedDevices() = default;
 
 void EmulatedDevices::ReloadFromSettings() {
-    const auto& mouse = Settings::values.mouse_buttons;
-
-    for (std::size_t index = 0; index < mouse.size(); ++index) {
-        mouse_button_params[index] = Common::ParamPackage(mouse[index]);
-    }
     ReloadInput();
 }
 
 void EmulatedDevices::ReloadInput() {
-    std::transform(mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_BEGIN,
-                   mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_END,
-                   mouse_button_devices.begin(),
-                   Common::Input::CreateDevice<Common::Input::InputDevice>);
-
+    // If you load any device here add the equivalent to the UnloadInput() function
     std::size_t key_index = 0;
+    for (auto& mouse_device : mouse_button_devices) {
+        Common::ParamPackage mouse_params;
+        mouse_params.Set("engine", "mouse");
+        mouse_params.Set("button", static_cast<int>(key_index));
+        mouse_device = Common::Input::CreateDevice<Common::Input::InputDevice>(mouse_params);
+        key_index++;
+    }
+
+    mouse_stick_device = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
+        "engine:mouse,axis_x:0,axis_y:1");
+
+    // First two axis are reserved for mouse position
+    key_index = 2;
+    for (auto& mouse_device : mouse_analog_devices) {
+        Common::ParamPackage mouse_params;
+        mouse_params.Set("engine", "mouse");
+        mouse_params.Set("axis", static_cast<int>(key_index));
+        mouse_device = Common::Input::CreateDevice<Common::Input::InputDevice>(mouse_params);
+        key_index++;
+    }
+
+    key_index = 0;
     for (auto& keyboard_device : keyboard_devices) {
         // Keyboard keys are only mapped on port 1, pad 0
         Common::ParamPackage keyboard_params;
@@ -64,6 +77,23 @@ void EmulatedDevices::ReloadInput() {
         mouse_button_devices[index]->SetCallback(button_callback);
     }
 
+    for (std::size_t index = 0; index < mouse_analog_devices.size(); ++index) {
+        if (!mouse_analog_devices[index]) {
+            continue;
+        }
+        Common::Input::InputCallback button_callback{
+            [this, index](Common::Input::CallbackStatus callback) {
+                SetMouseAnalog(callback, index);
+            }};
+        mouse_analog_devices[index]->SetCallback(button_callback);
+    }
+
+    if (mouse_stick_device) {
+        Common::Input::InputCallback button_callback{
+            [this](Common::Input::CallbackStatus callback) { SetMouseStick(callback); }};
+        mouse_stick_device->SetCallback(button_callback);
+    }
+
     for (std::size_t index = 0; index < keyboard_devices.size(); ++index) {
         if (!keyboard_devices[index]) {
             continue;
@@ -91,6 +121,10 @@ void EmulatedDevices::UnloadInput() {
     for (auto& button : mouse_button_devices) {
         button.reset();
     }
+    for (auto& analog : mouse_analog_devices) {
+        analog.reset();
+    }
+    mouse_stick_device.reset();
     for (auto& button : keyboard_devices) {
         button.reset();
     }
@@ -116,12 +150,6 @@ void EmulatedDevices::SaveCurrentConfig() {
     if (!is_configuring) {
         return;
     }
-
-    auto& mouse = Settings::values.mouse_buttons;
-
-    for (std::size_t index = 0; index < mouse.size(); ++index) {
-        mouse[index] = mouse_button_params[index].Serialize();
-    }
 }
 
 void EmulatedDevices::RestoreConfig() {
@@ -131,21 +159,6 @@ void EmulatedDevices::RestoreConfig() {
     ReloadFromSettings();
 }
 
-Common::ParamPackage EmulatedDevices::GetMouseButtonParam(std::size_t index) const {
-    if (index >= mouse_button_params.size()) {
-        return {};
-    }
-    return mouse_button_params[index];
-}
-
-void EmulatedDevices::SetMouseButtonParam(std::size_t index, Common::ParamPackage param) {
-    if (index >= mouse_button_params.size()) {
-        return;
-    }
-    mouse_button_params[index] = param;
-    ReloadInput();
-}
-
 void EmulatedDevices::SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index) {
     if (index >= device_status.keyboard_values.size()) {
         return;
@@ -334,6 +347,51 @@ void EmulatedDevices::SetMouseButton(Common::Input::CallbackStatus callback, std
     TriggerOnChange(DeviceTriggerType::Mouse);
 }
 
+void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index) {
+    if (index >= device_status.mouse_analog_values.size()) {
+        return;
+    }
+    std::lock_guard lock{mutex};
+    const auto analog_value = TransformToAnalog(callback);
+
+    device_status.mouse_analog_values[index] = analog_value;
+
+    if (is_configuring) {
+        device_status.mouse_position_state = {};
+        TriggerOnChange(DeviceTriggerType::Mouse);
+        return;
+    }
+
+    switch (index) {
+    case Settings::NativeMouseWheel::X:
+        device_status.mouse_wheel_state.x = static_cast<s32>(analog_value.value);
+        break;
+    case Settings::NativeMouseWheel::Y:
+        device_status.mouse_wheel_state.y = static_cast<s32>(analog_value.value);
+        break;
+    }
+
+    TriggerOnChange(DeviceTriggerType::Mouse);
+}
+
+void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) {
+    std::lock_guard lock{mutex};
+    const auto stick_value = TransformToStick(callback);
+
+    device_status.mouse_stick_value = stick_value;
+
+    if (is_configuring) {
+        device_status.mouse_position_state = {};
+        TriggerOnChange(DeviceTriggerType::Mouse);
+        return;
+    }
+
+    device_status.mouse_position_state.x = stick_value.x.value;
+    device_status.mouse_position_state.y = stick_value.y.value;
+
+    TriggerOnChange(DeviceTriggerType::Mouse);
+}
+
 KeyboardValues EmulatedDevices::GetKeyboardValues() const {
     return device_status.keyboard_values;
 }
@@ -362,6 +420,10 @@ MousePosition EmulatedDevices::GetMousePosition() const {
     return device_status.mouse_position_state;
 }
 
+AnalogStickState EmulatedDevices::GetMouseDeltaWheel() const {
+    return device_status.mouse_wheel_state;
+}
+
 void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) {
     for (const auto& poller_pair : callback_list) {
         const InterfaceUpdateCallback& poller = poller_pair.second;
diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h
index d49d6d78a5..49edfd255b 100644
--- a/src/core/hid/emulated_devices.h
+++ b/src/core/hid/emulated_devices.h
@@ -17,13 +17,15 @@
 #include "core/hid/hid_types.h"
 
 namespace Core::HID {
-
 using KeyboardDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
                                    Settings::NativeKeyboard::NumKeyboardKeys>;
 using KeyboardModifierDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
                                            Settings::NativeKeyboard::NumKeyboardMods>;
 using MouseButtonDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
                                       Settings::NativeMouseButton::NumMouseButtons>;
+using MouseAnalogDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
+                                      Settings::NativeMouseWheel::NumMouseWheels>;
+using MouseStickDevice = std::unique_ptr<Common::Input::InputDevice>;
 
 using MouseButtonParams =
     std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons>;
@@ -34,12 +36,13 @@ using KeyboardModifierValues =
     std::array<Common::Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardMods>;
 using MouseButtonValues =
     std::array<Common::Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>;
+using MouseAnalogValues =
+    std::array<Common::Input::AnalogStatus, Settings::NativeMouseWheel::NumMouseWheels>;
+using MouseStickValue = Common::Input::StickStatus;
 
 struct MousePosition {
-    s32 x;
-    s32 y;
-    s32 delta_wheel_x;
-    s32 delta_wheel_y;
+    f32 x;
+    f32 y;
 };
 
 struct DeviceStatus {
@@ -47,12 +50,15 @@ struct DeviceStatus {
     KeyboardValues keyboard_values{};
     KeyboardModifierValues keyboard_moddifier_values{};
     MouseButtonValues mouse_button_values{};
+    MouseAnalogValues mouse_analog_values{};
+    MouseStickValue mouse_stick_value{};
 
     // Data for HID serices
     KeyboardKey keyboard_state{};
     KeyboardModifier keyboard_moddifier_state{};
     MouseButton mouse_button_state{};
     MousePosition mouse_position_state{};
+    AnalogStickState mouse_wheel_state{};
 };
 
 enum class DeviceTriggerType {
@@ -102,15 +108,6 @@ public:
     /// Reverts any mapped changes made that weren't saved
     void RestoreConfig();
 
-    /// Returns the current mapped mouse button device
-    Common::ParamPackage GetMouseButtonParam(std::size_t index) const;
-
-    /**
-     * Updates the current mapped mouse button device
-     * @param ParamPackage with controller data to be mapped
-     */
-    void SetMouseButtonParam(std::size_t index, Common::ParamPackage param);
-
     /// Returns the latest status of button input from the keyboard with parameters
     KeyboardValues GetKeyboardValues() const;
 
@@ -132,9 +129,12 @@ public:
     /// Returns the latest mouse coordinates
     MousePosition GetMousePosition() const;
 
+    /// Returns the latest mouse wheel change
+    AnalogStickState GetMouseDeltaWheel() const;
+
     /**
      * Adds a callback to the list of events
-     * @param ConsoleUpdateCallback that will be triggered
+     * @param InterfaceUpdateCallback that will be triggered
      * @return an unique key corresponding to the callback index in the list
      */
     int SetCallback(InterfaceUpdateCallback update_callback);
@@ -150,26 +150,40 @@ private:
     void UpdateKey(std::size_t key_index, bool status);
 
     /**
-     * Updates the touch status of the console
+     * Updates the touch status of the keyboard device
      * @param callback: A CallbackStatus containing the key status
      * @param index: key ID to be updated
      */
     void SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index);
 
     /**
-     * Updates the touch status of the console
+     * Updates the keyboard status of the keyboard device
      * @param callback: A CallbackStatus containing the modifier key status
      * @param index: modifier key ID to be updated
      */
     void SetKeyboardModifier(Common::Input::CallbackStatus callback, std::size_t index);
 
     /**
-     * Updates the touch status of the console
+     * Updates the mouse button status of the mouse device
      * @param callback: A CallbackStatus containing the button status
-     * @param index: Button ID of the to be updated
+     * @param index: Button ID to be updated
      */
     void SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index);
 
+    /**
+     * Updates the mouse wheel status of the mouse device
+     * @param callback: A CallbackStatus containing the wheel status
+     * @param index: wheel ID to be updated
+     */
+    void SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index);
+
+    /**
+     * Updates the mouse position status of the mouse device
+     * @param callback: A CallbackStatus containing the position status
+     * @param index: stick ID to be updated
+     */
+    void SetMouseStick(Common::Input::CallbackStatus callback);
+
     /**
      * Triggers a callback that something has changed on the device status
      * @param Input type of the event to trigger
@@ -178,11 +192,11 @@ private:
 
     bool is_configuring{false};
 
-    MouseButtonParams mouse_button_params;
-
     KeyboardDevices keyboard_devices;
     KeyboardModifierDevices keyboard_modifier_devices;
     MouseButtonDevices mouse_button_devices;
+    MouseAnalogDevices mouse_analog_devices;
+    MouseStickDevice mouse_stick_device;
 
     mutable std::mutex mutex;
     std::unordered_map<int, InterfaceUpdateCallback> callback_list;
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index 480b862fdc..c4e6539568 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -242,6 +242,27 @@ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackSta
     return status;
 }
 
+Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback) {
+    Common::Input::AnalogStatus status{};
+
+    switch (callback.type) {
+    case Common::Input::InputType::Analog:
+        status.properties = callback.analog_status.properties;
+        status.raw_value = callback.analog_status.raw_value;
+        break;
+    default:
+        LOG_ERROR(Input, "Conversion from type {} to analog not implemented", callback.type);
+        break;
+    }
+
+    SanitizeAnalog(status, false);
+
+    // Adjust if value is inverted
+    status.value = status.properties.inverted ? -status.value : status.value;
+
+    return status;
+}
+
 void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) {
     const auto& properties = analog.properties;
     float& raw_value = analog.raw_value;
diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h
index 2a722b39f8..1492489d73 100644
--- a/src/core/hid/input_converter.h
+++ b/src/core/hid/input_converter.h
@@ -68,6 +68,15 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus&
  */
 Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback);
 
+/**
+ * Converts raw input data into a valid analog status. Applies offset, deadzone, range and
+ * invert properties to the output.
+ *
+ * @param Supported callbacks: Analog.
+ * @return A valid AnalogStatus object.
+ */
+Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback);
+
 /**
  * Converts raw analog data into a valid analog value
  * @param An analog object containing raw data and properties, bool that determines if the value
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 83e69ca94f..9c408e7f40 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -38,13 +38,14 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
     if (Settings::values.mouse_enabled) {
         const auto& mouse_button_state = emulated_devices->GetMouseButtons();
         const auto& mouse_position_state = emulated_devices->GetMousePosition();
+        const auto& mouse_wheel_state = emulated_devices->GetMouseDeltaWheel();
         next_state.attribute.is_connected.Assign(1);
-        next_state.x = mouse_position_state.x;
-        next_state.y = mouse_position_state.y;
+        next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width);
+        next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height);
         next_state.delta_x = next_state.x - last_entry.x;
         next_state.delta_y = next_state.y - last_entry.y;
-        next_state.delta_wheel_x = mouse_position_state.delta_wheel_x;
-        next_state.delta_wheel_y = mouse_position_state.delta_wheel_y;
+        next_state.delta_wheel_x = mouse_wheel_state.x;
+        next_state.delta_wheel_y = mouse_wheel_state.y;
 
         next_state.button = mouse_button_state;
     }
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
index afa92b4583..478737db22 100644
--- a/src/input_common/drivers/mouse.cpp
+++ b/src/input_common/drivers/mouse.cpp
@@ -12,6 +12,10 @@
 #include "input_common/drivers/mouse.h"
 
 namespace InputCommon {
+constexpr int mouse_axis_x = 0;
+constexpr int mouse_axis_y = 1;
+constexpr int wheel_axis_x = 2;
+constexpr int wheel_axis_y = 3;
 constexpr int touch_axis_x = 10;
 constexpr int touch_axis_y = 11;
 constexpr PadIdentifier identifier = {
@@ -22,6 +26,12 @@ constexpr PadIdentifier identifier = {
 
 Mouse::Mouse(const std::string input_engine_) : InputEngine(input_engine_) {
     PreSetController(identifier);
+    PreSetAxis(identifier, mouse_axis_x);
+    PreSetAxis(identifier, mouse_axis_y);
+    PreSetAxis(identifier, wheel_axis_x);
+    PreSetAxis(identifier, wheel_axis_y);
+    PreSetAxis(identifier, touch_axis_x);
+    PreSetAxis(identifier, touch_axis_x);
     update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); });
 }
 
@@ -34,14 +44,18 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
             last_mouse_change *= 0.96f;
             const float sensitivity =
                 Settings::values.mouse_panning_sensitivity.GetValue() * 0.022f;
-            SetAxis(identifier, 0, last_mouse_change.x * sensitivity);
-            SetAxis(identifier, 1, -last_mouse_change.y * sensitivity);
+            SetAxis(identifier, mouse_axis_x, last_mouse_change.x * sensitivity);
+            SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity);
         }
 
         if (mouse_panning_timout++ > 20) {
             StopPanning();
         }
         std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
+
+        // Reset wheel position
+        SetAxis(identifier, wheel_axis_x, 0);
+        SetAxis(identifier, wheel_axis_y, 0);
     }
 }
 
@@ -89,8 +103,8 @@ void Mouse::MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int
     if (button_pressed) {
         const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin;
         const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.0012f;
-        SetAxis(identifier, 0, static_cast<float>(mouse_move.x) * sensitivity);
-        SetAxis(identifier, 1, static_cast<float>(-mouse_move.y) * sensitivity);
+        SetAxis(identifier, mouse_axis_x, static_cast<float>(mouse_move.x) * sensitivity);
+        SetAxis(identifier, mouse_axis_y, static_cast<float>(-mouse_move.y) * sensitivity);
     }
 }
 
@@ -108,12 +122,17 @@ void Mouse::ReleaseButton(MouseButton button) {
     SetButton(identifier, static_cast<int>(button), false);
 
     if (!Settings::values.mouse_panning) {
-        SetAxis(identifier, 0, 0);
-        SetAxis(identifier, 1, 0);
+        SetAxis(identifier, mouse_axis_x, 0);
+        SetAxis(identifier, mouse_axis_y, 0);
     }
     button_pressed = false;
 }
 
+void Mouse::MouseWheelChange(int x, int y) {
+    SetAxis(identifier, wheel_axis_x, static_cast<f32>(x));
+    SetAxis(identifier, wheel_axis_y, static_cast<f32>(y));
+}
+
 void Mouse::ReleaseAllButtons() {
     ResetButtonState();
     button_pressed = false;
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index 1be362b946..429502af9f 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -52,6 +52,13 @@ public:
      */
     void ReleaseButton(MouseButton button);
 
+    /**
+     * Sets the status of the mouse wheel
+     * @param x delta movement in the x direction
+     * @param y delta movement in the y direction
+     */
+    void MouseWheelChange(int x, int y);
+
     void ReleaseAllButtons();
 
     std::vector<Common::ParamPackage> GetInputDevices() const override;
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index d62fd566f7..a44815e71e 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -90,9 +90,6 @@ add_executable(yuzu
     configuration/configure_motion_touch.cpp
     configuration/configure_motion_touch.h
     configuration/configure_motion_touch.ui
-    configuration/configure_mouse_advanced.cpp
-    configuration/configure_mouse_advanced.h
-    configuration/configure_mouse_advanced.ui
     configuration/configure_per_game.cpp
     configuration/configure_per_game.h
     configuration/configure_per_game.ui
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 9f4d1aac37..1015e51b56 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -746,6 +746,12 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
     input_subsystem->GetMouse()->ReleaseButton(button);
 }
 
+void GRenderWindow::wheelEvent(QWheelEvent* event) {
+    const int x = event->delta();
+    const int y = 0;
+    input_subsystem->GetMouse()->MouseWheelChange(x, y);
+}
+
 void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) {
     QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints();
     for (const auto& touch_point : touch_points) {
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index c42d139beb..d6b2ab5f3f 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -173,6 +173,7 @@ public:
     void mousePressEvent(QMouseEvent* event) override;
     void mouseMoveEvent(QMouseEvent* event) override;
     void mouseReleaseEvent(QMouseEvent* event) override;
+    void wheelEvent(QWheelEvent* event) override;
 
     bool event(QEvent* event) override;
 
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 5865359fe0..ae1684dd4c 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -60,11 +60,6 @@ const std::array<int, 2> Config::default_stick_mod = {
     0,
 };
 
-const std::array<int, Settings::NativeMouseButton::NumMouseButtons> Config::default_mouse_buttons =
-    {
-        Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal,
-};
-
 // This shouldn't have anything except static initializers (no functions). So
 // QKeySequence(...).toString() is NOT ALLOWED HERE.
 // This must be in alphabetical order according to action name as it must have the same order as
@@ -348,22 +343,6 @@ void Config::ReadKeyboardValues() {
 
 void Config::ReadMouseValues() {
     ReadBasicSetting(Settings::values.mouse_enabled);
-
-    for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
-        const std::string default_param =
-            InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]);
-        auto& mouse_buttons = Settings::values.mouse_buttons[i];
-
-        mouse_buttons = qt_config
-                            ->value(QStringLiteral("mouse_") +
-                                        QString::fromUtf8(Settings::NativeMouseButton::mapping[i]),
-                                    QString::fromStdString(default_param))
-                            .toString()
-                            .toStdString();
-        if (mouse_buttons.empty()) {
-            mouse_buttons = default_param;
-        }
-    }
 }
 
 void Config::ReadTouchscreenValues() {
@@ -947,15 +926,6 @@ void Config::SaveDebugValues() {
 
 void Config::SaveMouseValues() {
     WriteBasicSetting(Settings::values.mouse_enabled);
-
-    for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
-        const std::string default_param =
-            InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]);
-        WriteSetting(QStringLiteral("mouse_") +
-                         QString::fromStdString(Settings::NativeMouseButton::mapping[i]),
-                     QString::fromStdString(Settings::values.mouse_buttons[i]),
-                     QString::fromStdString(default_param));
-    }
 }
 
 void Config::SaveTouchscreenValues() {
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 99450bc7d1..d53179dbbb 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -24,7 +24,6 @@
 #include "yuzu/configuration/configure_input_advanced.h"
 #include "yuzu/configuration/configure_input_player.h"
 #include "yuzu/configuration/configure_motion_touch.h"
-#include "yuzu/configuration/configure_mouse_advanced.h"
 #include "yuzu/configuration/configure_touchscreen_advanced.h"
 #include "yuzu/configuration/configure_vibration.h"
 #include "yuzu/configuration/input_profiles.h"
@@ -157,9 +156,6 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
                 CallConfigureDialog<ConfigureDebugController>(
                     *this, input_subsystem, profiles.get(), hid_core, is_powered_on);
             });
-    connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] {
-        CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem);
-    });
     connect(advanced, &ConfigureInputAdvanced::CallTouchscreenConfigDialog,
             [this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); });
     connect(advanced, &ConfigureInputAdvanced::CallMotionTouchConfigDialog,
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index b30f09013c..cf8aad4abf 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -82,7 +82,6 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent)
 
     connect(ui->debug_configure, &QPushButton::clicked, this,
             [this] { CallDebugControllerDialog(); });
-    connect(ui->mouse_advanced, &QPushButton::clicked, this, [this] { CallMouseConfigDialog(); });
     connect(ui->touchscreen_advanced, &QPushButton::clicked, this,
             [this] { CallTouchscreenConfigDialog(); });
     connect(ui->buttonMotionTouch, &QPushButton::clicked, this,
@@ -178,7 +177,6 @@ void ConfigureInputAdvanced::RetranslateUI() {
 }
 
 void ConfigureInputAdvanced::UpdateUIEnabled() {
-    ui->mouse_advanced->setEnabled(ui->mouse_enabled->isChecked());
     ui->debug_configure->setEnabled(ui->debug_enabled->isChecked());
     ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked());
 }
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui
index 9095206a07..75487a5d0a 100644
--- a/src/yuzu/configuration/configure_input_advanced.ui
+++ b/src/yuzu/configuration/configure_input_advanced.ui
@@ -2528,11 +2528,11 @@
              <number>0</number>
             </property>
             <item>
-             <widget class="QGroupBox" name="gridGroupBox_3">
+             <widget class="QGroupBox" name="emulatedDevicesGroupBox">
               <property name="title">
-               <string>Other</string>
+               <string>Emulated Devices</string>
               </property>
-              <layout class="QGridLayout" name="gridLayout_3">
+              <layout class="QGridLayout" name="emulatedDevicesGridLayout">
                <item row="0" column="0">
                 <widget class="QCheckBox" name="keyboard_enabled">
                  <property name="minimumSize">
@@ -2547,7 +2547,7 @@
                 </widget>
                </item>
                 <item row="1" column="0">
-                  <widget class="QCheckBox" name="emulate_analog_keyboard">
+                  <widget class="QCheckBox" name="mouse_enabled">
                     <property name="minimumSize">
                       <size>
                         <width>0</width>
@@ -2555,53 +2555,18 @@
                       </size>
                     </property>
                     <property name="text">
-                      <string>Emulate Analog with Keyboard Input</string>
+                      <string>Mouse</string>
                     </property>
                   </widget>
                 </item>
                 <item row="2" column="0">
-                  <widget class="QCheckBox" name="mouse_panning">
-                    <property name="minimumSize">
-                      <size>
-                        <width>0</width>
-                        <height>23</height>
-                      </size>
-                    </property>
+                  <widget class="QCheckBox" name="touchscreen_enabled">
                     <property name="text">
-                      <string>Enable mouse panning</string>
+                      <string>Touchscreen</string>
                     </property>
                   </widget>
                 </item>
-                <item row="2" column="2">
-                    <widget class="QSpinBox" name="mouse_panning_sensitivity">
-                      <property name="toolTip">
-                        <string>Mouse sensitivity</string>
-                      </property>
-                      <property name="alignment">
-                        <set>Qt::AlignCenter</set>
-                      </property>
-                      <property name="suffix">
-                        <string>%</string>
-                      </property>
-                      <property name="minimum">
-                        <number>1</number>
-                      </property>
-                      <property name="maximum">
-                        <number>100</number>
-                      </property>
-                      <property name="value">
-                        <number>100</number>
-                      </property>
-                    </widget>
-                </item>
-               <item row="6" column="2">
-                <widget class="QPushButton" name="touchscreen_advanced">
-                 <property name="text">
-                  <string>Advanced</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="3" column="1">
+               <item row="2" column="1">
                 <spacer name="horizontalSpacer_8">
                  <property name="orientation">
                   <enum>Qt::Horizontal</enum>
@@ -2617,80 +2582,117 @@
                  </property>
                 </spacer>
                </item>
-               <item row="3" column="2">
-                <widget class="QPushButton" name="mouse_advanced">
-                 <property name="text">
-                  <string>Advanced</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="6" column="0">
-                <widget class="QCheckBox" name="touchscreen_enabled">
-                 <property name="text">
-                  <string>Touchscreen</string>
-                 </property>
-                </widget>
-               </item>
+                <item row="2" column="2">
+                  <widget class="QPushButton" name="touchscreen_advanced">
+                    <property name="text">
+                      <string>Advanced</string>
+                    </property>
+                  </widget>
+                </item>
                <item row="3" column="0">
-                <widget class="QCheckBox" name="mouse_enabled">
-                 <property name="minimumSize">
-                  <size>
-                   <width>0</width>
-                   <height>23</height>
-                  </size>
-                 </property>
-                 <property name="text">
-                  <string>Mouse</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="8" column="0">
-                <widget class="QLabel" name="motion_touch">
-                 <property name="text">
-                  <string>Motion / Touch</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="8" column="2">
-                <widget class="QPushButton" name="buttonMotionTouch">
-                 <property name="text">
-                  <string>Configure</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="7" column="0">
                 <widget class="QCheckBox" name="debug_enabled">
                  <property name="text">
                   <string>Debug Controller</string>
                  </property>
                 </widget>
                </item>
-               <item row="7" column="2">
+               <item row="3" column="2">
                 <widget class="QPushButton" name="debug_configure">
                  <property name="text">
                   <string>Configure</string>
                  </property>
                 </widget>
                </item>
-               <item row="9" column="0">
-                 <widget class="QCheckBox" name="enable_raw_input">
-                   <property name="toolTip">
-                     <string>Requires restarting yuzu</string>
-                   </property>
-                   <property name="minimumSize">
-                     <size>
-                       <width>0</width>
-                       <height>23</height>
-                     </size>
-                   </property>
-                   <property name="text">
-                     <string>Enable XInput 8 player support (disables web applet)</string>
-                   </property>
-                 </widget>
-               </item>
               </layout>
              </widget>
             </item>
+             <item>
+               <widget class="QGroupBox" name="otherGroupBox">
+                 <property name="title">
+                   <string>Other</string>
+                 </property>
+                 <layout class="QGridLayout" name="OtherGridLayout">
+                   <item row="1" column="0">
+                     <widget class="QCheckBox" name="emulate_analog_keyboard">
+                       <property name="minimumSize">
+                         <size>
+                           <width>0</width>
+                           <height>23</height>
+                         </size>
+                       </property>
+                       <property name="text">
+                         <string>Emulate Analog with Keyboard Input</string>
+                       </property>
+                     </widget>
+                   </item>
+                   <item row="2" column="0">
+                     <widget class="QCheckBox" name="enable_raw_input">
+                       <property name="toolTip">
+                         <string>Requires restarting yuzu</string>
+                       </property>
+                       <property name="minimumSize">
+                         <size>
+                           <width>0</width>
+                           <height>23</height>
+                         </size>
+                       </property>
+                       <property name="text">
+                         <string>Enable XInput 8 player support (disables web applet)</string>
+                       </property>
+                     </widget>
+                   </item>
+                   <item row="3" column="0">
+                     <widget class="QCheckBox" name="mouse_panning">
+                       <property name="minimumSize">
+                         <size>
+                           <width>0</width>
+                           <height>23</height>
+                         </size>
+                       </property>
+                       <property name="text">
+                         <string>Enable mouse panning</string>
+                       </property>
+                     </widget>
+                   </item>
+                   <item row="3" column="2">
+                     <widget class="QSpinBox" name="mouse_panning_sensitivity">
+                       <property name="toolTip">
+                         <string>Mouse sensitivity</string>
+                       </property>
+                       <property name="alignment">
+                         <set>Qt::AlignCenter</set>
+                       </property>
+                       <property name="suffix">
+                         <string>%</string>
+                       </property>
+                       <property name="minimum">
+                         <number>1</number>
+                       </property>
+                       <property name="maximum">
+                         <number>100</number>
+                       </property>
+                       <property name="value">
+                         <number>100</number>
+                       </property>
+                     </widget>
+                   </item>
+                   <item row="4" column="0">
+                     <widget class="QLabel" name="motion_touch">
+                       <property name="text">
+                         <string>Motion / Touch</string>
+                       </property>
+                     </widget>
+                   </item>
+                   <item row="4" column="2">
+                     <widget class="QPushButton" name="buttonMotionTouch">
+                       <property name="text">
+                         <string>Configure</string>
+                       </property>
+                     </widget>
+                   </item>
+                 </layout>
+               </widget>
+             </item>
             <item>
              <spacer name="verticalSpacer">
               <property name="orientation">
diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp
deleted file mode 100644
index 1e7a3751df..0000000000
--- a/src/yuzu/configuration/configure_mouse_advanced.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <memory>
-
-#include <QKeyEvent>
-#include <QMenu>
-#include <QTimer>
-
-#include "common/assert.h"
-#include "common/param_package.h"
-#include "input_common/drivers/keyboard.h"
-#include "input_common/drivers/mouse.h"
-#include "input_common/main.h"
-#include "ui_configure_mouse_advanced.h"
-#include "yuzu/bootmanager.h"
-#include "yuzu/configuration/config.h"
-#include "yuzu/configuration/configure_mouse_advanced.h"
-
-static QString GetKeyName(int key_code) {
-    switch (key_code) {
-    case Qt::LeftButton:
-        return QObject::tr("Click 0");
-    case Qt::RightButton:
-        return QObject::tr("Click 1");
-    case Qt::MiddleButton:
-        return QObject::tr("Click 2");
-    case Qt::BackButton:
-        return QObject::tr("Click 3");
-    case Qt::ForwardButton:
-        return QObject::tr("Click 4");
-    case Qt::Key_Shift:
-        return QObject::tr("Shift");
-    case Qt::Key_Control:
-        return QObject::tr("Ctrl");
-    case Qt::Key_Alt:
-        return QObject::tr("Alt");
-    case Qt::Key_Meta:
-        return {};
-    default:
-        return QKeySequence(key_code).toString();
-    }
-}
-
-static QString ButtonToText(const Common::ParamPackage& param) {
-    if (!param.Has("engine")) {
-        return QObject::tr("[not set]");
-    }
-
-    if (param.Get("engine", "") == "keyboard") {
-        return GetKeyName(param.Get("code", 0));
-    }
-
-    if (param.Get("engine", "") == "sdl") {
-        if (param.Has("hat")) {
-            const QString hat_str = QString::fromStdString(param.Get("hat", ""));
-            const QString direction_str = QString::fromStdString(param.Get("direction", ""));
-
-            return QObject::tr("Hat %1 %2").arg(hat_str, direction_str);
-        }
-
-        if (param.Has("axis")) {
-            const QString axis_str = QString::fromStdString(param.Get("axis", ""));
-            const QString direction_str = QString::fromStdString(param.Get("direction", ""));
-
-            return QObject::tr("Axis %1%2").arg(axis_str, direction_str);
-        }
-
-        if (param.Has("button")) {
-            const QString button_str = QString::fromStdString(param.Get("button", ""));
-
-            return QObject::tr("Button %1").arg(button_str);
-        }
-        return {};
-    }
-
-    return QObject::tr("[unknown]");
-}
-
-ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent,
-                                               InputCommon::InputSubsystem* input_subsystem_)
-    : QDialog(parent),
-      ui(std::make_unique<Ui::ConfigureMouseAdvanced>()), input_subsystem{input_subsystem_},
-      timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) {
-    ui->setupUi(this);
-    setFocusPolicy(Qt::ClickFocus);
-
-    button_map = {
-        ui->left_button, ui->right_button, ui->middle_button, ui->forward_button, ui->back_button,
-    };
-
-    for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) {
-        auto* const button = button_map[button_id];
-        if (button == nullptr) {
-            continue;
-        }
-
-        button->setContextMenuPolicy(Qt::CustomContextMenu);
-        connect(button, &QPushButton::clicked, [=, this] {
-            HandleClick(
-                button_map[button_id],
-                [=, this](const Common::ParamPackage& params) {
-                    buttons_param[button_id] = params;
-                },
-                InputCommon::Polling::InputType::Button);
-        });
-        connect(button, &QPushButton::customContextMenuRequested,
-                [=, this](const QPoint& menu_location) {
-                    QMenu context_menu;
-                    context_menu.addAction(tr("Clear"), [&] {
-                        buttons_param[button_id].Clear();
-                        button_map[button_id]->setText(tr("[not set]"));
-                    });
-                    context_menu.addAction(tr("Restore Default"), [&] {
-                        buttons_param[button_id] =
-                            Common::ParamPackage{InputCommon::GenerateKeyboardParam(
-                                Config::default_mouse_buttons[button_id])};
-                        button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
-                    });
-                    context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
-                });
-    }
-
-    connect(ui->buttonClearAll, &QPushButton::clicked, [this] { ClearAll(); });
-    connect(ui->buttonRestoreDefaults, &QPushButton::clicked, [this] { RestoreDefaults(); });
-
-    timeout_timer->setSingleShot(true);
-    connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
-
-    connect(poll_timer.get(), &QTimer::timeout, [this] {
-        const auto& params = input_subsystem->GetNextInput();
-        if (params.Has("engine")) {
-            SetPollingResult(params, false);
-            return;
-        }
-    });
-
-    LoadConfiguration();
-    resize(0, 0);
-}
-
-ConfigureMouseAdvanced::~ConfigureMouseAdvanced() = default;
-
-void ConfigureMouseAdvanced::ApplyConfiguration() {
-    std::transform(buttons_param.begin(), buttons_param.end(),
-                   Settings::values.mouse_buttons.begin(),
-                   [](const Common::ParamPackage& param) { return param.Serialize(); });
-}
-
-void ConfigureMouseAdvanced::LoadConfiguration() {
-    std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(),
-                   buttons_param.begin(),
-                   [](const std::string& str) { return Common::ParamPackage(str); });
-    UpdateButtonLabels();
-}
-
-void ConfigureMouseAdvanced::changeEvent(QEvent* event) {
-    if (event->type() == QEvent::LanguageChange) {
-        RetranslateUI();
-    }
-
-    QDialog::changeEvent(event);
-}
-
-void ConfigureMouseAdvanced::RetranslateUI() {
-    ui->retranslateUi(this);
-}
-
-void ConfigureMouseAdvanced::RestoreDefaults() {
-    for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) {
-        buttons_param[button_id] = Common::ParamPackage{
-            InputCommon::GenerateKeyboardParam(Config::default_mouse_buttons[button_id])};
-    }
-
-    UpdateButtonLabels();
-}
-
-void ConfigureMouseAdvanced::ClearAll() {
-    for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
-        const auto* const button = button_map[i];
-        if (button != nullptr && button->isEnabled()) {
-            buttons_param[i].Clear();
-        }
-    }
-
-    UpdateButtonLabels();
-}
-
-void ConfigureMouseAdvanced::UpdateButtonLabels() {
-    for (int button = 0; button < Settings::NativeMouseButton::NumMouseButtons; button++) {
-        button_map[button]->setText(ButtonToText(buttons_param[button]));
-    }
-}
-
-void ConfigureMouseAdvanced::HandleClick(
-    QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
-    InputCommon::Polling::InputType type) {
-    button->setText(tr("[press key]"));
-    button->setFocus();
-
-    input_setter = new_input_setter;
-
-    input_subsystem->BeginMapping(type);
-
-    QWidget::grabMouse();
-    QWidget::grabKeyboard();
-
-    timeout_timer->start(2500); // Cancel after 2.5 seconds
-    poll_timer->start(50);      // Check for new inputs every 50ms
-}
-
-void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) {
-    timeout_timer->stop();
-    poll_timer->stop();
-    input_subsystem->StopMapping();
-
-    QWidget::releaseMouse();
-    QWidget::releaseKeyboard();
-
-    if (!abort) {
-        (*input_setter)(params);
-    }
-
-    UpdateButtonLabels();
-    input_setter = std::nullopt;
-}
-
-void ConfigureMouseAdvanced::mousePressEvent(QMouseEvent* event) {
-    if (!input_setter || !event) {
-        return;
-    }
-
-    const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
-    input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button);
-}
-
-void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) {
-    if (!input_setter || !event) {
-        return;
-    }
-
-    if (event->key() != Qt::Key_Escape) {
-        input_subsystem->GetKeyboard()->PressKey(event->key());
-    }
-}
diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h
deleted file mode 100644
index 5fa534eaf2..0000000000
--- a/src/yuzu/configuration/configure_mouse_advanced.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include <optional>
-#include <QDialog>
-
-class QCheckBox;
-class QPushButton;
-class QTimer;
-
-namespace InputCommon {
-class InputSubsystem;
-}
-
-namespace Ui {
-class ConfigureMouseAdvanced;
-}
-
-class ConfigureMouseAdvanced : public QDialog {
-    Q_OBJECT
-
-public:
-    explicit ConfigureMouseAdvanced(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_);
-    ~ConfigureMouseAdvanced() override;
-
-    void ApplyConfiguration();
-
-private:
-    void changeEvent(QEvent* event) override;
-    void RetranslateUI();
-
-    /// Load configuration settings.
-    void LoadConfiguration();
-    /// Restore all buttons to their default values.
-    void RestoreDefaults();
-    /// Clear all input configuration
-    void ClearAll();
-
-    /// Update UI to reflect current configuration.
-    void UpdateButtonLabels();
-
-    /// Called when the button was pressed.
-    void HandleClick(QPushButton* button,
-                     std::function<void(const Common::ParamPackage&)> new_input_setter,
-                     InputCommon::Polling::InputType type);
-
-    /// Finish polling and configure input using the input_setter
-    void SetPollingResult(const Common::ParamPackage& params, bool abort);
-
-    /// Handle mouse button press events.
-    void mousePressEvent(QMouseEvent* event) override;
-
-    /// Handle key press events.
-    void keyPressEvent(QKeyEvent* event) override;
-
-    std::unique_ptr<Ui::ConfigureMouseAdvanced> ui;
-
-    InputCommon::InputSubsystem* input_subsystem;
-
-    /// This will be the the setting function when an input is awaiting configuration.
-    std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
-
-    std::array<QPushButton*, Settings::NativeMouseButton::NumMouseButtons> button_map;
-    std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons> buttons_param;
-
-    std::unique_ptr<QTimer> timeout_timer;
-    std::unique_ptr<QTimer> poll_timer;
-};
diff --git a/src/yuzu/configuration/configure_mouse_advanced.ui b/src/yuzu/configuration/configure_mouse_advanced.ui
deleted file mode 100644
index 5b99e1c375..0000000000
--- a/src/yuzu/configuration/configure_mouse_advanced.ui
+++ /dev/null
@@ -1,335 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ConfigureMouseAdvanced</class>
- <widget class="QDialog" name="ConfigureMouseAdvanced">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>310</width>
-    <height>193</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>Configure Mouse</string>
-  </property>
-  <property name="styleSheet">
-   <string notr="true">QPushButton {
-  min-width: 60px;
-}</string>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
-   <item>
-    <widget class="QGroupBox" name="gridGroupBox">
-     <property name="title">
-      <string>Mouse Buttons</string>
-     </property>
-     <layout class="QGridLayout" name="gridLayout">
-      <item row="3" column="5">
-       <layout class="QVBoxLayout" name="verticalLayout_6">
-        <item>
-         <layout class="QHBoxLayout" name="horizontalLayout_5">
-          <item>
-           <widget class="QLabel" name="label_5">
-            <property name="text">
-             <string>Forward:</string>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </item>
-        <item>
-         <widget class="QPushButton" name="forward_button">
-          <property name="minimumSize">
-           <size>
-            <width>68</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="maximumSize">
-           <size>
-            <width>68</width>
-            <height>16777215</height>
-           </size>
-          </property>
-          <property name="text">
-           <string/>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-      <item row="3" column="1">
-       <layout class="QVBoxLayout" name="verticalLayout_5">
-        <item>
-         <layout class="QHBoxLayout" name="horizontalLayout_4">
-          <item>
-           <widget class="QLabel" name="label_4">
-            <property name="minimumSize">
-             <size>
-              <width>54</width>
-              <height>0</height>
-             </size>
-            </property>
-            <property name="text">
-             <string>Back:</string>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </item>
-        <item>
-         <widget class="QPushButton" name="back_button">
-          <property name="minimumSize">
-           <size>
-            <width>68</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="text">
-           <string/>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-      <item row="0" column="1">
-       <layout class="QVBoxLayout" name="verticalLayout_2">
-        <item>
-         <layout class="QHBoxLayout" name="horizontalLayout">
-          <item>
-           <widget class="QLabel" name="label">
-            <property name="text">
-             <string>Left:</string>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </item>
-        <item>
-         <widget class="QPushButton" name="left_button">
-          <property name="minimumSize">
-           <size>
-            <width>68</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="text">
-           <string/>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-      <item row="0" column="3">
-       <layout class="QVBoxLayout" name="verticalLayout_3">
-        <item>
-         <layout class="QHBoxLayout" name="horizontalLayout_2">
-          <item>
-           <widget class="QLabel" name="label_2">
-            <property name="text">
-             <string>Middle:</string>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </item>
-        <item>
-         <widget class="QPushButton" name="middle_button">
-          <property name="minimumSize">
-           <size>
-            <width>68</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="maximumSize">
-           <size>
-            <width>68</width>
-            <height>16777215</height>
-           </size>
-          </property>
-          <property name="text">
-           <string/>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-      <item row="0" column="6">
-       <spacer name="horizontalSpacer_2">
-        <property name="orientation">
-         <enum>Qt::Horizontal</enum>
-        </property>
-        <property name="sizeType">
-         <enum>QSizePolicy::Fixed</enum>
-        </property>
-        <property name="sizeHint" stdset="0">
-         <size>
-          <width>0</width>
-          <height>20</height>
-         </size>
-        </property>
-       </spacer>
-      </item>
-      <item row="0" column="0">
-       <spacer name="horizontalSpacer">
-        <property name="orientation">
-         <enum>Qt::Horizontal</enum>
-        </property>
-        <property name="sizeType">
-         <enum>QSizePolicy::Fixed</enum>
-        </property>
-        <property name="sizeHint" stdset="0">
-         <size>
-          <width>0</width>
-          <height>20</height>
-         </size>
-        </property>
-       </spacer>
-      </item>
-      <item row="0" column="5">
-       <layout class="QVBoxLayout" name="verticalLayout_4">
-        <item>
-         <layout class="QHBoxLayout" name="horizontalLayout_3">
-          <item>
-           <widget class="QLabel" name="label_3">
-            <property name="text">
-             <string>Right:</string>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </item>
-        <item>
-         <widget class="QPushButton" name="right_button">
-          <property name="minimumSize">
-           <size>
-            <width>68</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="maximumSize">
-           <size>
-            <width>68</width>
-            <height>16777215</height>
-           </size>
-          </property>
-          <property name="text">
-           <string/>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-      <item row="0" column="2">
-       <spacer name="horizontalSpacer_4">
-        <property name="orientation">
-         <enum>Qt::Horizontal</enum>
-        </property>
-        <property name="sizeHint" stdset="0">
-         <size>
-          <width>0</width>
-          <height>20</height>
-         </size>
-        </property>
-       </spacer>
-      </item>
-      <item row="0" column="4">
-       <spacer name="horizontalSpacer_5">
-        <property name="orientation">
-         <enum>Qt::Horizontal</enum>
-        </property>
-        <property name="sizeHint" stdset="0">
-         <size>
-          <width>0</width>
-          <height>20</height>
-         </size>
-        </property>
-       </spacer>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <layout class="QHBoxLayout" name="horizontalLayout_6">
-     <item>
-      <widget class="QPushButton" name="buttonClearAll">
-       <property name="minimumSize">
-        <size>
-         <width>68</width>
-         <height>0</height>
-        </size>
-       </property>
-       <property name="maximumSize">
-        <size>
-         <width>68</width>
-         <height>16777215</height>
-        </size>
-       </property>
-       <property name="text">
-        <string>Clear</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <widget class="QPushButton" name="buttonRestoreDefaults">
-       <property name="minimumSize">
-        <size>
-         <width>68</width>
-         <height>0</height>
-        </size>
-       </property>
-       <property name="maximumSize">
-        <size>
-         <width>68</width>
-         <height>16777215</height>
-        </size>
-       </property>
-       <property name="text">
-        <string>Defaults</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <spacer name="horizontalSpacer_3">
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="sizeHint" stdset="0">
-        <size>
-         <width>0</width>
-         <height>20</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
-     <item>
-      <widget class="QDialogButtonBox" name="buttonBox">
-       <property name="styleSheet">
-        <string notr="true"/>
-       </property>
-       <property name="standardButtons">
-        <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
-       </property>
-      </widget>
-     </item>
-    </layout>
-   </item>
-  </layout>
- </widget>
- <resources/>
- <connections>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>accepted()</signal>
-   <receiver>ConfigureMouseAdvanced</receiver>
-   <slot>accept()</slot>
-  </connection>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>rejected()</signal>
-   <receiver>ConfigureMouseAdvanced</receiver>
-   <slot>reject()</slot>
-  </connection>
- </connections>
-</ui>
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 7ca09a635b..8e9c7d211c 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -83,163 +83,6 @@ static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs>
     },
 }};
 
-static const std::array<int, Settings::NativeMouseButton::NumMouseButtons> default_mouse_buttons = {
-    SDL_SCANCODE_LEFTBRACKET, SDL_SCANCODE_RIGHTBRACKET, SDL_SCANCODE_APOSTROPHE,
-    SDL_SCANCODE_MINUS,       SDL_SCANCODE_EQUALS,
-};
-
-static const std::array<int, 0x8A> keyboard_keys = {
-    0,
-    0,
-    0,
-    0,
-    SDL_SCANCODE_A,
-    SDL_SCANCODE_B,
-    SDL_SCANCODE_C,
-    SDL_SCANCODE_D,
-    SDL_SCANCODE_E,
-    SDL_SCANCODE_F,
-    SDL_SCANCODE_G,
-    SDL_SCANCODE_H,
-    SDL_SCANCODE_I,
-    SDL_SCANCODE_J,
-    SDL_SCANCODE_K,
-    SDL_SCANCODE_L,
-    SDL_SCANCODE_M,
-    SDL_SCANCODE_N,
-    SDL_SCANCODE_O,
-    SDL_SCANCODE_P,
-    SDL_SCANCODE_Q,
-    SDL_SCANCODE_R,
-    SDL_SCANCODE_S,
-    SDL_SCANCODE_T,
-    SDL_SCANCODE_U,
-    SDL_SCANCODE_V,
-    SDL_SCANCODE_W,
-    SDL_SCANCODE_X,
-    SDL_SCANCODE_Y,
-    SDL_SCANCODE_Z,
-    SDL_SCANCODE_1,
-    SDL_SCANCODE_2,
-    SDL_SCANCODE_3,
-    SDL_SCANCODE_4,
-    SDL_SCANCODE_5,
-    SDL_SCANCODE_6,
-    SDL_SCANCODE_7,
-    SDL_SCANCODE_8,
-    SDL_SCANCODE_9,
-    SDL_SCANCODE_0,
-    SDL_SCANCODE_RETURN,
-    SDL_SCANCODE_ESCAPE,
-    SDL_SCANCODE_BACKSPACE,
-    SDL_SCANCODE_TAB,
-    SDL_SCANCODE_SPACE,
-    SDL_SCANCODE_MINUS,
-    SDL_SCANCODE_EQUALS,
-    SDL_SCANCODE_LEFTBRACKET,
-    SDL_SCANCODE_RIGHTBRACKET,
-    SDL_SCANCODE_BACKSLASH,
-    0,
-    SDL_SCANCODE_SEMICOLON,
-    SDL_SCANCODE_APOSTROPHE,
-    SDL_SCANCODE_GRAVE,
-    SDL_SCANCODE_COMMA,
-    SDL_SCANCODE_PERIOD,
-    SDL_SCANCODE_SLASH,
-    SDL_SCANCODE_CAPSLOCK,
-
-    SDL_SCANCODE_F1,
-    SDL_SCANCODE_F2,
-    SDL_SCANCODE_F3,
-    SDL_SCANCODE_F4,
-    SDL_SCANCODE_F5,
-    SDL_SCANCODE_F6,
-    SDL_SCANCODE_F7,
-    SDL_SCANCODE_F8,
-    SDL_SCANCODE_F9,
-    SDL_SCANCODE_F10,
-    SDL_SCANCODE_F11,
-    SDL_SCANCODE_F12,
-
-    0,
-    SDL_SCANCODE_SCROLLLOCK,
-    SDL_SCANCODE_PAUSE,
-    SDL_SCANCODE_INSERT,
-    SDL_SCANCODE_HOME,
-    SDL_SCANCODE_PAGEUP,
-    SDL_SCANCODE_DELETE,
-    SDL_SCANCODE_END,
-    SDL_SCANCODE_PAGEDOWN,
-    SDL_SCANCODE_RIGHT,
-    SDL_SCANCODE_LEFT,
-    SDL_SCANCODE_DOWN,
-    SDL_SCANCODE_UP,
-
-    SDL_SCANCODE_NUMLOCKCLEAR,
-    SDL_SCANCODE_KP_DIVIDE,
-    SDL_SCANCODE_KP_MULTIPLY,
-    SDL_SCANCODE_KP_MINUS,
-    SDL_SCANCODE_KP_PLUS,
-    SDL_SCANCODE_KP_ENTER,
-    SDL_SCANCODE_KP_1,
-    SDL_SCANCODE_KP_2,
-    SDL_SCANCODE_KP_3,
-    SDL_SCANCODE_KP_4,
-    SDL_SCANCODE_KP_5,
-    SDL_SCANCODE_KP_6,
-    SDL_SCANCODE_KP_7,
-    SDL_SCANCODE_KP_8,
-    SDL_SCANCODE_KP_9,
-    SDL_SCANCODE_KP_0,
-    SDL_SCANCODE_KP_PERIOD,
-
-    0,
-    0,
-    SDL_SCANCODE_POWER,
-    SDL_SCANCODE_KP_EQUALS,
-
-    SDL_SCANCODE_F13,
-    SDL_SCANCODE_F14,
-    SDL_SCANCODE_F15,
-    SDL_SCANCODE_F16,
-    SDL_SCANCODE_F17,
-    SDL_SCANCODE_F18,
-    SDL_SCANCODE_F19,
-    SDL_SCANCODE_F20,
-    SDL_SCANCODE_F21,
-    SDL_SCANCODE_F22,
-    SDL_SCANCODE_F23,
-    SDL_SCANCODE_F24,
-
-    0,
-    SDL_SCANCODE_HELP,
-    SDL_SCANCODE_MENU,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    SDL_SCANCODE_KP_COMMA,
-    SDL_SCANCODE_KP_LEFTPAREN,
-    SDL_SCANCODE_KP_RIGHTPAREN,
-    0,
-    0,
-    0,
-    0,
-};
-
-static const std::array<int, 8> keyboard_mods{
-    SDL_SCANCODE_LCTRL, SDL_SCANCODE_LSHIFT, SDL_SCANCODE_LALT, SDL_SCANCODE_LGUI,
-    SDL_SCANCODE_RCTRL, SDL_SCANCODE_RSHIFT, SDL_SCANCODE_RALT, SDL_SCANCODE_RGUI,
-};
-
 template <>
 void Config::ReadSetting(const std::string& group, Settings::BasicSetting<std::string>& setting) {
     setting = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault());
@@ -283,14 +126,6 @@ void Config::ReadValues() {
     }
 
     ReadSetting("ControlsGeneral", Settings::values.mouse_enabled);
-    for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
-        std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]);
-        Settings::values.mouse_buttons[i] = sdl2_config->Get(
-            "ControlsGeneral", std::string("mouse_") + Settings::NativeMouseButton::mapping[i],
-            default_param);
-        if (Settings::values.mouse_buttons[i].empty())
-            Settings::values.mouse_buttons[i] = default_param;
-    }
 
     ReadSetting("ControlsGeneral", Settings::values.touch_device);
 
@@ -365,15 +200,6 @@ void Config::ReadValues() {
 
     ReadSetting("ControlsGeneral", Settings::values.udp_input_servers);
 
-    std::transform(keyboard_keys.begin(), keyboard_keys.end(),
-                   Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam);
-    std::transform(keyboard_mods.begin(), keyboard_mods.end(),
-                   Settings::values.keyboard_keys.begin() +
-                       Settings::NativeKeyboard::LeftControlKey,
-                   InputCommon::GenerateKeyboardParam);
-    std::transform(keyboard_mods.begin(), keyboard_mods.end(),
-                   Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam);
-
     // Data Storage
     ReadSetting("Data Storage", Settings::values.use_virtual_sd);
     FS::SetYuzuPath(FS::YuzuPath::NANDDir,

From f4e5f89e6fb9d68cd4ba7d98c281584c50f0e149 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 14 Nov 2021 21:28:38 -0600
Subject: [PATCH 79/88] core/hid: Improve accuary of mouse implementation

---
 src/core/hid/emulated_devices.cpp             | 10 +++---
 src/core/hid/emulated_devices.h               |  4 +--
 src/core/hid/hid_types.h                      | 35 ++++++++++++-------
 src/core/hid/input_converter.cpp              |  4 +++
 .../hle/service/hid/controllers/keyboard.cpp  |  3 +-
 .../hle/service/hid/controllers/keyboard.h    |  1 +
 .../hle/service/hid/controllers/mouse.cpp     |  7 ++--
 src/core/hle/service/hid/controllers/mouse.h  |  2 ++
 src/core/hle/service/hid/hid.cpp              | 29 +++++++++------
 src/core/hle/service/hid/hid.h                |  4 +--
 src/input_common/drivers/mouse.cpp            | 21 ++++++-----
 src/input_common/drivers/mouse.h              |  1 +
 src/yuzu/bootmanager.cpp                      |  4 +--
 .../configure_input_advanced.cpp              |  2 ++
 14 files changed, 79 insertions(+), 48 deletions(-)

diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
index 70a494097a..874780ec28 100644
--- a/src/core/hid/emulated_devices.cpp
+++ b/src/core/hid/emulated_devices.cpp
@@ -376,9 +376,9 @@ void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std
 
 void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) {
     std::lock_guard lock{mutex};
-    const auto stick_value = TransformToStick(callback);
+    const auto touch_value = TransformToTouch(callback);
 
-    device_status.mouse_stick_value = stick_value;
+    device_status.mouse_stick_value = touch_value;
 
     if (is_configuring) {
         device_status.mouse_position_state = {};
@@ -386,8 +386,8 @@ void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) {
         return;
     }
 
-    device_status.mouse_position_state.x = stick_value.x.value;
-    device_status.mouse_position_state.y = stick_value.y.value;
+    device_status.mouse_position_state.x = touch_value.x.value;
+    device_status.mouse_position_state.y = touch_value.y.value;
 
     TriggerOnChange(DeviceTriggerType::Mouse);
 }
@@ -420,7 +420,7 @@ MousePosition EmulatedDevices::GetMousePosition() const {
     return device_status.mouse_position_state;
 }
 
-AnalogStickState EmulatedDevices::GetMouseDeltaWheel() const {
+AnalogStickState EmulatedDevices::GetMouseWheel() const {
     return device_status.mouse_wheel_state;
 }
 
diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h
index 49edfd255b..05a945d083 100644
--- a/src/core/hid/emulated_devices.h
+++ b/src/core/hid/emulated_devices.h
@@ -38,7 +38,7 @@ using MouseButtonValues =
     std::array<Common::Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>;
 using MouseAnalogValues =
     std::array<Common::Input::AnalogStatus, Settings::NativeMouseWheel::NumMouseWheels>;
-using MouseStickValue = Common::Input::StickStatus;
+using MouseStickValue = Common::Input::TouchStatus;
 
 struct MousePosition {
     f32 x;
@@ -130,7 +130,7 @@ public:
     MousePosition GetMousePosition() const;
 
     /// Returns the latest mouse wheel change
-    AnalogStickState GetMouseDeltaWheel() const;
+    AnalogStickState GetMouseWheel() const;
 
     /**
      * Adds a callback to the list of events
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index af95f3aff9..8b12f63ad9 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -502,21 +502,30 @@ static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incor
 // This is nn::hid::KeyboardModifier
 struct KeyboardModifier {
     union {
-        u64 raw{};
-        BitField<0, 1, u64> control;
-        BitField<1, 1, u64> shift;
-        BitField<2, 1, u64> left_alt;
-        BitField<3, 1, u64> right_alt;
-        BitField<4, 1, u64> gui;
-        BitField<8, 1, u64> caps_lock;
-        BitField<9, 1, u64> scroll_lock;
-        BitField<10, 1, u64> num_lock;
-        BitField<11, 1, u64> katakana;
-        BitField<12, 1, u64> hiragana;
-        BitField<32, 1, u64> unknown;
+        u32 raw{};
+        BitField<0, 1, u32> control;
+        BitField<1, 1, u32> shift;
+        BitField<2, 1, u32> left_alt;
+        BitField<3, 1, u32> right_alt;
+        BitField<4, 1, u32> gui;
+        BitField<8, 1, u32> caps_lock;
+        BitField<9, 1, u32> scroll_lock;
+        BitField<10, 1, u32> num_lock;
+        BitField<11, 1, u32> katakana;
+        BitField<12, 1, u32> hiragana;
     };
 };
-static_assert(sizeof(KeyboardModifier) == 0x8, "KeyboardModifier is an invalid size");
+
+static_assert(sizeof(KeyboardModifier) == 0x4, "KeyboardModifier is an invalid size");
+
+// This is nn::hid::KeyboardAttribute
+struct KeyboardAttribute {
+    union {
+        u32 raw{};
+        BitField<0, 1, u32> is_connected;
+    };
+};
+static_assert(sizeof(KeyboardAttribute) == 0x4, "KeyboardAttribute is an invalid size");
 
 // This is nn::hid::KeyboardKey
 struct KeyboardKey {
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index c4e6539568..f5acff6e0f 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -175,6 +175,10 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus&
     case Common::Input::InputType::Touch:
         status = callback.touch_status;
         break;
+    case Common::Input::InputType::Stick:
+        status.x = callback.stick_status.x;
+        status.y = callback.stick_status.y;
+        break;
     default:
         LOG_ERROR(Input, "Conversion from type {} to touch not implemented", callback.type);
         break;
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 0ef8af0e69..9588a69101 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -42,8 +42,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
 
         next_state.key = keyboard_state;
         next_state.modifier = keyboard_modifier_state;
-        // This is always enabled on HW. Check what it actually does
-        next_state.modifier.unknown.Assign(1);
+        next_state.attribute.is_connected.Assign(1);
     }
 
     keyboard_lifo.WriteNextEntry(next_state);
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index ec5dd607cb..0d61cb4709 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -38,6 +38,7 @@ private:
     struct KeyboardState {
         s64 sampling_number;
         Core::HID::KeyboardModifier modifier;
+        Core::HID::KeyboardAttribute attribute;
         Core::HID::KeyboardKey key;
     };
     static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 9c408e7f40..ba79888ae0 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -38,15 +38,16 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
     if (Settings::values.mouse_enabled) {
         const auto& mouse_button_state = emulated_devices->GetMouseButtons();
         const auto& mouse_position_state = emulated_devices->GetMousePosition();
-        const auto& mouse_wheel_state = emulated_devices->GetMouseDeltaWheel();
+        const auto& mouse_wheel_state = emulated_devices->GetMouseWheel();
         next_state.attribute.is_connected.Assign(1);
         next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width);
         next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height);
         next_state.delta_x = next_state.x - last_entry.x;
         next_state.delta_y = next_state.y - last_entry.y;
-        next_state.delta_wheel_x = mouse_wheel_state.x;
-        next_state.delta_wheel_y = mouse_wheel_state.y;
+        next_state.delta_wheel_x = mouse_wheel_state.x - last_mouse_wheel_state.x;
+        next_state.delta_wheel_y = mouse_wheel_state.y - last_mouse_wheel_state.y;
 
+        last_mouse_wheel_state = mouse_wheel_state;
         next_state.button = mouse_button_state;
     }
 
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 25017f1173..1ac69aa6ff 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -14,6 +14,7 @@
 namespace Core::HID {
 class EmulatedDevices;
 struct MouseState;
+struct AnalogStickState;
 } // namespace Core::HID
 
 namespace Service::HID {
@@ -37,6 +38,7 @@ private:
     static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
     Core::HID::MouseState next_state{};
 
+    Core::HID::AnalogStickState last_mouse_wheel_state;
     Core::HID::EmulatedDevices* emulated_devices;
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index e740b43314..95fc07325b 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -35,9 +35,9 @@ namespace Service::HID {
 
 // Updating period for each HID device.
 // Period time is obtained by measuring the number of samples in a second on HW using a homebrew
-constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000};      // (4ms, 250Hz)
-constexpr auto keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
-constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000};   // (5ms, 200Hz)
+constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000};            // (4ms, 250Hz)
+constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
+constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000};         // (5ms, 200Hz)
 constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
 
 IAppletResource::IAppletResource(Core::System& system_,
@@ -79,11 +79,11 @@ IAppletResource::IAppletResource(Core::System& system_,
             const auto guard = LockService();
             UpdateControllers(user_data, ns_late);
         });
-    keyboard_update_event = Core::Timing::CreateEvent(
-        "HID::UpdatekeyboardCallback",
+    mouse_keyboard_update_event = Core::Timing::CreateEvent(
+        "HID::UpdateMouseKeyboardCallback",
         [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
             const auto guard = LockService();
-            UpdateKeyboard(user_data, ns_late);
+            UpdateMouseKeyboard(user_data, ns_late);
         });
     motion_update_event = Core::Timing::CreateEvent(
         "HID::UpdateMotionCallback",
@@ -93,7 +93,7 @@ IAppletResource::IAppletResource(Core::System& system_,
         });
 
     system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
-    system.CoreTiming().ScheduleEvent(keyboard_update_ns, keyboard_update_event);
+    system.CoreTiming().ScheduleEvent(mouse_keyboard_update_ns, mouse_keyboard_update_event);
     system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event);
 
     system.HIDCore().ReloadInputDevices();
@@ -109,7 +109,7 @@ void IAppletResource::DeactivateController(HidController controller) {
 
 IAppletResource::~IAppletResource() {
     system.CoreTiming().UnscheduleEvent(pad_update_event, 0);
-    system.CoreTiming().UnscheduleEvent(keyboard_update_event, 0);
+    system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
     system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
 }
 
@@ -130,6 +130,10 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
         if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) {
             continue;
         }
+        // Mouse has it's own update event
+        if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {
+            continue;
+        }
         controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(),
                              SHARED_MEMORY_SIZE);
     }
@@ -142,18 +146,21 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
     core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);
 }
 
-void IAppletResource::UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
+void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,
+                                          std::chrono::nanoseconds ns_late) {
     auto& core_timing = system.CoreTiming();
 
+    controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(
+        core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
     controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(
         core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
 
     // If ns_late is higher than the update rate ignore the delay
-    if (ns_late > keyboard_update_ns) {
+    if (ns_late > mouse_keyboard_update_ns) {
         ns_late = {};
     }
 
-    core_timing.ScheduleEvent(keyboard_update_ns - ns_late, keyboard_update_event);
+    core_timing.ScheduleEvent(mouse_keyboard_update_ns - ns_late, mouse_keyboard_update_event);
 }
 
 void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index bbad165f89..ab00841180 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -70,13 +70,13 @@ private:
 
     void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
     void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
-    void UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
+    void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
     void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
 
     KernelHelpers::ServiceContext& service_context;
 
     std::shared_ptr<Core::Timing::EventType> pad_update_event;
-    std::shared_ptr<Core::Timing::EventType> keyboard_update_event;
+    std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
     std::shared_ptr<Core::Timing::EventType> motion_update_event;
 
     std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
index 478737db22..05fd7f9c0d 100644
--- a/src/input_common/drivers/mouse.cpp
+++ b/src/input_common/drivers/mouse.cpp
@@ -39,7 +39,7 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
     Common::SetCurrentThreadName("yuzu:input:Mouse");
     constexpr int update_time = 10;
     while (!stop_token.stop_requested()) {
-        if (Settings::values.mouse_panning) {
+        if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
             // Slow movement by 4%
             last_mouse_change *= 0.96f;
             const float sensitivity =
@@ -52,14 +52,17 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
             StopPanning();
         }
         std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
-
-        // Reset wheel position
-        SetAxis(identifier, wheel_axis_x, 0);
-        SetAxis(identifier, wheel_axis_y, 0);
     }
 }
 
 void Mouse::MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int center_y) {
+    // If native mouse is enabled just set the screen coordinates
+    if (Settings::values.mouse_enabled) {
+        SetAxis(identifier, mouse_axis_x, touch_x);
+        SetAxis(identifier, mouse_axis_y, touch_y);
+        return;
+    }
+
     SetAxis(identifier, touch_axis_x, touch_x);
     SetAxis(identifier, touch_axis_y, touch_y);
 
@@ -121,7 +124,7 @@ void Mouse::PressButton(int x, int y, f32 touch_x, f32 touch_y, MouseButton butt
 void Mouse::ReleaseButton(MouseButton button) {
     SetButton(identifier, static_cast<int>(button), false);
 
-    if (!Settings::values.mouse_panning) {
+    if (!Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
         SetAxis(identifier, mouse_axis_x, 0);
         SetAxis(identifier, mouse_axis_y, 0);
     }
@@ -129,8 +132,10 @@ void Mouse::ReleaseButton(MouseButton button) {
 }
 
 void Mouse::MouseWheelChange(int x, int y) {
-    SetAxis(identifier, wheel_axis_x, static_cast<f32>(x));
-    SetAxis(identifier, wheel_axis_y, static_cast<f32>(y));
+    wheel_position.x += x;
+    wheel_position.y += y;
+    SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x));
+    SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y));
 }
 
 void Mouse::ReleaseAllButtons() {
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index 429502af9f..f7e6db0b5f 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -72,6 +72,7 @@ private:
     Common::Vec2<int> mouse_origin;
     Common::Vec2<int> last_mouse_position;
     Common::Vec2<float> last_mouse_change;
+    Common::Vec2<int> wheel_position;
     bool button_pressed;
     int mouse_panning_timout{};
     std::jthread update_thread;
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 1015e51b56..2313a41894 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -729,7 +729,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
     const int center_y = height() / 2;
     input_subsystem->GetMouse()->MouseMove(x, y, touch_x, touch_y, center_x, center_y);
 
-    if (Settings::values.mouse_panning) {
+    if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
         QCursor::setPos(mapToGlobal({center_x, center_y}));
     }
 
@@ -1044,7 +1044,7 @@ void GRenderWindow::showEvent(QShowEvent* event) {
 
 bool GRenderWindow::eventFilter(QObject* object, QEvent* event) {
     if (event->type() == QEvent::HoverMove) {
-        if (Settings::values.mouse_panning) {
+        if (Settings::values.mouse_panning || Settings::values.mouse_enabled) {
             auto* hover_event = static_cast<QMouseEvent*>(event);
             mouseMoveEvent(hover_event);
             return false;
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index cf8aad4abf..e6127f9e67 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -179,4 +179,6 @@ void ConfigureInputAdvanced::RetranslateUI() {
 void ConfigureInputAdvanced::UpdateUIEnabled() {
     ui->debug_configure->setEnabled(ui->debug_enabled->isChecked());
     ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked());
+    ui->mouse_panning->setEnabled(!ui->mouse_enabled->isChecked());
+    ui->mouse_panning_sensitivity->setEnabled(!ui->mouse_enabled->isChecked());
 }

From 42949738f2c01a4125a9a385c9100240181153ec Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 14 Nov 2021 21:56:54 -0600
Subject: [PATCH 80/88] kraken: Address comments from review

Fix compiler bug
---
 src/core/hid/hid_types.h                      |  3 +-
 src/core/hle/service/hid/controllers/npad.cpp |  2 +-
 src/core/hle/service/hid/ring_lifo.h          |  7 +-
 src/input_common/drivers/gc_adapter.cpp       | 16 +----
 src/input_common/drivers/gc_adapter.h         |  2 +-
 src/input_common/drivers/mouse.cpp            |  2 +-
 src/input_common/drivers/mouse.h              |  2 +-
 src/input_common/drivers/sdl_driver.cpp       |  2 +-
 src/input_common/drivers/sdl_driver.h         |  2 +-
 src/input_common/drivers/tas_input.cpp        |  2 +-
 src/input_common/drivers/tas_input.h          |  2 +-
 src/input_common/drivers/touch_screen.cpp     |  2 +-
 src/input_common/drivers/touch_screen.h       |  2 +-
 src/input_common/input_engine.cpp             |  4 +-
 src/input_common/input_engine.h               |  2 +-
 src/yuzu/bootmanager.cpp                      | 66 +++++++++----------
 src/yuzu/bootmanager.h                        |  2 +-
 17 files changed, 54 insertions(+), 66 deletions(-)

diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 8b12f63ad9..3cbe162603 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -564,8 +564,9 @@ struct MouseState {
     s32 y;
     s32 delta_x;
     s32 delta_y;
-    s32 delta_wheel_x;
+    // Axis Order in HW is switched for the wheel
     s32 delta_wheel_y;
+    s32 delta_wheel_x;
     MouseButton button;
     MouseAttribute attribute;
 };
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index eaec791399..4b23230e1c 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -345,7 +345,7 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
         constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R |
                                           btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp |
                                           btn::StickRRight | btn::StickRDown;
-        pad_entry.npad_buttons.raw |= button_state.raw & right_button_mask;
+        pad_entry.npad_buttons.raw = button_state.raw & right_button_mask;
         pad_entry.r_stick = stick_state.right;
     }
 
diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h
index 6209ed0d15..f0e0bab7fe 100644
--- a/src/core/hle/service/hid/ring_lifo.h
+++ b/src/core/hle/service/hid/ring_lifo.h
@@ -7,7 +7,6 @@
 #include <array>
 
 #include "common/common_types.h"
-#include "common/swap.h"
 
 namespace Service::HID {
 constexpr std::size_t max_buffer_size = 17;
@@ -21,7 +20,7 @@ struct AtomicStorage {
 template <typename State>
 struct Lifo {
     s64 timestamp{};
-    s64 total_buffer_count = max_buffer_size;
+    s64 total_buffer_count = static_cast<s64>(max_buffer_size);
     s64 buffer_tail{};
     s64 buffer_count{};
     std::array<AtomicStorage<State>, max_buffer_size> entries{};
@@ -35,11 +34,11 @@ struct Lifo {
     }
 
     std::size_t GetPreviousEntryIndex() const {
-        return (buffer_tail + total_buffer_count - 1) % total_buffer_count;
+        return static_cast<size_t>((buffer_tail + total_buffer_count - 1) % total_buffer_count);
     }
 
     std::size_t GetNextEntryIndex() const {
-        return (buffer_tail + 1) % total_buffer_count;
+        return static_cast<size_t>((buffer_tail + 1) % total_buffer_count);
     }
 
     void WriteNextEntry(const State& new_state) {
diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp
index 2550f8cba5..a1b9b6d988 100644
--- a/src/input_common/drivers/gc_adapter.cpp
+++ b/src/input_common/drivers/gc_adapter.cpp
@@ -69,7 +69,7 @@ private:
     libusb_device_handle* handle{};
 };
 
-GCAdapter::GCAdapter(const std::string input_engine_) : InputEngine(input_engine_) {
+GCAdapter::GCAdapter(const std::string& input_engine_) : InputEngine(input_engine_) {
     if (usb_adapter_handle) {
         return;
     }
@@ -486,42 +486,30 @@ std::string GCAdapter::GetUIButtonName(const Common::ParamPackage& params) const
     switch (button) {
     case PadButton::ButtonLeft:
         return "left";
-        break;
     case PadButton::ButtonRight:
         return "right";
-        break;
     case PadButton::ButtonDown:
         return "down";
-        break;
     case PadButton::ButtonUp:
         return "up";
-        break;
     case PadButton::TriggerZ:
         return "Z";
-        break;
     case PadButton::TriggerR:
         return "R";
-        break;
     case PadButton::TriggerL:
         return "L";
-        break;
     case PadButton::ButtonA:
         return "A";
-        break;
     case PadButton::ButtonB:
         return "B";
-        break;
     case PadButton::ButtonX:
         return "X";
-        break;
     case PadButton::ButtonY:
         return "Y";
-        break;
     case PadButton::ButtonStart:
         return "start";
-        break;
     default:
-        return "Unkown GC";
+        return "Unknown GC";
     }
 }
 
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h
index fba90352e9..3e4747040f 100644
--- a/src/input_common/drivers/gc_adapter.h
+++ b/src/input_common/drivers/gc_adapter.h
@@ -24,7 +24,7 @@ class LibUSBDeviceHandle;
 
 class GCAdapter : public InputCommon::InputEngine {
 public:
-    explicit GCAdapter(const std::string input_engine_);
+    explicit GCAdapter(const std::string& input_engine_);
     ~GCAdapter();
 
     Common::Input::VibrationError SetRumble(
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
index 05fd7f9c0d..9a9a1987d5 100644
--- a/src/input_common/drivers/mouse.cpp
+++ b/src/input_common/drivers/mouse.cpp
@@ -24,7 +24,7 @@ constexpr PadIdentifier identifier = {
     .pad = 0,
 };
 
-Mouse::Mouse(const std::string input_engine_) : InputEngine(input_engine_) {
+Mouse::Mouse(const std::string& input_engine_) : InputEngine(input_engine_) {
     PreSetController(identifier);
     PreSetAxis(identifier, mouse_axis_x);
     PreSetAxis(identifier, mouse_axis_y);
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index f7e6db0b5f..11dd76e140 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -29,7 +29,7 @@ enum class MouseButton {
  */
 class Mouse final : public InputCommon::InputEngine {
 public:
-    explicit Mouse(const std::string input_engine_);
+    explicit Mouse(const std::string& input_engine_);
 
     /**
      * Signals that mouse has moved.
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index 1e3741e0f8..0b24f1858c 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -929,7 +929,7 @@ std::string SDLDriver::GetHatButtonName(u8 direction_value) const {
     }
 }
 
-u8 SDLDriver::GetHatButtonId(const std::string direction_name) const {
+u8 SDLDriver::GetHatButtonId(const std::string& direction_name) const {
     Uint8 direction;
     if (direction_name == "up") {
         direction = SDL_HAT_UP;
diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h
index b879df8abf..3faaca9842 100644
--- a/src/input_common/drivers/sdl_driver.h
+++ b/src/input_common/drivers/sdl_driver.h
@@ -56,7 +56,7 @@ public:
     std::string GetUIName(const Common::ParamPackage& params) const override;
 
     std::string GetHatButtonName(u8 direction_value) const override;
-    u8 GetHatButtonId(const std::string direction_name) const override;
+    u8 GetHatButtonId(const std::string& direction_name) const override;
 
     Common::Input::VibrationError SetRumble(
         const PadIdentifier& identifier, const Common::Input::VibrationStatus vibration) override;
diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp
index bb9c236eae..0e01fb0d96 100644
--- a/src/input_common/drivers/tas_input.cpp
+++ b/src/input_common/drivers/tas_input.cpp
@@ -47,7 +47,7 @@ constexpr std::array<std::pair<std::string_view, TasButton>, 20> text_to_tas_but
     {"KEY_ZR", TasButton::TRIGGER_ZR},
 };
 
-Tas::Tas(const std::string input_engine_) : InputCommon::InputEngine(input_engine_) {
+Tas::Tas(const std::string& input_engine_) : InputCommon::InputEngine(input_engine_) {
     for (size_t player_index = 0; player_index < PLAYER_NUMBER; player_index++) {
         PadIdentifier identifier{
             .guid = Common::UUID{},
diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h
index bfb37a638b..c95a130fcb 100644
--- a/src/input_common/drivers/tas_input.h
+++ b/src/input_common/drivers/tas_input.h
@@ -83,7 +83,7 @@ enum class TasState {
 
 class Tas final : public InputCommon::InputEngine {
 public:
-    explicit Tas(const std::string input_engine_);
+    explicit Tas(const std::string& input_engine_);
     ~Tas();
 
     /**
diff --git a/src/input_common/drivers/touch_screen.cpp b/src/input_common/drivers/touch_screen.cpp
index 377c9ee2b5..45b3086f6a 100644
--- a/src/input_common/drivers/touch_screen.cpp
+++ b/src/input_common/drivers/touch_screen.cpp
@@ -13,7 +13,7 @@ constexpr PadIdentifier identifier = {
     .pad = 0,
 };
 
-TouchScreen::TouchScreen(const std::string input_engine_) : InputEngine(input_engine_) {
+TouchScreen::TouchScreen(const std::string& input_engine_) : InputEngine(input_engine_) {
     PreSetController(identifier);
 }
 
diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h
index 0f4cd0e7ad..25c11e8bfd 100644
--- a/src/input_common/drivers/touch_screen.h
+++ b/src/input_common/drivers/touch_screen.h
@@ -14,7 +14,7 @@ namespace InputCommon {
  */
 class TouchScreen final : public InputCommon::InputEngine {
 public:
-    explicit TouchScreen(const std::string input_engine_);
+    explicit TouchScreen(const std::string& input_engine_);
 
     /**
      * Signals that mouse has moved.
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp
index 139d8d2e61..2b2105376f 100644
--- a/src/input_common/input_engine.cpp
+++ b/src/input_common/input_engine.cpp
@@ -300,8 +300,8 @@ void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int mot
     if (!configuring || !mapping_callback.on_data) {
         return;
     }
-    if (std::abs(value.gyro_x) < 1.0f && std::abs(value.gyro_y) < 1.0f &&
-        std::abs(value.gyro_z) < 1.0f) {
+    if (std::abs(value.gyro_x) < 0.6f && std::abs(value.gyro_y) < 0.6f &&
+        std::abs(value.gyro_z) < 0.6f) {
         return;
     }
     mapping_callback.on_data(MappingData{
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h
index 5430c0cf8f..c621686e54 100644
--- a/src/input_common/input_engine.h
+++ b/src/input_common/input_engine.h
@@ -166,7 +166,7 @@ public:
     };
 
     /// Retrieves the index number of the given hat button direction
-    virtual u8 GetHatButtonId([[maybe_unused]] const std::string direction_name) const {
+    virtual u8 GetHatButtonId([[maybe_unused]] const std::string& direction_name) const {
         return 0;
     };
 
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 2313a41894..7390fc5bda 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -613,56 +613,56 @@ int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) {
     }
 }
 
-int GRenderWindow::QtModifierToSwitchModdifier(quint32 qt_moddifiers) {
-    int moddifier = 0;
+int GRenderWindow::QtModifierToSwitchModifier(quint32 qt_modifiers) {
+    int modifier = 0;
     // The values are obtained through testing, Qt doesn't seem to provide a proper enum
-    if ((qt_moddifiers & 0x1) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::LeftShift;
+    if ((qt_modifiers & 0x1) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::LeftShift;
     }
-    if ((qt_moddifiers & 0x2) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::LeftControl;
+    if ((qt_modifiers & 0x2) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::LeftControl;
     }
-    if ((qt_moddifiers & 0x4) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::LeftAlt;
+    if ((qt_modifiers & 0x4) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::LeftAlt;
     }
-    if ((qt_moddifiers & 0x08) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::LeftMeta;
+    if ((qt_modifiers & 0x08) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::LeftMeta;
     }
-    if ((qt_moddifiers & 0x10) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::RightShift;
+    if ((qt_modifiers & 0x10) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::RightShift;
     }
-    if ((qt_moddifiers & 0x20) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::RightControl;
+    if ((qt_modifiers & 0x20) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::RightControl;
     }
-    if ((qt_moddifiers & 0x40) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::RightAlt;
+    if ((qt_modifiers & 0x40) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::RightAlt;
     }
-    if ((qt_moddifiers & 0x80) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::RightMeta;
+    if ((qt_modifiers & 0x80) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::RightMeta;
     }
-    if ((qt_moddifiers & 0x100) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::CapsLock;
+    if ((qt_modifiers & 0x100) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::CapsLock;
     }
-    if ((qt_moddifiers & 0x200) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::NumLock;
+    if ((qt_modifiers & 0x200) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::NumLock;
     }
     // Verify the last two keys
-    if ((qt_moddifiers & 0x400) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::Katakana;
+    if ((qt_modifiers & 0x400) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::Katakana;
     }
-    if ((qt_moddifiers & 0x800) != 0) {
-        moddifier |= 1 << Settings::NativeKeyboard::Hiragana;
+    if ((qt_modifiers & 0x800) != 0) {
+        modifier |= 1 << Settings::NativeKeyboard::Hiragana;
     }
-    return moddifier;
+    return modifier;
 }
 
 void GRenderWindow::keyPressEvent(QKeyEvent* event) {
     if (!event->isAutoRepeat()) {
-        const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers());
+        const auto modifier = QtModifierToSwitchModifier(event->nativeModifiers());
         // Replace event->key() with event->nativeVirtualKey() since the second one provides raw key
         // buttons
         const auto key = QtKeyToSwitchKey(Qt::Key(event->key()));
-        input_subsystem->GetKeyboard()->SetKeyboardModifiers(moddifier);
+        input_subsystem->GetKeyboard()->SetKeyboardModifiers(modifier);
         input_subsystem->GetKeyboard()->PressKeyboardKey(key);
         // This is used for gamepads
         input_subsystem->GetKeyboard()->PressKey(event->key());
@@ -671,9 +671,9 @@ void GRenderWindow::keyPressEvent(QKeyEvent* event) {
 
 void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
     if (!event->isAutoRepeat()) {
-        const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers());
+        const auto modifier = QtModifierToSwitchModifier(event->nativeModifiers());
         const auto key = QtKeyToSwitchKey(Qt::Key(event->key()));
-        input_subsystem->GetKeyboard()->SetKeyboardModifiers(moddifier);
+        input_subsystem->GetKeyboard()->SetKeyboardModifiers(modifier);
         input_subsystem->GetKeyboard()->ReleaseKeyboardKey(key);
         // This is used for gamepads
         input_subsystem->GetKeyboard()->ReleaseKey(event->key());
@@ -747,8 +747,8 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
 }
 
 void GRenderWindow::wheelEvent(QWheelEvent* event) {
-    const int x = event->delta();
-    const int y = 0;
+    const int x = event->angleDelta().x();
+    const int y = event->angleDelta().y();
     input_subsystem->GetMouse()->MouseWheelChange(x, y);
 }
 
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index d6b2ab5f3f..81e3c4eb02 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -162,7 +162,7 @@ public:
     static int QtKeyToSwitchKey(Qt::Key qt_keys);
 
     /// Converts a Qt modifier keys into NativeKeyboard modifier keys
-    static int QtModifierToSwitchModdifier(quint32 qt_moddifiers);
+    static int QtModifierToSwitchModifier(quint32 qt_modifiers);
 
     void keyPressEvent(QKeyEvent* event) override;
     void keyReleaseEvent(QKeyEvent* event) override;

From 922aa9410a78ef9d6fd5b5d4455375d512333239 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Fri, 19 Nov 2021 10:56:52 -0600
Subject: [PATCH 81/88] bootmanager: Use cross-platform keyboard input

---
 src/core/hid/hid_core.h  |  2 +-
 src/yuzu/bootmanager.cpp | 93 ++++++++++++++++++++++++----------------
 src/yuzu/bootmanager.h   |  2 +-
 3 files changed, 58 insertions(+), 39 deletions(-)

diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h
index 1fe2fd89be..609f40f3b9 100644
--- a/src/core/hid/hid_core.h
+++ b/src/core/hid/hid_core.h
@@ -52,7 +52,7 @@ public:
     void UnloadInputDevices();
 
     /// Number of emulated controllers
-    const std::size_t available_controllers{10};
+    static constexpr std::size_t available_controllers{10};
 
 private:
     std::unique_ptr<EmulatedController> player_1;
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 7390fc5bda..5e19f8cb13 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -613,69 +613,88 @@ int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) {
     }
 }
 
-int GRenderWindow::QtModifierToSwitchModifier(quint32 qt_modifiers) {
+int GRenderWindow::QtModifierToSwitchModifier(Qt::KeyboardModifiers qt_modifiers) {
     int modifier = 0;
-    // The values are obtained through testing, Qt doesn't seem to provide a proper enum
-    if ((qt_modifiers & 0x1) != 0) {
+
+    if ((qt_modifiers & Qt::KeyboardModifier::ShiftModifier) != 0) {
         modifier |= 1 << Settings::NativeKeyboard::LeftShift;
     }
-    if ((qt_modifiers & 0x2) != 0) {
+    if ((qt_modifiers & Qt::KeyboardModifier::ControlModifier) != 0) {
         modifier |= 1 << Settings::NativeKeyboard::LeftControl;
     }
-    if ((qt_modifiers & 0x4) != 0) {
+    if ((qt_modifiers & Qt::KeyboardModifier::AltModifier) != 0) {
         modifier |= 1 << Settings::NativeKeyboard::LeftAlt;
     }
-    if ((qt_modifiers & 0x08) != 0) {
+    if ((qt_modifiers & Qt::KeyboardModifier::MetaModifier) != 0) {
         modifier |= 1 << Settings::NativeKeyboard::LeftMeta;
     }
-    if ((qt_modifiers & 0x10) != 0) {
-        modifier |= 1 << Settings::NativeKeyboard::RightShift;
-    }
-    if ((qt_modifiers & 0x20) != 0) {
-        modifier |= 1 << Settings::NativeKeyboard::RightControl;
-    }
-    if ((qt_modifiers & 0x40) != 0) {
-        modifier |= 1 << Settings::NativeKeyboard::RightAlt;
-    }
-    if ((qt_modifiers & 0x80) != 0) {
-        modifier |= 1 << Settings::NativeKeyboard::RightMeta;
-    }
-    if ((qt_modifiers & 0x100) != 0) {
-        modifier |= 1 << Settings::NativeKeyboard::CapsLock;
-    }
-    if ((qt_modifiers & 0x200) != 0) {
-        modifier |= 1 << Settings::NativeKeyboard::NumLock;
-    }
-    // Verify the last two keys
-    if ((qt_modifiers & 0x400) != 0) {
-        modifier |= 1 << Settings::NativeKeyboard::Katakana;
-    }
-    if ((qt_modifiers & 0x800) != 0) {
-        modifier |= 1 << Settings::NativeKeyboard::Hiragana;
-    }
+
+    // TODO: These keys can't be obtained with Qt::KeyboardModifier
+
+    // if ((qt_modifiers & 0x10) != 0) {
+    //    modifier |= 1 << Settings::NativeKeyboard::RightShift;
+    // }
+    // if ((qt_modifiers & 0x20) != 0) {
+    //    modifier |= 1 << Settings::NativeKeyboard::RightControl;
+    // }
+    // if ((qt_modifiers & 0x40) != 0) {
+    //    modifier |= 1 << Settings::NativeKeyboard::RightAlt;
+    // }
+    // if ((qt_modifiers & 0x80) != 0) {
+    //    modifier |= 1 << Settings::NativeKeyboard::RightMeta;
+    // }
+    // if ((qt_modifiers & 0x100) != 0) {
+    //    modifier |= 1 << Settings::NativeKeyboard::CapsLock;
+    // }
+    // if ((qt_modifiers & 0x200) != 0) {
+    //    modifier |= 1 << Settings::NativeKeyboard::NumLock;
+    // }
+    // if ((qt_modifiers & ???) != 0) {
+    //    modifier |= 1 << Settings::NativeKeyboard::ScrollLock;
+    // }
+    // if ((qt_modifiers & ???) != 0) {
+    //    modifier |= 1 << Settings::NativeKeyboard::Katakana;
+    // }
+    // if ((qt_modifiers & ???) != 0) {
+    //    modifier |= 1 << Settings::NativeKeyboard::Hiragana;
+    // }
     return modifier;
 }
 
 void GRenderWindow::keyPressEvent(QKeyEvent* event) {
+    /**
+     * This feature can be enhanced with the following functions, but they do not provide
+     * cross-platform behavior.
+     *
+     * event->nativeVirtualKey() can distinguish between keys on the numpad.
+     * event->nativeModifiers() can distinguish between left and right keys and numlock,
+     * capslock, scroll lock.
+     */
     if (!event->isAutoRepeat()) {
-        const auto modifier = QtModifierToSwitchModifier(event->nativeModifiers());
-        // Replace event->key() with event->nativeVirtualKey() since the second one provides raw key
-        // buttons
+        const auto modifier = QtModifierToSwitchModifier(event->modifiers());
         const auto key = QtKeyToSwitchKey(Qt::Key(event->key()));
         input_subsystem->GetKeyboard()->SetKeyboardModifiers(modifier);
         input_subsystem->GetKeyboard()->PressKeyboardKey(key);
-        // This is used for gamepads
+        // This is used for gamepads that can have any key mapped
         input_subsystem->GetKeyboard()->PressKey(event->key());
     }
 }
 
 void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
+    /**
+     * This feature can be enhanced with the following functions, but they do not provide
+     * cross-platform behavior.
+     *
+     * event->nativeVirtualKey() can distinguish between keys on the numpad.
+     * event->nativeModifiers() can distinguish between left and right buttons and numlock,
+     * capslock, scroll lock.
+     */
     if (!event->isAutoRepeat()) {
-        const auto modifier = QtModifierToSwitchModifier(event->nativeModifiers());
+        const auto modifier = QtModifierToSwitchModifier(event->modifiers());
         const auto key = QtKeyToSwitchKey(Qt::Key(event->key()));
         input_subsystem->GetKeyboard()->SetKeyboardModifiers(modifier);
         input_subsystem->GetKeyboard()->ReleaseKeyboardKey(key);
-        // This is used for gamepads
+        // This is used for gamepads that can have any key mapped
         input_subsystem->GetKeyboard()->ReleaseKey(event->key());
     }
 }
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 81e3c4eb02..c8a2c59b48 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -162,7 +162,7 @@ public:
     static int QtKeyToSwitchKey(Qt::Key qt_keys);
 
     /// Converts a Qt modifier keys into NativeKeyboard modifier keys
-    static int QtModifierToSwitchModifier(quint32 qt_modifiers);
+    static int QtModifierToSwitchModifier(Qt::KeyboardModifiers qt_modifiers);
 
     void keyPressEvent(QKeyEvent* event) override;
     void keyReleaseEvent(QKeyEvent* event) override;

From c4760489a0386cdeaed68ecbed7f87532193743e Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 21 Nov 2021 12:59:51 -0600
Subject: [PATCH 82/88] input_common: Fix SDL controller with inverted axis

---
 src/input_common/drivers/sdl_driver.cpp | 23 -----------------------
 src/input_common/input_poller.cpp       |  9 ++++++++-
 2 files changed, 8 insertions(+), 24 deletions(-)

diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index 0b24f1858c..d5af6c09b4 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -220,24 +220,6 @@ public:
         return "Unknown";
     }
 
-    bool IsYAxis(u8 index) {
-        if (!sdl_controller) {
-            return false;
-        }
-
-        const auto& binding_left_y =
-            SDL_GameControllerGetBindForAxis(sdl_controller.get(), SDL_CONTROLLER_AXIS_LEFTY);
-        const auto& binding_right_y =
-            SDL_GameControllerGetBindForAxis(sdl_controller.get(), SDL_CONTROLLER_AXIS_RIGHTY);
-        if (index == binding_left_y.value.axis) {
-            return true;
-        }
-        if (index == binding_right_y.value.axis) {
-            return true;
-        }
-        return false;
-    }
-
 private:
     std::string guid;
     int port;
@@ -376,11 +358,6 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {
     case SDL_JOYAXISMOTION: {
         if (const auto joystick = GetSDLJoystickBySDLID(event.jaxis.which)) {
             const PadIdentifier identifier = joystick->GetPadIdentifier();
-            // Vertical axis is inverted on nintendo compared to SDL
-            if (joystick->IsYAxis(event.jaxis.axis)) {
-                SetAxis(identifier, event.jaxis.axis, -event.jaxis.value / 32767.0f);
-                break;
-            }
             SetAxis(identifier, event.jaxis.axis, event.jaxis.value / 32767.0f);
         }
         break;
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 92cf690cd9..7e4eafded0 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -146,7 +146,8 @@ public:
                             Common::Input::AnalogProperties properties_y_,
                             InputEngine* input_engine_)
         : identifier(identifier_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_),
-          properties_y(properties_y_), input_engine(input_engine_) {
+          properties_y(properties_y_),
+          input_engine(input_engine_), invert_axis_y{input_engine_->GetEngineName() == "sdl"} {
         UpdateCallback engine_callback{[this]() { OnChange(); }};
         const InputIdentifier x_input_identifier{
             .identifier = identifier,
@@ -181,6 +182,11 @@ public:
             .raw_value = input_engine->GetAxis(identifier, axis_y),
             .properties = properties_y,
         };
+        // This is a workaround too keep compatibility with old yuzu versions. Vertical axis is
+        // inverted on SDL compared to Nintendo
+        if (invert_axis_y) {
+            status.y.raw_value = -status.y.raw_value;
+        }
         return status;
     }
 
@@ -220,6 +226,7 @@ private:
     float last_axis_x_value;
     float last_axis_y_value;
     InputEngine* input_engine;
+    const bool invert_axis_y;
 };
 
 class InputFromTouch final : public Common::Input::InputDevice {

From 746c85b56011b87afb57e37b75953435389fc810 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 21 Nov 2021 14:12:01 -0600
Subject: [PATCH 83/88] input_common: Move button names to the frontend

---
 src/common/input.h                            | 22 +++++
 src/input_common/drivers/gc_adapter.cpp       | 36 ++++----
 src/input_common/drivers/gc_adapter.h         |  4 +-
 src/input_common/drivers/mouse.cpp            |  9 +-
 src/input_common/drivers/mouse.h              |  2 +-
 src/input_common/drivers/sdl_driver.cpp       | 15 ++--
 src/input_common/drivers/sdl_driver.h         |  2 +-
 src/input_common/input_engine.h               |  5 +-
 src/input_common/input_mapping.cpp            |  5 ++
 src/input_common/main.cpp                     | 17 ++--
 src/input_common/main.h                       |  9 +-
 .../configuration/configure_input_player.cpp  | 86 ++++++++++++++++++-
 12 files changed, 160 insertions(+), 52 deletions(-)

diff --git a/src/common/input.h b/src/common/input.h
index d997853c61..cc0cbd9b8a 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -175,6 +175,28 @@ struct LedStatus {
     bool led_4{};
 };
 
+// List of buttons to be passed to Qt that can be translated
+enum class ButtonNames {
+    Undefined,
+    Invalid,
+    // This will display the engine name instead of the button name
+    Engine,
+    // This will display the button by value instead of the button name
+    Value,
+    ButtonLeft,
+    ButtonRight,
+    ButtonDown,
+    ButtonUp,
+    TriggerZ,
+    TriggerR,
+    TriggerL,
+    ButtonA,
+    ButtonB,
+    ButtonX,
+    ButtonY,
+    ButtonStart,
+};
+
 // Callback data consisting of an input type and the equivalent data status
 struct CallbackStatus {
     InputType type{InputType::None};
diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp
index a1b9b6d988..8b65742236 100644
--- a/src/input_common/drivers/gc_adapter.cpp
+++ b/src/input_common/drivers/gc_adapter.cpp
@@ -481,47 +481,47 @@ AnalogMapping GCAdapter::GetAnalogMappingForDevice(const Common::ParamPackage& p
     return mapping;
 }
 
-std::string GCAdapter::GetUIButtonName(const Common::ParamPackage& params) const {
+Common::Input::ButtonNames GCAdapter::GetUIButtonName(const Common::ParamPackage& params) const {
     PadButton button = static_cast<PadButton>(params.Get("button", 0));
     switch (button) {
     case PadButton::ButtonLeft:
-        return "left";
+        return Common::Input::ButtonNames::ButtonLeft;
     case PadButton::ButtonRight:
-        return "right";
+        return Common::Input::ButtonNames::ButtonRight;
     case PadButton::ButtonDown:
-        return "down";
+        return Common::Input::ButtonNames::ButtonDown;
     case PadButton::ButtonUp:
-        return "up";
+        return Common::Input::ButtonNames::ButtonUp;
     case PadButton::TriggerZ:
-        return "Z";
+        return Common::Input::ButtonNames::TriggerZ;
     case PadButton::TriggerR:
-        return "R";
+        return Common::Input::ButtonNames::TriggerR;
     case PadButton::TriggerL:
-        return "L";
+        return Common::Input::ButtonNames::TriggerL;
     case PadButton::ButtonA:
-        return "A";
+        return Common::Input::ButtonNames::ButtonA;
     case PadButton::ButtonB:
-        return "B";
+        return Common::Input::ButtonNames::ButtonB;
     case PadButton::ButtonX:
-        return "X";
+        return Common::Input::ButtonNames::ButtonX;
     case PadButton::ButtonY:
-        return "Y";
+        return Common::Input::ButtonNames::ButtonY;
     case PadButton::ButtonStart:
-        return "start";
+        return Common::Input::ButtonNames::ButtonStart;
     default:
-        return "Unknown GC";
+        return Common::Input::ButtonNames::Undefined;
     }
 }
 
-std::string GCAdapter::GetUIName(const Common::ParamPackage& params) const {
+Common::Input::ButtonNames GCAdapter::GetUIName(const Common::ParamPackage& params) const {
     if (params.Has("button")) {
-        return fmt::format("Button {}", GetUIButtonName(params));
+        return GetUIButtonName(params);
     }
     if (params.Has("axis")) {
-        return fmt::format("Axis {}", params.Get("axis", 0));
+        return Common::Input::ButtonNames::Value;
     }
 
-    return "Bad GC Adapter";
+    return Common::Input::ButtonNames::Invalid;
 }
 
 } // namespace InputCommon
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h
index 3e4747040f..8dc51d2e58 100644
--- a/src/input_common/drivers/gc_adapter.h
+++ b/src/input_common/drivers/gc_adapter.h
@@ -34,7 +34,7 @@ public:
     std::vector<Common::ParamPackage> GetInputDevices() const override;
     ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override;
     AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
-    std::string GetUIName(const Common::ParamPackage& params) const override;
+    Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
 
 private:
     enum class PadButton {
@@ -112,7 +112,7 @@ private:
     /// Updates vibration state of all controllers
     void SendVibrations();
 
-    std::string GetUIButtonName(const Common::ParamPackage& params) const;
+    Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
 
     std::unique_ptr<LibUSBDeviceHandle> usb_adapter_handle;
     std::array<GCController, 4> pads;
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
index 9a9a1987d5..752118e97e 100644
--- a/src/input_common/drivers/mouse.cpp
+++ b/src/input_common/drivers/mouse.cpp
@@ -171,12 +171,15 @@ AnalogMapping Mouse::GetAnalogMappingForDevice(
     return mapping;
 }
 
-std::string Mouse::GetUIName(const Common::ParamPackage& params) const {
+Common::Input::ButtonNames Mouse::GetUIName(const Common::ParamPackage& params) const {
     if (params.Has("button")) {
-        return fmt::format("Mouse {}", params.Get("button", 0));
+        return Common::Input::ButtonNames::Value;
+    }
+    if (params.Has("axis")) {
+        return Common::Input::ButtonNames::Value;
     }
 
-    return "Bad Mouse";
+    return Common::Input::ButtonNames::Invalid;
 }
 
 } // namespace InputCommon
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index 11dd76e140..4a1fd2fd96 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -63,7 +63,7 @@ public:
 
     std::vector<Common::ParamPackage> GetInputDevices() const override;
     AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
-    std::string GetUIName(const Common::ParamPackage& params) const override;
+    Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
 
 private:
     void UpdateThread(std::stop_token stop_token);
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index d5af6c09b4..90128b6cf6 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -869,26 +869,25 @@ MotionMapping SDLDriver::GetMotionMappingForDevice(const Common::ParamPackage& p
     return mapping;
 }
 
-std::string SDLDriver::GetUIName(const Common::ParamPackage& params) const {
+Common::Input::ButtonNames SDLDriver::GetUIName(const Common::ParamPackage& params) const {
     if (params.Has("button")) {
         // TODO(German77): Find how to substitue the values for real button names
-        return fmt::format("Button {}", params.Get("button", 0));
+        return Common::Input::ButtonNames::Value;
     }
     if (params.Has("hat")) {
-        return fmt::format("Hat {}", params.Get("direction", ""));
+        return Common::Input::ButtonNames::Value;
     }
     if (params.Has("axis")) {
-        return fmt::format("Axis {}", params.Get("axis", ""));
+        return Common::Input::ButtonNames::Value;
     }
     if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) {
-        return fmt::format("Axis {},{},{}", params.Get("axis_x", ""), params.Get("axis_y", ""),
-                           params.Get("axis_z", ""));
+        return Common::Input::ButtonNames::Value;
     }
     if (params.Has("motion")) {
-        return "SDL motion";
+        return Common::Input::ButtonNames::Engine;
     }
 
-    return "Bad SDL";
+    return Common::Input::ButtonNames::Invalid;
 }
 
 std::string SDLDriver::GetHatButtonName(u8 direction_value) const {
diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h
index 3faaca9842..d03ff4b84f 100644
--- a/src/input_common/drivers/sdl_driver.h
+++ b/src/input_common/drivers/sdl_driver.h
@@ -53,7 +53,7 @@ public:
     ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override;
     AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
     MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override;
-    std::string GetUIName(const Common::ParamPackage& params) const override;
+    Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
 
     std::string GetHatButtonName(u8 direction_value) const override;
     u8 GetHatButtonId(const std::string& direction_name) const override;
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h
index c621686e54..02272b3f87 100644
--- a/src/input_common/input_engine.h
+++ b/src/input_common/input_engine.h
@@ -161,8 +161,9 @@ public:
     };
 
     /// Retrieves the name of the given input.
-    virtual std::string GetUIName([[maybe_unused]] const Common::ParamPackage& params) const {
-        return GetEngineName();
+    virtual Common::Input::ButtonNames GetUIName(
+        [[maybe_unused]] const Common::ParamPackage& params) const {
+        return Common::Input::ButtonNames::Engine;
     };
 
     /// Retrieves the index number of the given hat button direction
diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp
index 0eeeff3725..c5218f2cb7 100644
--- a/src/input_common/input_mapping.cpp
+++ b/src/input_common/input_mapping.cpp
@@ -61,6 +61,7 @@ void MappingFactory::RegisterButton(const MappingData& data) {
     }
     new_input.Set("port", static_cast<int>(data.pad.port));
     new_input.Set("pad", static_cast<int>(data.pad.pad));
+
     switch (data.type) {
     case EngineInputType::Button:
         // Workaround for old compatibility
@@ -75,6 +76,10 @@ void MappingFactory::RegisterButton(const MappingData& data) {
         new_input.Set("direction", data.hat_name);
         break;
     case EngineInputType::Analog:
+        // Ignore mouse axis when mapping buttons
+        if (data.engine == "mouse") {
+            return;
+        }
         new_input.Set("axis", data.index);
         new_input.Set("threshold", 0.5f);
         break;
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index df36a337c7..39e4935dc1 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -205,9 +205,9 @@ struct InputSubsystem::Impl {
         return {};
     }
 
-    std::string GetButtonName(const Common::ParamPackage& params) const {
+    Common::Input::ButtonNames GetButtonName(const Common::ParamPackage& params) const {
         if (!params.Has("engine") || params.Get("engine", "") == "any") {
-            return "Unknown";
+            return Common::Input::ButtonNames::Undefined;
         }
         const std::string engine = params.Get("engine", "");
         if (engine == mouse->GetEngineName()) {
@@ -227,7 +227,7 @@ struct InputSubsystem::Impl {
             return sdl->GetUIName(params);
         }
 #endif
-        return "Bad engine";
+        return Common::Input::ButtonNames::Invalid;
     }
 
     bool IsController(const Common::ParamPackage& params) {
@@ -361,15 +361,8 @@ MotionMapping InputSubsystem::GetMotionMappingForDevice(const Common::ParamPacka
     return impl->GetMotionMappingForDevice(device);
 }
 
-std::string InputSubsystem::GetButtonName(const Common::ParamPackage& params) const {
-    const std::string toggle = params.Get("toggle", false) ? "~" : "";
-    const std::string inverted = params.Get("inverted", false) ? "!" : "";
-    const std::string button_name = impl->GetButtonName(params);
-    std::string axis_direction = "";
-    if (params.Has("axis")) {
-        axis_direction = params.Get("invert", "+");
-    }
-    return fmt::format("{}{}{}{}", toggle, inverted, button_name, axis_direction);
+Common::Input::ButtonNames InputSubsystem::GetButtonName(const Common::ParamPackage& params) const {
+    return impl->GetButtonName(params);
 }
 
 bool InputSubsystem::IsController(const Common::ParamPackage& params) const {
diff --git a/src/input_common/main.h b/src/input_common/main.h
index a4a24d076e..c6f97f6918 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -13,6 +13,10 @@ namespace Common {
 class ParamPackage;
 }
 
+namespace Common::Input {
+enum class ButtonNames;
+}
+
 namespace Settings::NativeAnalog {
 enum Values : int;
 }
@@ -108,8 +112,9 @@ public:
     /// Retrieves the motion mappings for the given device.
     [[nodiscard]] MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& device) const;
 
-    /// Returns a string contaning the name of the button from the input engine.
-    [[nodiscard]] std::string GetButtonName(const Common::ParamPackage& params) const;
+    /// Returns an enum contaning the name to be displayed from the input engine.
+    [[nodiscard]] Common::Input::ButtonNames GetButtonName(
+        const Common::ParamPackage& params) const;
 
     /// Returns true if device is a controller.
     [[nodiscard]] bool IsController(const Common::ParamPackage& params) const;
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 0254ea6fe1..6219a09a84 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -52,6 +52,37 @@ QString GetKeyName(int key_code) {
     }
 }
 
+QString GetButtonName(Common::Input::ButtonNames button_name) {
+    switch (button_name) {
+    case Common::Input::ButtonNames::ButtonLeft:
+        return QObject::tr("Left");
+    case Common::Input::ButtonNames::ButtonRight:
+        return QObject::tr("Right");
+    case Common::Input::ButtonNames::ButtonDown:
+        return QObject::tr("Down");
+    case Common::Input::ButtonNames::ButtonUp:
+        return QObject::tr("Up");
+    case Common::Input::ButtonNames::TriggerZ:
+        return QObject::tr("Z");
+    case Common::Input::ButtonNames::TriggerR:
+        return QObject::tr("R");
+    case Common::Input::ButtonNames::TriggerL:
+        return QObject::tr("L");
+    case Common::Input::ButtonNames::ButtonA:
+        return QObject::tr("A");
+    case Common::Input::ButtonNames::ButtonB:
+        return QObject::tr("B");
+    case Common::Input::ButtonNames::ButtonX:
+        return QObject::tr("X");
+    case Common::Input::ButtonNames::ButtonY:
+        return QObject::tr("Y");
+    case Common::Input::ButtonNames::ButtonStart:
+        return QObject::tr("Start");
+    default:
+        return QObject::tr("[undefined]");
+    }
+}
+
 void SetAnalogParam(const Common::ParamPackage& input_param, Common::ParamPackage& analog_param,
                     const std::string& button_name) {
     // The poller returned a complete axis, so set all the buttons
@@ -75,15 +106,64 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
         return QObject::tr("[not set]");
     }
 
+    const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
+    const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : "");
+    const auto common_button_name = input_subsystem->GetButtonName(param);
+
     // Retrieve the names from Qt
     if (param.Get("engine", "") == "keyboard") {
         const QString button_str = GetKeyName(param.Get("code", 0));
-        const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
         return QObject::tr("%1%2").arg(toggle, button_str);
     }
 
-    std::string button_name = input_subsystem->GetButtonName(param);
-    return QString::fromStdString(button_name);
+    if (common_button_name == Common::Input::ButtonNames::Invalid) {
+        return QObject::tr("[invalid]");
+    }
+
+    if (common_button_name == Common::Input::ButtonNames::Engine) {
+        return QString::fromStdString(param.Get("engine", ""));
+    }
+
+    if (common_button_name == Common::Input::ButtonNames::Value) {
+        if (param.Has("hat")) {
+            const QString hat = QString::fromStdString(param.Get("direction", ""));
+            return QObject::tr("%1%2Hat %3").arg(toggle, inverted, hat);
+        }
+        if (param.Has("axis")) {
+            const QString axis = QString::fromStdString(param.Get("axis", ""));
+            return QObject::tr("%1%2Axis %3").arg(toggle, inverted, axis);
+        }
+        if (param.Has("axis_x") && param.Has("axis_y") && param.Has("axis_z")) {
+            const QString axis_x = QString::fromStdString(param.Get("axis_x", ""));
+            const QString axis_y = QString::fromStdString(param.Get("axis_y", ""));
+            const QString axis_z = QString::fromStdString(param.Get("axis_z", ""));
+            return QObject::tr("%1%2Axis %3,%4,%5").arg(toggle, inverted, axis_x, axis_y, axis_z);
+        }
+        if (param.Has("motion")) {
+            const QString motion = QString::fromStdString(param.Get("motion", ""));
+            return QObject::tr("%1%2Motion %3").arg(toggle, inverted, motion);
+        }
+        if (param.Has("button")) {
+            const QString button = QString::fromStdString(param.Get("button", ""));
+            return QObject::tr("%1%2Button %3").arg(toggle, inverted, button);
+        }
+    }
+
+    QString button_name = GetButtonName(common_button_name);
+    if (param.Has("hat")) {
+        return QObject::tr("%1%2Hat %3").arg(toggle, inverted, button_name);
+    }
+    if (param.Has("axis")) {
+        return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name);
+    }
+    if (param.Has("motion")) {
+        return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name);
+    }
+    if (param.Has("button")) {
+        return QObject::tr("%1%2Button %3").arg(toggle, inverted, button_name);
+    }
+
+    return QObject::tr("[unknown]");
 }
 
 QString ConfigureInputPlayer::AnalogToText(const Common::ParamPackage& param,

From e64ee99f00c6d2d884113f79785d4aec9fc05db8 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sun, 21 Nov 2021 22:37:50 -0600
Subject: [PATCH 84/88] yuzu: Fix TAS from rebase

---
 src/yuzu/bootmanager.cpp |  3 ++-
 src/yuzu/bootmanager.h   | 10 +++++-----
 src/yuzu/main.cpp        |  7 ++++---
 3 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 5e19f8cb13..114f17c06b 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -320,7 +320,8 @@ GRenderWindow::~GRenderWindow() {
 
 void GRenderWindow::OnFrameDisplayed() {
     input_subsystem->GetTas()->UpdateThread();
-    const TasInput::TasState new_tas_state = std::get<0>(input_subsystem->GetTas()->GetStatus());
+    const InputCommon::TasInput::TasState new_tas_state =
+        std::get<0>(input_subsystem->GetTas()->GetStatus());
 
     if (!first_frame) {
         last_tas_state = new_tas_state;
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index c8a2c59b48..92297a43b3 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -33,15 +33,15 @@ class InputSubsystem;
 enum class MouseButton;
 } // namespace InputCommon
 
+namespace InputCommon::TasInput {
+enum class TasState;
+} // namespace InputCommon::TasInput
+
 namespace VideoCore {
 enum class LoadCallbackStage;
 class RendererBase;
 } // namespace VideoCore
 
-namespace TasInput {
-enum class TasState;
-}
-
 class EmuThread final : public QThread {
     Q_OBJECT
 
@@ -245,7 +245,7 @@ private:
     QWidget* child_widget = nullptr;
 
     bool first_frame = false;
-    TasInput::TasState last_tas_state;
+    InputCommon::TasInput::TasState last_tas_state;
 
     std::array<std::size_t, 16> touch_ids{};
 
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index cd8ea221d7..09ea21f5e5 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2992,9 +2992,10 @@ void GMainWindow::OnTasStateChanged() {
     bool is_running = false;
     bool is_recording = false;
     if (emulation_running) {
-        const TasInput::TasState tas_status = std::get<0>(input_subsystem->GetTas()->GetStatus());
-        is_running = tas_status == TasInput::TasState::Running;
-        is_recording = tas_status == TasInput::TasState::Recording;
+        const InputCommon::TasInput::TasState tas_status =
+            std::get<0>(input_subsystem->GetTas()->GetStatus());
+        is_running = tas_status == InputCommon::TasInput::TasState::Running;
+        is_recording = tas_status == InputCommon::TasInput::TasState::Recording;
     }
 
     ui->action_TAS_Start->setText(is_running ? tr("&Stop Running") : tr("&Start"));

From 23bf2e3bb6fe0881e28767e768ad9c0a9f851d57 Mon Sep 17 00:00:00 2001
From: Narr the Reg <juangerman-13@hotmail.com>
Date: Mon, 22 Nov 2021 22:15:34 -0600
Subject: [PATCH 85/88] service/hid: Finish converting LIFO objects and address
 some nits

---
 src/core/hid/emulated_controller.cpp          |  2 +-
 src/core/hid/hid_types.h                      |  6 +-
 .../hid/controllers/console_sixaxis.cpp       | 31 ++++------
 .../service/hid/controllers/console_sixaxis.h | 31 ++--------
 .../service/hid/controllers/controller_base.h |  2 +
 .../hle/service/hid/controllers/debug_pad.h   |  2 +-
 .../hle/service/hid/controllers/gesture.h     |  2 +-
 .../hle/service/hid/controllers/keyboard.h    |  2 +-
 src/core/hle/service/hid/controllers/mouse.h  |  2 +-
 src/core/hle/service/hid/controllers/npad.cpp |  2 +
 src/core/hle/service/hid/controllers/npad.h   | 56 ++++++-------------
 .../hle/service/hid/controllers/touchscreen.h |  2 +-
 src/core/hle/service/hid/controllers/xpad.h   |  2 +-
 src/core/hle/service/hid/ring_lifo.h          |  3 +-
 14 files changed, 50 insertions(+), 95 deletions(-)

diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 54c1a23243..54d4ed93d7 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -723,7 +723,7 @@ void EmulatedController::SetBattery(Common::Input::CallbackStatus callback, std:
 
     bool is_charging = false;
     bool is_powered = false;
-    BatteryLevel battery_level = 0;
+    NpadBatteryLevel battery_level = 0;
     switch (controller.battery_values[index]) {
     case Common::Input::BatteryLevel::Charging:
         is_charging = true;
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 3cbe162603..acf54e233a 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -346,15 +346,15 @@ struct NpadGcTriggerState {
 static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
 
 // This is nn::hid::system::NpadBatteryLevel
-using BatteryLevel = u32;
-static_assert(sizeof(BatteryLevel) == 0x4, "BatteryLevel is an invalid size");
+using NpadBatteryLevel = u32;
+static_assert(sizeof(NpadBatteryLevel) == 0x4, "NpadBatteryLevel is an invalid size");
 
 // This is nn::hid::system::NpadPowerInfo
 struct NpadPowerInfo {
     bool is_powered;
     bool is_charging;
     INSERT_PADDING_BYTES(0x6);
-    BatteryLevel battery_level;
+    NpadBatteryLevel battery_level;
 };
 static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
 
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
index ea7e8f18fd..f0f3105dc5 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
@@ -24,34 +24,25 @@ void Controller_ConsoleSixAxis::OnRelease() {}
 
 void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                                          std::size_t size) {
-    seven_six_axis.header.timestamp = core_timing.GetCPUTicks();
-    seven_six_axis.header.total_entry_count = 17;
-
     if (!IsControllerActivated() || !is_transfer_memory_set) {
-        seven_six_axis.header.entry_count = 0;
-        seven_six_axis.header.last_entry_index = 0;
+        seven_sixaxis_lifo.buffer_count = 0;
+        seven_sixaxis_lifo.buffer_tail = 0;
         return;
     }
-    seven_six_axis.header.entry_count = 16;
 
-    const auto& last_entry =
-        seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index];
-    seven_six_axis.header.last_entry_index = (seven_six_axis.header.last_entry_index + 1) % 17;
-    auto& cur_entry = seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index];
-
-    cur_entry.sampling_number = last_entry.sampling_number + 1;
-    cur_entry.sampling_number2 = cur_entry.sampling_number;
+    const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state;
+    next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1;
 
     // Try to read sixaxis sensor states
     const auto motion_status = console->GetMotion();
 
     console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
 
-    cur_entry.accel = motion_status.accel;
+    next_seven_sixaxis_state.accel = motion_status.accel;
     // Zero gyro values as they just mess up with the camera
     // Note: Probably a correct sensivity setting must be set
-    cur_entry.gyro = {};
-    cur_entry.quaternion = {
+    next_seven_sixaxis_state.gyro = {};
+    next_seven_sixaxis_state.quaternion = {
         {
             motion_status.quaternion.xyz.y,
             motion_status.quaternion.xyz.x,
@@ -68,7 +59,8 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
     // Update console six axis shared memory
     std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis));
     // Update seven six axis transfer memory
-    std::memcpy(transfer_memory, &seven_six_axis, sizeof(seven_six_axis));
+    seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
+    std::memcpy(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo));
 }
 
 void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) {
@@ -77,8 +69,7 @@ void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) {
 }
 
 void Controller_ConsoleSixAxis::ResetTimestamp() {
-    auto& cur_entry = seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index];
-    cur_entry.sampling_number = 0;
-    cur_entry.sampling_number2 = 0;
+    seven_sixaxis_lifo.buffer_count = 0;
+    seven_sixaxis_lifo.buffer_tail = 0;
 }
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h
index 7c92413e8d..2792418588 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.h
@@ -10,6 +10,7 @@
 #include "common/quaternion.h"
 #include "core/hid/hid_types.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/hid/ring_lifo.h"
 
 namespace Core::HID {
 class EmulatedConsole;
@@ -40,50 +41,30 @@ private:
     struct SevenSixAxisState {
         INSERT_PADDING_WORDS(4); // unused
         s64 sampling_number{};
-        s64 sampling_number2{};
         u64 unknown{};
         Common::Vec3f accel{};
         Common::Vec3f gyro{};
         Common::Quaternion<f32> quaternion{};
     };
-    static_assert(sizeof(SevenSixAxisState) == 0x50, "SevenSixAxisState is an invalid size");
-
-    struct CommonHeader {
-        s64 timestamp;
-        s64 total_entry_count;
-        s64 last_entry_index;
-        s64 entry_count;
-    };
-    static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
-
-    // TODO(german77): SevenSixAxisMemory doesn't follow the standard lifo. Investigate
-    struct SevenSixAxisMemory {
-        CommonHeader header{};
-        std::array<SevenSixAxisState, 0x21> sevensixaxis_states{};
-    };
-    static_assert(sizeof(SevenSixAxisMemory) == 0xA70, "SevenSixAxisMemory is an invalid size");
+    static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size");
 
     // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
     struct ConsoleSharedMemory {
         u64 sampling_number{};
         bool is_seven_six_axis_sensor_at_rest{};
+        INSERT_PADDING_BYTES(4); // padding
         f32 verticalization_error{};
         Common::Vec3f gyro_bias{};
     };
     static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
 
-    struct MotionDevice {
-        Common::Vec3f accel;
-        Common::Vec3f gyro;
-        Common::Vec3f rotation;
-        std::array<Common::Vec3f, 3> orientation;
-        Common::Quaternion<f32> quaternion;
-    };
+    Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{};
+    static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size");
 
     Core::HID::EmulatedConsole* console;
     u8* transfer_memory = nullptr;
     bool is_transfer_memory_set = false;
     ConsoleSharedMemory console_six_axis{};
-    SevenSixAxisMemory seven_six_axis{};
+    SevenSixAxisState next_seven_sixaxis_state{};
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h
index 8125bbc842..7450eb20a7 100644
--- a/src/core/hle/service/hid/controllers/controller_base.h
+++ b/src/core/hle/service/hid/controllers/controller_base.h
@@ -41,6 +41,8 @@ public:
 
     bool IsControllerActivated() const;
 
+    static const std::size_t hid_entry_count = 17;
+
 protected:
     bool is_activated{false};
 
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 15b3afb7a3..afe374fc26 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -54,7 +54,7 @@ private:
     static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
 
     // This is nn::hid::detail::DebugPadLifo
-    Lifo<DebugPadState> debug_pad_lifo{};
+    Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{};
     static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
     DebugPadState next_state{};
 
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index f924464e0d..0936a3fa37 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -136,7 +136,7 @@ private:
     GestureProperties GetGestureProperties();
 
     // This is nn::hid::detail::GestureLifo
-    Lifo<GestureState> gesture_lifo{};
+    Lifo<GestureState, hid_entry_count> gesture_lifo{};
     static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
     GestureState next_state{};
 
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index 0d61cb4709..cf62d38961 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -44,7 +44,7 @@ private:
     static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
 
     // This is nn::hid::detail::KeyboardLifo
-    Lifo<KeyboardState> keyboard_lifo{};
+    Lifo<KeyboardState, hid_entry_count> keyboard_lifo{};
     static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
     KeyboardState next_state{};
 
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 1ac69aa6ff..7559fc78d2 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -34,7 +34,7 @@ public:
 
 private:
     // This is nn::hid::detail::MouseLifo
-    Lifo<Core::HID::MouseState> mouse_lifo{};
+    Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{};
     static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
     Core::HID::MouseState next_state{};
 
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 4b23230e1c..dd4d954aac 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -157,6 +157,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
         shared_memory.system_properties.is_vertical.Assign(1);
         shared_memory.system_properties.use_plus.Assign(1);
         shared_memory.system_properties.use_minus.Assign(1);
+        shared_memory.system_properties.use_directional_buttons.Assign(1);
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
         shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
         break;
@@ -167,6 +168,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
         shared_memory.system_properties.is_vertical.Assign(1);
         shared_memory.system_properties.use_plus.Assign(1);
         shared_memory.system_properties.use_minus.Assign(1);
+        shared_memory.system_properties.use_directional_buttons.Assign(1);
         shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
         shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
         break;
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 3798c037fa..9fa113bb6b 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -339,26 +339,6 @@ private:
     static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
                   "NfcXcdDeviceHandleStateImpl is an invalid size");
 
-    // nn::hid::detail::NfcXcdDeviceHandleStateImplAtomicStorage
-    struct NfcXcdDeviceHandleStateImplAtomicStorage {
-        u64 sampling_number;
-        NfcXcdDeviceHandleStateImpl nfc_xcd_device_handle_state;
-    };
-    static_assert(sizeof(NfcXcdDeviceHandleStateImplAtomicStorage) == 0x20,
-                  "NfcXcdDeviceHandleStateImplAtomicStorage is an invalid size");
-
-    // This is nn::hid::detail::NfcXcdDeviceHandleState
-    struct NfcXcdDeviceHandleState {
-        // TODO(german77): Make this struct a ring lifo object
-        INSERT_PADDING_BYTES(0x8); // Unused
-        s64 total_buffer_count = max_buffer_size;
-        s64 buffer_tail{};
-        s64 buffer_count{};
-        std::array<NfcXcdDeviceHandleStateImplAtomicStorage, 2> nfc_xcd_device_handle_storage;
-    };
-    static_assert(sizeof(NfcXcdDeviceHandleState) == 0x60,
-                  "NfcXcdDeviceHandleState is an invalid size");
-
     // This is nn::hid::system::AppletFooterUiAttributesSet
     struct AppletFooterUiAttributes {
         INSERT_PADDING_BYTES(0x4);
@@ -433,32 +413,32 @@ private:
         NpadJoyAssignmentMode assignment_mode;
         NpadFullKeyColorState fullkey_color;
         NpadJoyColorState joycon_color;
-        Lifo<NPadGenericState> fullkey_lifo;
-        Lifo<NPadGenericState> handheld_lifo;
-        Lifo<NPadGenericState> joy_dual_lifo;
-        Lifo<NPadGenericState> joy_left_lifo;
-        Lifo<NPadGenericState> joy_right_lifo;
-        Lifo<NPadGenericState> palma_lifo;
-        Lifo<NPadGenericState> system_ext_lifo;
-        Lifo<SixAxisSensorState> sixaxis_fullkey_lifo;
-        Lifo<SixAxisSensorState> sixaxis_handheld_lifo;
-        Lifo<SixAxisSensorState> sixaxis_dual_left_lifo;
-        Lifo<SixAxisSensorState> sixaxis_dual_right_lifo;
-        Lifo<SixAxisSensorState> sixaxis_left_lifo;
-        Lifo<SixAxisSensorState> sixaxis_right_lifo;
+        Lifo<NPadGenericState, hid_entry_count> fullkey_lifo;
+        Lifo<NPadGenericState, hid_entry_count> handheld_lifo;
+        Lifo<NPadGenericState, hid_entry_count> joy_dual_lifo;
+        Lifo<NPadGenericState, hid_entry_count> joy_left_lifo;
+        Lifo<NPadGenericState, hid_entry_count> joy_right_lifo;
+        Lifo<NPadGenericState, hid_entry_count> palma_lifo;
+        Lifo<NPadGenericState, hid_entry_count> system_ext_lifo;
+        Lifo<SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo;
+        Lifo<SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo;
+        Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo;
+        Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo;
+        Lifo<SixAxisSensorState, hid_entry_count> sixaxis_left_lifo;
+        Lifo<SixAxisSensorState, hid_entry_count> sixaxis_right_lifo;
         DeviceType device_type;
         INSERT_PADDING_BYTES(0x4); // Reserved
         NPadSystemProperties system_properties;
         NpadSystemButtonProperties button_properties;
-        Core::HID::BatteryLevel battery_level_dual;
-        Core::HID::BatteryLevel battery_level_left;
-        Core::HID::BatteryLevel battery_level_right;
+        Core::HID::NpadBatteryLevel battery_level_dual;
+        Core::HID::NpadBatteryLevel battery_level_left;
+        Core::HID::NpadBatteryLevel battery_level_right;
         union {
-            NfcXcdDeviceHandleState nfc_xcd_device_handle;
+            Lifo<NfcXcdDeviceHandleStateImpl, 0x2> nfc_xcd_device_lifo{};
             AppletFooterUi applet_footer;
         };
         INSERT_PADDING_BYTES(0x20); // Unknown
-        Lifo<NpadGcTriggerState> gc_trigger_lifo;
+        Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo;
         NpadLarkType lark_type_l_and_main;
         NpadLarkType lark_type_r;
         NpadLuciaType lucia_type;
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index 135c2bf138..708dde4f08 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -61,7 +61,7 @@ private:
     static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
 
     // This is nn::hid::detail::TouchScreenLifo
-    Lifo<TouchScreenState> touch_screen_lifo{};
+    Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{};
     static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
     TouchScreenState next_state{};
 
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index 54dae0be1b..ba8db8d9d8 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -102,7 +102,7 @@ private:
     static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size");
 
     // This is nn::hid::detail::BasicXpadLifo
-    Lifo<BasicXpadState> basic_xpad_lifo{};
+    Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{};
     static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size");
     BasicXpadState next_state{};
 };
diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h
index f0e0bab7fe..44c20d9673 100644
--- a/src/core/hle/service/hid/ring_lifo.h
+++ b/src/core/hle/service/hid/ring_lifo.h
@@ -9,7 +9,6 @@
 #include "common/common_types.h"
 
 namespace Service::HID {
-constexpr std::size_t max_buffer_size = 17;
 
 template <typename State>
 struct AtomicStorage {
@@ -17,7 +16,7 @@ struct AtomicStorage {
     State state;
 };
 
-template <typename State>
+template <typename State, std::size_t max_buffer_size>
 struct Lifo {
     s64 timestamp{};
     s64 total_buffer_count = static_cast<s64>(max_buffer_size);

From 639402850ac65c694967ef6519becb65abe89b39 Mon Sep 17 00:00:00 2001
From: Narr the Reg <juangerman-13@hotmail.com>
Date: Fri, 26 Nov 2021 15:45:37 -0600
Subject: [PATCH 86/88] input_common: Fully implement UDP controllers

---
 src/common/input.h                            |  14 ++
 src/common/settings.h                         |   1 +
 src/core/hid/emulated_console.cpp             |   6 +-
 src/input_common/drivers/udp_client.cpp       | 206 +++++++++++++++++-
 src/input_common/drivers/udp_client.h         |  56 +++++
 src/input_common/helpers/udp_protocol.h       |  75 +++++--
 src/input_common/input_mapping.cpp            |   6 +
 src/input_common/main.cpp                     |  26 ++-
 src/yuzu/configuration/config.cpp             |   2 +
 .../configure_input_advanced.cpp              |   2 +
 .../configuration/configure_input_advanced.ui |  19 +-
 .../configuration/configure_input_player.cpp  |  24 ++
 12 files changed, 397 insertions(+), 40 deletions(-)

diff --git a/src/common/input.h b/src/common/input.h
index cc0cbd9b8a..eaee0bdeaf 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -195,6 +195,20 @@ enum class ButtonNames {
     ButtonX,
     ButtonY,
     ButtonStart,
+
+    // DS4 button names
+    L1,
+    L2,
+    L3,
+    R1,
+    R2,
+    R3,
+    Circle,
+    Cross,
+    Square,
+    Triangle,
+    Share,
+    Options,
 };
 
 // Callback data consisting of an input type and the equivalent data status
diff --git a/src/common/settings.h b/src/common/settings.h
index d7410fa9b2..e4e049f670 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -560,6 +560,7 @@ struct Values {
 
     Setting<bool> motion_enabled{true, "motion_enabled"};
     BasicSetting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"};
+    BasicSetting<bool> enable_udp_controller{false, "enable_udp_controller"};
 
     BasicSetting<bool> pause_tas_on_load{true, "pause_tas_on_load"};
     BasicSetting<bool> tas_enable{false, "tas_enable"};
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index b224932dc5..80db8e9c6d 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -30,8 +30,10 @@ void EmulatedConsole::SetTouchParams() {
     }
     touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"};
     touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"};
-    touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:0,axis_y:1,button:0"};
-    touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:2,axis_y:3,button:1"};
+    touch_params[index++] =
+        Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"};
+    touch_params[index++] =
+        Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"};
 
     const auto button_index =
         static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp
index 7cab707da5..fdee0f2d53 100644
--- a/src/input_common/drivers/udp_client.cpp
+++ b/src/input_common/drivers/udp_client.cpp
@@ -103,7 +103,7 @@ private:
 
         // Send a request for getting pad data for the pad
         const Request::PadData pad_data{
-            Request::PadData::Flags::AllPorts,
+            Request::RegisterFlags::AllPads,
             0,
             EMPTY_MAC_ADDRESS,
         };
@@ -247,7 +247,12 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
 
     for (std::size_t id = 0; id < data.touch.size(); ++id) {
         const auto touch_pad = data.touch[id];
-        const int touch_id = static_cast<int>(client * 2 + id);
+        const auto touch_axis_x_id =
+            static_cast<int>(id == 0 ? PadAxes::Touch1X : PadAxes::Touch2X);
+        const auto touch_axis_y_id =
+            static_cast<int>(id == 0 ? PadAxes::Touch1Y : PadAxes::Touch2Y);
+        const auto touch_button_id =
+            static_cast<int>(id == 0 ? PadButton::Touch1 : PadButton::touch2);
 
         // TODO: Use custom calibration per device
         const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue());
@@ -264,14 +269,35 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
             static_cast<f32>(max_y - min_y);
 
         if (touch_pad.is_active) {
-            SetAxis(identifier, touch_id * 2, x);
-            SetAxis(identifier, touch_id * 2 + 1, y);
-            SetButton(identifier, touch_id, true);
+            SetAxis(identifier, touch_axis_x_id, x);
+            SetAxis(identifier, touch_axis_y_id, y);
+            SetButton(identifier, touch_button_id, true);
             continue;
         }
-        SetAxis(identifier, touch_id * 2, 0);
-        SetAxis(identifier, touch_id * 2 + 1, 0);
-        SetButton(identifier, touch_id, false);
+        SetAxis(identifier, touch_axis_x_id, 0);
+        SetAxis(identifier, touch_axis_y_id, 0);
+        SetButton(identifier, touch_button_id, false);
+    }
+
+    SetAxis(identifier, static_cast<int>(PadAxes::LeftStickX),
+            (data.left_stick_x - 127.0f) / 127.0f);
+    SetAxis(identifier, static_cast<int>(PadAxes::LeftStickY),
+            (data.left_stick_y - 127.0f) / 127.0f);
+    SetAxis(identifier, static_cast<int>(PadAxes::RightStickX),
+            (data.right_stick_x - 127.0f) / 127.0f);
+    SetAxis(identifier, static_cast<int>(PadAxes::RightStickY),
+            (data.right_stick_y - 127.0f) / 127.0f);
+
+    static constexpr std::array<PadButton, 16> buttons{
+        PadButton::Share,    PadButton::L3,     PadButton::R3,    PadButton::Options,
+        PadButton::Up,       PadButton::Right,  PadButton::Down,  PadButton::Left,
+        PadButton::L2,       PadButton::R2,     PadButton::L1,    PadButton::R1,
+        PadButton::Triangle, PadButton::Circle, PadButton::Cross, PadButton::Square};
+
+    for (std::size_t i = 0; i < buttons.size(); ++i) {
+        const bool button_status = (data.digital_button & (1U << i)) != 0;
+        const int button = static_cast<int>(buttons[i]);
+        SetButton(identifier, button, button_status);
     }
 }
 
@@ -317,6 +343,170 @@ void UDPClient::Reset() {
     }
 }
 
+std::vector<Common::ParamPackage> UDPClient::GetInputDevices() const {
+    std::vector<Common::ParamPackage> devices;
+    if (!Settings::values.enable_udp_controller) {
+        return devices;
+    }
+    for (std::size_t client = 0; client < clients.size(); client++) {
+        if (clients[client].active != 1) {
+            continue;
+        }
+        for (std::size_t index = 0; index < PADS_PER_CLIENT; ++index) {
+            const std::size_t pad_index = client * PADS_PER_CLIENT + index;
+            if (!pads[pad_index].connected) {
+                continue;
+            }
+            const auto pad_identifier = GetPadIdentifier(pad_index);
+            Common::ParamPackage identifier{};
+            identifier.Set("engine", GetEngineName());
+            identifier.Set("display", fmt::format("UDP Controller {}", pad_identifier.pad));
+            identifier.Set("guid", pad_identifier.guid.Format());
+            identifier.Set("port", static_cast<int>(pad_identifier.port));
+            identifier.Set("pad", static_cast<int>(pad_identifier.pad));
+            devices.emplace_back(identifier);
+        }
+    }
+    return devices;
+}
+
+ButtonMapping UDPClient::GetButtonMappingForDevice(const Common::ParamPackage& params) {
+    // This list excludes any button that can't be really mapped
+    static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 18>
+        switch_to_dsu_button = {
+            std::pair{Settings::NativeButton::A, PadButton::Circle},
+            {Settings::NativeButton::B, PadButton::Cross},
+            {Settings::NativeButton::X, PadButton::Triangle},
+            {Settings::NativeButton::Y, PadButton::Square},
+            {Settings::NativeButton::Plus, PadButton::Options},
+            {Settings::NativeButton::Minus, PadButton::Share},
+            {Settings::NativeButton::DLeft, PadButton::Left},
+            {Settings::NativeButton::DUp, PadButton::Up},
+            {Settings::NativeButton::DRight, PadButton::Right},
+            {Settings::NativeButton::DDown, PadButton::Down},
+            {Settings::NativeButton::L, PadButton::L1},
+            {Settings::NativeButton::R, PadButton::R1},
+            {Settings::NativeButton::ZL, PadButton::L2},
+            {Settings::NativeButton::ZR, PadButton::R2},
+            {Settings::NativeButton::SL, PadButton::L2},
+            {Settings::NativeButton::SR, PadButton::R2},
+            {Settings::NativeButton::LStick, PadButton::L3},
+            {Settings::NativeButton::RStick, PadButton::R3},
+        };
+    if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) {
+        return {};
+    }
+
+    ButtonMapping mapping{};
+    for (const auto& [switch_button, dsu_button] : switch_to_dsu_button) {
+        Common::ParamPackage button_params{};
+        button_params.Set("engine", GetEngineName());
+        button_params.Set("guid", params.Get("guid", ""));
+        button_params.Set("port", params.Get("port", 0));
+        button_params.Set("pad", params.Get("pad", 0));
+        button_params.Set("button", static_cast<int>(dsu_button));
+        mapping.insert_or_assign(switch_button, std::move(button_params));
+    }
+
+    return mapping;
+}
+
+AnalogMapping UDPClient::GetAnalogMappingForDevice(const Common::ParamPackage& params) {
+    if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) {
+        return {};
+    }
+
+    AnalogMapping mapping = {};
+    Common::ParamPackage left_analog_params;
+    left_analog_params.Set("engine", GetEngineName());
+    left_analog_params.Set("guid", params.Get("guid", ""));
+    left_analog_params.Set("port", params.Get("port", 0));
+    left_analog_params.Set("pad", params.Get("pad", 0));
+    left_analog_params.Set("axis_x", static_cast<int>(PadAxes::LeftStickX));
+    left_analog_params.Set("axis_y", static_cast<int>(PadAxes::LeftStickY));
+    mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params));
+    Common::ParamPackage right_analog_params;
+    right_analog_params.Set("engine", GetEngineName());
+    right_analog_params.Set("guid", params.Get("guid", ""));
+    right_analog_params.Set("port", params.Get("port", 0));
+    right_analog_params.Set("pad", params.Get("pad", 0));
+    right_analog_params.Set("axis_x", static_cast<int>(PadAxes::RightStickX));
+    right_analog_params.Set("axis_y", static_cast<int>(PadAxes::RightStickY));
+    mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params));
+    return mapping;
+}
+
+MotionMapping UDPClient::GetMotionMappingForDevice(const Common::ParamPackage& params) {
+    if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) {
+        return {};
+    }
+
+    MotionMapping mapping = {};
+    Common::ParamPackage motion_params;
+    motion_params.Set("engine", GetEngineName());
+    motion_params.Set("guid", params.Get("guid", ""));
+    motion_params.Set("port", params.Get("port", 0));
+    motion_params.Set("pad", params.Get("pad", 0));
+    motion_params.Set("motion", 0);
+    mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, std::move(motion_params));
+    mapping.insert_or_assign(Settings::NativeMotion::MotionRight, std::move(motion_params));
+    return mapping;
+}
+
+Common::Input::ButtonNames UDPClient::GetUIButtonName(const Common::ParamPackage& params) const {
+    PadButton button = static_cast<PadButton>(params.Get("button", 0));
+    switch (button) {
+    case PadButton::Left:
+        return Common::Input::ButtonNames::ButtonLeft;
+    case PadButton::Right:
+        return Common::Input::ButtonNames::ButtonRight;
+    case PadButton::Down:
+        return Common::Input::ButtonNames::ButtonDown;
+    case PadButton::Up:
+        return Common::Input::ButtonNames::ButtonUp;
+    case PadButton::L1:
+        return Common::Input::ButtonNames::L1;
+    case PadButton::L2:
+        return Common::Input::ButtonNames::L2;
+    case PadButton::L3:
+        return Common::Input::ButtonNames::L3;
+    case PadButton::R1:
+        return Common::Input::ButtonNames::R1;
+    case PadButton::R2:
+        return Common::Input::ButtonNames::R2;
+    case PadButton::R3:
+        return Common::Input::ButtonNames::R3;
+    case PadButton::Circle:
+        return Common::Input::ButtonNames::Circle;
+    case PadButton::Cross:
+        return Common::Input::ButtonNames::Cross;
+    case PadButton::Square:
+        return Common::Input::ButtonNames::Square;
+    case PadButton::Triangle:
+        return Common::Input::ButtonNames::Triangle;
+    case PadButton::Share:
+        return Common::Input::ButtonNames::Share;
+    case PadButton::Options:
+        return Common::Input::ButtonNames::Options;
+    default:
+        return Common::Input::ButtonNames::Undefined;
+    }
+}
+
+Common::Input::ButtonNames UDPClient::GetUIName(const Common::ParamPackage& params) const {
+    if (params.Has("button")) {
+        return GetUIButtonName(params);
+    }
+    if (params.Has("axis")) {
+        return Common::Input::ButtonNames::Value;
+    }
+    if (params.Has("motion")) {
+        return Common::Input::ButtonNames::Engine;
+    }
+
+    return Common::Input::ButtonNames::Invalid;
+}
+
 void TestCommunication(const std::string& host, u16 port,
                        const std::function<void()>& success_callback,
                        const std::function<void()>& failure_callback) {
diff --git a/src/input_common/drivers/udp_client.h b/src/input_common/drivers/udp_client.h
index 1f02adba58..5d483f26b3 100644
--- a/src/input_common/drivers/udp_client.h
+++ b/src/input_common/drivers/udp_client.h
@@ -56,7 +56,61 @@ public:
 
     void ReloadSockets();
 
+    /// Used for automapping features
+    std::vector<Common::ParamPackage> GetInputDevices() const override;
+    ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override;
+    AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
+    MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override;
+    Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
+
 private:
+    enum class PadButton {
+        Undefined = 0x0000,
+        Share = 0x0001,
+        L3 = 0x0002,
+        R3 = 0x0004,
+        Options = 0x0008,
+        Up = 0x0010,
+        Right = 0x0020,
+        Down = 0x0040,
+        Left = 0x0080,
+        L2 = 0x0100,
+        R2 = 0x0200,
+        L1 = 0x0400,
+        R1 = 0x0800,
+        Triangle = 0x1000,
+        Circle = 0x2000,
+        Cross = 0x4000,
+        Square = 0x8000,
+        Touch1 = 0x10000,
+        touch2 = 0x20000,
+    };
+
+    enum class PadAxes : u8 {
+        LeftStickX,
+        LeftStickY,
+        RightStickX,
+        RightStickY,
+        AnalogLeft,
+        AnalogDown,
+        AnalogRight,
+        AnalogUp,
+        AnalogSquare,
+        AnalogCross,
+        AnalogCircle,
+        AnalogTriangle,
+        AnalogR1,
+        AnalogL1,
+        AnalogR2,
+        AnalogL3,
+        AnalogR3,
+        Touch1X,
+        Touch1Y,
+        Touch2X,
+        Touch2Y,
+        Undefined,
+    };
+
     struct PadData {
         std::size_t pad_index{};
         bool connected{};
@@ -90,6 +144,8 @@ private:
     const PadIdentifier GetPadIdentifier(std::size_t pad_index) const;
     const Common::UUID GetHostUUID(const std::string host) const;
 
+    Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
+
     // Allocate clients for 8 udp servers
     static constexpr std::size_t MAX_UDP_CLIENTS = 8;
     static constexpr std::size_t PADS_PER_CLIENT = 4;
diff --git a/src/input_common/helpers/udp_protocol.h b/src/input_common/helpers/udp_protocol.h
index 1bdc9209e7..bcba12c58e 100644
--- a/src/input_common/helpers/udp_protocol.h
+++ b/src/input_common/helpers/udp_protocol.h
@@ -56,6 +56,12 @@ constexpr Type GetMessageType();
 
 namespace Request {
 
+enum RegisterFlags : u8 {
+    AllPads,
+    PadID,
+    PadMACAdddress,
+};
+
 struct Version {};
 /**
  * Requests the server to send information about what controllers are plugged into the ports
@@ -77,13 +83,8 @@ static_assert(std::is_trivially_copyable_v<PortInfo>,
  * timeout seems to be 5 seconds.
  */
 struct PadData {
-    enum class Flags : u8 {
-        AllPorts,
-        Id,
-        Mac,
-    };
     /// Determines which method will be used as a look up for the controller
-    Flags flags{};
+    RegisterFlags flags{};
     /// Index of the port of the controller to retrieve data about
     u8 port_id{};
     /// Mac address of the controller to retrieve data about
@@ -113,6 +114,36 @@ Message<T> Create(const T data, const u32 client_id = 0) {
 
 namespace Response {
 
+enum class ConnectionType : u8 {
+    None,
+    Usb,
+    Bluetooth,
+};
+
+enum class State : u8 {
+    Disconnected,
+    Reserved,
+    Connected,
+};
+
+enum class Model : u8 {
+    None,
+    PartialGyro,
+    FullGyro,
+    Generic,
+};
+
+enum class Battery : u8 {
+    None = 0x00,
+    Dying = 0x01,
+    Low = 0x02,
+    Medium = 0x03,
+    High = 0x04,
+    Full = 0x05,
+    Charging = 0xEE,
+    Charged = 0xEF,
+};
+
 struct Version {
     u16_le version{};
 };
@@ -122,11 +153,11 @@ static_assert(std::is_trivially_copyable_v<Version>,
 
 struct PortInfo {
     u8 id{};
-    u8 state{};
-    u8 model{};
-    u8 connection_type{};
+    State state{};
+    Model model{};
+    ConnectionType connection_type{};
     MacAddress mac;
-    u8 battery{};
+    Battery battery{};
     u8 is_pad_active{};
 };
 static_assert(sizeof(PortInfo) == 12, "UDP Response PortInfo struct has wrong size");
@@ -177,18 +208,18 @@ struct PadData {
     u8 right_stick_y{};
 
     struct AnalogButton {
-        u8 button_8{};
-        u8 button_7{};
-        u8 button_6{};
-        u8 button_5{};
-        u8 button_12{};
-        u8 button_11{};
-        u8 button_10{};
-        u8 button_9{};
-        u8 button_16{};
-        u8 button_15{};
-        u8 button_14{};
-        u8 button_13{};
+        u8 button_dpad_left_analog{};
+        u8 button_dpad_down_analog{};
+        u8 button_dpad_right_analog{};
+        u8 button_dpad_up_analog{};
+        u8 button_square_analog{};
+        u8 button_cross_analog{};
+        u8 button_circle_analog{};
+        u8 button_triangle_analog{};
+        u8 button_r1_analog{};
+        u8 button_l1_analog{};
+        u8 trigger_r2{};
+        u8 trigger_l2{};
     } analog_button;
 
     std::array<TouchPad, 2> touch;
diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp
index c5218f2cb7..6e0024b2da 100644
--- a/src/input_common/input_mapping.cpp
+++ b/src/input_common/input_mapping.cpp
@@ -3,6 +3,7 @@
 // Refer to the license.txt file included
 
 #include "common/common_types.h"
+#include "common/settings.h"
 #include "input_common/input_engine.h"
 #include "input_common/input_mapping.h"
 
@@ -182,6 +183,11 @@ bool MappingFactory::IsDriverValid(const MappingData& data) const {
     if (data.engine == "keyboard" && data.pad.port != 0) {
         return false;
     }
+    // To prevent mapping with two devices we disable any UDP except motion
+    if (!Settings::values.enable_udp_controller && data.engine == "cemuhookudp" &&
+        data.type != EngineInputType::Motion) {
+        return false;
+    }
     // The following drivers don't need to be mapped
     if (data.engine == "tas") {
         return false;
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 39e4935dc1..940744c5f0 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -63,9 +63,12 @@ struct InputSubsystem::Impl {
 
         udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
         udp_client->SetMappingCallback(mapping_callback);
-        udp_client_factory = std::make_shared<InputFactory>(udp_client);
+        udp_client_input_factory = std::make_shared<InputFactory>(udp_client);
+        udp_client_output_factory = std::make_shared<OutputFactory>(udp_client);
         Common::Input::RegisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName(),
-                                                                   udp_client_factory);
+                                                                   udp_client_input_factory);
+        Common::Input::RegisterFactory<Common::Input::OutputDevice>(udp_client->GetEngineName(),
+                                                                    udp_client_output_factory);
 
         tas_input = std::make_shared<TasInput::Tas>("tas");
         tas_input->SetMappingCallback(mapping_callback);
@@ -110,6 +113,7 @@ struct InputSubsystem::Impl {
         gcadapter.reset();
 
         Common::Input::UnregisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName());
+        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(udp_client->GetEngineName());
         udp_client.reset();
 
         Common::Input::UnregisterFactory<Common::Input::InputDevice>(tas_input->GetEngineName());
@@ -137,6 +141,8 @@ struct InputSubsystem::Impl {
         devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end());
         auto gcadapter_devices = gcadapter->GetInputDevices();
         devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end());
+        auto udp_devices = udp_client->GetInputDevices();
+        devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
 #ifdef HAVE_SDL2
         auto sdl_devices = sdl->GetInputDevices();
         devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
@@ -157,6 +163,9 @@ struct InputSubsystem::Impl {
         if (engine == gcadapter->GetEngineName()) {
             return gcadapter->GetAnalogMappingForDevice(params);
         }
+        if (engine == udp_client->GetEngineName()) {
+            return udp_client->GetAnalogMappingForDevice(params);
+        }
         if (engine == tas_input->GetEngineName()) {
             return tas_input->GetAnalogMappingForDevice(params);
         }
@@ -177,6 +186,9 @@ struct InputSubsystem::Impl {
         if (engine == gcadapter->GetEngineName()) {
             return gcadapter->GetButtonMappingForDevice(params);
         }
+        if (engine == udp_client->GetEngineName()) {
+            return udp_client->GetButtonMappingForDevice(params);
+        }
         if (engine == tas_input->GetEngineName()) {
             return tas_input->GetButtonMappingForDevice(params);
         }
@@ -194,8 +206,8 @@ struct InputSubsystem::Impl {
             return {};
         }
         const std::string engine = params.Get("engine", "");
-        if (engine == gcadapter->GetEngineName()) {
-            return gcadapter->GetMotionMappingForDevice(params);
+        if (engine == udp_client->GetEngineName()) {
+            return udp_client->GetMotionMappingForDevice(params);
         }
 #ifdef HAVE_SDL2
         if (engine == sdl->GetEngineName()) {
@@ -238,6 +250,9 @@ struct InputSubsystem::Impl {
         if (engine == gcadapter->GetEngineName()) {
             return true;
         }
+        if (engine == udp_client->GetEngineName()) {
+            return true;
+        }
         if (engine == tas_input->GetEngineName()) {
             return true;
         }
@@ -286,12 +301,13 @@ struct InputSubsystem::Impl {
     std::shared_ptr<InputFactory> mouse_factory;
     std::shared_ptr<InputFactory> gcadapter_input_factory;
     std::shared_ptr<InputFactory> touch_screen_factory;
-    std::shared_ptr<InputFactory> udp_client_factory;
+    std::shared_ptr<InputFactory> udp_client_input_factory;
     std::shared_ptr<InputFactory> tas_input_factory;
 
     std::shared_ptr<OutputFactory> keyboard_output_factory;
     std::shared_ptr<OutputFactory> mouse_output_factory;
     std::shared_ptr<OutputFactory> gcadapter_output_factory;
+    std::shared_ptr<OutputFactory> udp_client_output_factory;
     std::shared_ptr<OutputFactory> tas_output_factory;
 
 #ifdef HAVE_SDL2
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index ae1684dd4c..38fd6e93b3 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -447,6 +447,7 @@ void Config::ReadMotionTouchValues() {
     Settings::values.touch_from_button_map_index = std::clamp(
         Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
     ReadBasicSetting(Settings::values.udp_input_servers);
+    ReadBasicSetting(Settings::values.enable_udp_controller);
 }
 
 void Config::ReadCoreValues() {
@@ -942,6 +943,7 @@ void Config::SaveMotionTouchValues() {
     WriteBasicSetting(Settings::values.touch_device);
     WriteBasicSetting(Settings::values.touch_from_button_map_index);
     WriteBasicSetting(Settings::values.udp_input_servers);
+    WriteBasicSetting(Settings::values.enable_udp_controller);
 
     qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps"));
     for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index e6127f9e67..65c8e59ac4 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -130,6 +130,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
         static_cast<float>(ui->mouse_panning_sensitivity->value());
     Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked();
     Settings::values.enable_raw_input = ui->enable_raw_input->isChecked();
+    Settings::values.enable_udp_controller = ui->enable_udp_controller->isChecked();
 }
 
 void ConfigureInputAdvanced::LoadConfiguration() {
@@ -160,6 +161,7 @@ void ConfigureInputAdvanced::LoadConfiguration() {
     ui->mouse_panning_sensitivity->setValue(Settings::values.mouse_panning_sensitivity.GetValue());
     ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled);
     ui->enable_raw_input->setChecked(Settings::values.enable_raw_input.GetValue());
+    ui->enable_udp_controller->setChecked(Settings::values.enable_udp_controller.GetValue());
 
     UpdateUIEnabled();
 }
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui
index 75487a5d0a..df0e4d6024 100644
--- a/src/yuzu/configuration/configure_input_advanced.ui
+++ b/src/yuzu/configuration/configure_input_advanced.ui
@@ -2642,6 +2642,19 @@
                      </widget>
                    </item>
                    <item row="3" column="0">
+                     <widget class="QCheckBox" name="enable_udp_controller">
+                       <property name="minimumSize">
+                         <size>
+                           <width>0</width>
+                           <height>23</height>
+                         </size>
+                       </property>
+                       <property name="text">
+                         <string>Enable UDP controllers (not needed for motion)</string>
+                       </property>
+                     </widget>
+                   </item>
+                   <item row="4" column="0">
                      <widget class="QCheckBox" name="mouse_panning">
                        <property name="minimumSize">
                          <size>
@@ -2654,7 +2667,7 @@
                        </property>
                      </widget>
                    </item>
-                   <item row="3" column="2">
+                   <item row="4" column="2">
                      <widget class="QSpinBox" name="mouse_panning_sensitivity">
                        <property name="toolTip">
                          <string>Mouse sensitivity</string>
@@ -2676,14 +2689,14 @@
                        </property>
                      </widget>
                    </item>
-                   <item row="4" column="0">
+                   <item row="5" column="0">
                      <widget class="QLabel" name="motion_touch">
                        <property name="text">
                          <string>Motion / Touch</string>
                        </property>
                      </widget>
                    </item>
-                   <item row="4" column="2">
+                   <item row="5" column="2">
                      <widget class="QPushButton" name="buttonMotionTouch">
                        <property name="text">
                          <string>Configure</string>
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 6219a09a84..ec071d6ec4 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -78,6 +78,30 @@ QString GetButtonName(Common::Input::ButtonNames button_name) {
         return QObject::tr("Y");
     case Common::Input::ButtonNames::ButtonStart:
         return QObject::tr("Start");
+    case Common::Input::ButtonNames::L1:
+        return QObject::tr("L1");
+    case Common::Input::ButtonNames::L2:
+        return QObject::tr("L2");
+    case Common::Input::ButtonNames::L3:
+        return QObject::tr("L3");
+    case Common::Input::ButtonNames::R1:
+        return QObject::tr("R1");
+    case Common::Input::ButtonNames::R2:
+        return QObject::tr("R2");
+    case Common::Input::ButtonNames::R3:
+        return QObject::tr("R3");
+    case Common::Input::ButtonNames::Circle:
+        return QObject::tr("Circle");
+    case Common::Input::ButtonNames::Cross:
+        return QObject::tr("Cross");
+    case Common::Input::ButtonNames::Square:
+        return QObject::tr("Square");
+    case Common::Input::ButtonNames::Triangle:
+        return QObject::tr("Triangle");
+    case Common::Input::ButtonNames::Share:
+        return QObject::tr("Share");
+    case Common::Input::ButtonNames::Options:
+        return QObject::tr("Options");
     default:
         return QObject::tr("[undefined]");
     }

From a4a0638bc8043ddaea13025dd7e07b198cdb3cee Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Fri, 26 Nov 2021 18:55:28 -0600
Subject: [PATCH 87/88] applet/controller: Enable configuring mode while the
 applet is open

---
 src/yuzu/applets/qt_controller.cpp | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 6a2cdda634..eaa0f39f21 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -29,7 +29,7 @@ namespace {
 
 void UpdateController(Core::HID::EmulatedController* controller,
                       Core::HID::NpadStyleIndex controller_type, bool connected) {
-    if (controller->IsConnected()) {
+    if (controller->IsConnected(true)) {
         controller->Disconnect();
     }
     controller->SetNpadStyleIndex(controller_type);
@@ -139,6 +139,7 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
     DisableUnsupportedPlayers();
 
     for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) {
+        system.HIDCore().GetEmulatedControllerByIndex(player_index)->EnableConfiguration();
         SetEmulatedControllers(player_index);
     }
 
@@ -233,20 +234,24 @@ void QtControllerSelectorDialog::ApplyConfiguration() {
 
     Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
     Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
+    for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) {
+        system.HIDCore().GetEmulatedControllerByIndex(player_index)->DisableConfiguration();
+    }
 }
 
 void QtControllerSelectorDialog::LoadConfiguration() {
     const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
     for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
         const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index);
-        const auto connected = controller->IsConnected() || (index == 0 && handheld->IsConnected());
+        const auto connected =
+            controller->IsConnected(true) || (index == 0 && handheld->IsConnected(true));
         player_groupboxes[index]->setChecked(connected);
         connected_controller_checkboxes[index]->setChecked(connected);
         emulated_controllers[index]->setCurrentIndex(
-            GetIndexFromControllerType(controller->GetNpadStyleIndex(), index));
+            GetIndexFromControllerType(controller->GetNpadStyleIndex(true), index));
     }
 
-    UpdateDockedState(handheld->IsConnected());
+    UpdateDockedState(handheld->IsConnected(true));
 
     ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
     ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
@@ -510,8 +515,8 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index)
     const auto player_connected = player_groupboxes[player_index]->isChecked() &&
                                   controller_type != Core::HID::NpadStyleIndex::Handheld;
 
-    if (controller->GetNpadStyleIndex() == controller_type &&
-        controller->IsConnected() == player_connected) {
+    if (controller->GetNpadStyleIndex(true) == controller_type &&
+        controller->IsConnected(true) == player_connected) {
         // Set vibration devices in the event that the input device has changed.
         ConfigureVibration::SetVibrationDevices(player_index);
         return;
@@ -633,7 +638,7 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
     for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) {
         auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index);
         // Disconnect any unsupported players here and disable or hide them if applicable.
-        UpdateController(controller, controller->GetNpadStyleIndex(), false);
+        UpdateController(controller, controller->GetNpadStyleIndex(true), false);
         // Hide the player widgets when max_supported_controllers is less than or equal to 4.
         if (max_supported_players <= 4) {
             player_widgets[index]->hide();

From 182cd9004f75df21979d0edd47910fecbd129b63 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Fri, 26 Nov 2021 19:29:08 -0600
Subject: [PATCH 88/88] config: Remove vibration configuration

---
 src/common/settings_input.h                   |  2 -
 src/core/hid/emulated_controller.cpp          |  5 +-
 src/yuzu/applets/qt_controller.cpp            |  4 -
 src/yuzu/configuration/config.cpp             | 17 -----
 .../configuration/configure_vibration.cpp     | 74 -------------------
 src/yuzu/configuration/configure_vibration.h  |  3 -
 src/yuzu/main.cpp                             |  2 -
 7 files changed, 3 insertions(+), 104 deletions(-)

diff --git a/src/common/settings_input.h b/src/common/settings_input.h
index 9a88044881..9e3df73763 100644
--- a/src/common/settings_input.h
+++ b/src/common/settings_input.h
@@ -357,7 +357,6 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
 using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
 using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
 using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>;
-using VibrationsRaw = std::array<std::string, NativeVibration::NumVibrations>;
 
 constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28;
 constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A;
@@ -378,7 +377,6 @@ struct PlayerInput {
     ControllerType controller_type;
     ButtonsRaw buttons;
     AnalogsRaw analogs;
-    VibrationsRaw vibrations;
     MotionsRaw motions;
 
     bool vibration_enabled;
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 54d4ed93d7..06ae41c3eb 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -92,10 +92,11 @@ void EmulatedController::ReloadFromSettings() {
 
     ReloadInput();
 }
+
 void EmulatedController::LoadDevices() {
     // TODO(german77): Use more buttons to detect the correct device
-    const auto left_joycon = button_params[Settings::NativeButton::A];
-    const auto right_joycon = button_params[Settings::NativeButton::DRight];
+    const auto left_joycon = button_params[Settings::NativeButton::DRight];
+    const auto right_joycon = button_params[Settings::NativeButton::A];
 
     // Triggers for GC controllers
     trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL];
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index eaa0f39f21..589e0577a0 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -517,16 +517,12 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index)
 
     if (controller->GetNpadStyleIndex(true) == controller_type &&
         controller->IsConnected(true) == player_connected) {
-        // Set vibration devices in the event that the input device has changed.
-        ConfigureVibration::SetVibrationDevices(player_index);
         return;
     }
 
     // Disconnect the controller first.
     UpdateController(controller, controller_type, false);
 
-    ConfigureVibration::SetVibrationDevices(player_index);
-
     // Handheld
     if (player_index == 0) {
         if (controller_type == Core::HID::NpadStyleIndex::Handheld) {
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 38fd6e93b3..2c70d05486 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -273,18 +273,6 @@ void Config::ReadPlayerValue(std::size_t player_index) {
         }
     }
 
-    for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) {
-        auto& player_vibrations = player.vibrations[i];
-
-        player_vibrations =
-            qt_config
-                ->value(QStringLiteral("%1").arg(player_prefix) +
-                            QString::fromUtf8(Settings::NativeVibration::mapping[i]),
-                        QString{})
-                .toString()
-                .toStdString();
-    }
-
     for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
         const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
         auto& player_motions = player.motions[i];
@@ -891,11 +879,6 @@ void Config::SavePlayerValue(std::size_t player_index) {
                      QString::fromStdString(player.analogs[i]),
                      QString::fromStdString(default_param));
     }
-    for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) {
-        WriteSetting(QStringLiteral("%1").arg(player_prefix) +
-                         QString::fromStdString(Settings::NativeVibration::mapping[i]),
-                     QString::fromStdString(player.vibrations[i]), QString{});
-    }
     for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
         const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
         WriteSetting(QStringLiteral("%1").arg(player_prefix) +
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp
index f1ce7205d5..adce04b278 100644
--- a/src/yuzu/configuration/configure_vibration.cpp
+++ b/src/yuzu/configuration/configure_vibration.cpp
@@ -59,80 +59,6 @@ void ConfigureVibration::ApplyConfiguration() {
         ui->checkBoxAccurateVibration->isChecked());
 }
 
-void ConfigureVibration::SetVibrationDevices(std::size_t player_index) {
-    using namespace Settings::NativeButton;
-    static constexpr std::array<std::array<Settings::NativeButton::Values, 6>, 2> buttons{{
-        {DLeft, DUp, DRight, DDown, L, ZL}, // Left Buttons
-        {A, B, X, Y, R, ZR},                // Right Buttons
-    }};
-
-    auto& player = Settings::values.players.GetValue()[player_index];
-
-    for (std::size_t device_idx = 0; device_idx < buttons.size(); ++device_idx) {
-        std::unordered_map<std::string, int> params_count;
-
-        for (const auto button_index : buttons[device_idx]) {
-            const auto& player_button = player.buttons[button_index];
-
-            if (params_count.find(player_button) != params_count.end()) {
-                ++params_count[player_button];
-                continue;
-            }
-
-            params_count.insert_or_assign(player_button, 1);
-        }
-
-        const auto it = std::max_element(
-            params_count.begin(), params_count.end(),
-            [](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; });
-
-        auto& vibration_param_str = player.vibrations[device_idx];
-        vibration_param_str.clear();
-
-        if (it->first.empty()) {
-            continue;
-        }
-
-        const auto param = Common::ParamPackage(it->first);
-
-        const auto engine = param.Get("engine", "");
-        const auto guid = param.Get("guid", "");
-        const auto port = param.Get("port", 0);
-
-        if (engine.empty() || engine == "keyboard" || engine == "mouse" || engine == "tas") {
-            continue;
-        }
-
-        vibration_param_str += fmt::format("engine:{}", engine);
-
-        if (port != 0) {
-            vibration_param_str += fmt::format(",port:{}", port);
-        }
-        if (!guid.empty()) {
-            vibration_param_str += fmt::format(",guid:{}", guid);
-        }
-    }
-
-    if (player.vibrations[0] != player.vibrations[1]) {
-        return;
-    }
-
-    if (!player.vibrations[0].empty() &&
-        player.controller_type != Settings::ControllerType::RightJoycon) {
-        player.vibrations[1].clear();
-    } else if (!player.vibrations[1].empty() &&
-               player.controller_type == Settings::ControllerType::RightJoycon) {
-        player.vibrations[0].clear();
-    }
-}
-
-void ConfigureVibration::SetAllVibrationDevices() {
-    // Set vibration devices for all player indices including handheld
-    for (std::size_t player_idx = 0; player_idx < NUM_PLAYERS + 1; ++player_idx) {
-        SetVibrationDevices(player_idx);
-    }
-}
-
 void ConfigureVibration::changeEvent(QEvent* event) {
     if (event->type() == QEvent::LanguageChange) {
         RetranslateUI();
diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h
index 07411a86f8..37bbc26536 100644
--- a/src/yuzu/configuration/configure_vibration.h
+++ b/src/yuzu/configuration/configure_vibration.h
@@ -24,9 +24,6 @@ public:
 
     void ApplyConfiguration();
 
-    static void SetVibrationDevices(std::size_t player_index);
-    static void SetAllVibrationDevices();
-
 private:
     void changeEvent(QEvent* event) override;
     void RetranslateUI();
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 09ea21f5e5..552db6387d 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1380,8 +1380,6 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
         Config per_game_config(*system, config_file_name, Config::ConfigType::PerGameConfig);
     }
 
-    ConfigureVibration::SetAllVibrationDevices();
-
     // Disable fps limit toggle when booting a new title
     Settings::values.disable_fps_limit.SetValue(false);