diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 088f00b43622a14c1a5acd5ef545b19ff9f2d093..ca75adc2b3b715de295b19e350424d565333a85f 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -10,6 +10,7 @@
 
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
+constexpr u8 KEYS_PER_BYTE = 8;
 
 Controller_Keyboard::Controller_Keyboard() = default;
 Controller_Keyboard::~Controller_Keyboard() = default;
@@ -37,8 +38,8 @@ void Controller_Keyboard::OnUpdate(u8* data, std::size_t size) {
     cur_entry.sampling_number2 = cur_entry.sampling_number;
 
     for (std::size_t i = 0; i < keyboard_keys.size(); ++i) {
-        for (std::size_t k = 0; k < 8; ++k) {
-            cur_entry.key[i / 8] |= (keyboard_keys[i]->GetStatus() << k);
+        for (std::size_t k = 0; k < KEYS_PER_BYTE; ++k) {
+            cur_entry.key[i / KEYS_PER_BYTE] |= (keyboard_keys[i]->GetStatus() << k);
         }
     }
 
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 911ba3574c7892421bb03f66507fbdc84ed6fefd..46604887c7b27e264a3ba317593b94935261dc36 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -21,13 +21,9 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
 constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
 constexpr std::size_t NPAD_OFFSET = 0x9A00;
 constexpr u32 BATTERY_FULL = 2;
-constexpr u32 NPAD_HANDHELD = 32;
-constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this?
 constexpr u32 MAX_NPAD_ID = 7;
-constexpr Controller_NPad::NPadControllerType PREFERRED_CONTROLLER =
-    Controller_NPad::NPadControllerType::JoyDual;
 constexpr std::array<u32, 10> npad_id_list{
-    0, 1, 2, 3, 4, 5, 6, 7, 32, 16,
+    0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN,
 };
 
 enum class JoystickId : std::size_t {
@@ -51,7 +47,7 @@ static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::Contr
     }
 }
 
-static std::size_t NPadIdToIndex(u32 npad_id) {
+std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) {
     switch (npad_id) {
     case 0:
     case 1:
@@ -74,6 +70,27 @@ static std::size_t NPadIdToIndex(u32 npad_id) {
     }
 }
 
+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 8:
+        return NPAD_HANDHELD;
+    case 9:
+        return NPAD_UNKNOWN;
+    default:
+        UNIMPLEMENTED_MSG("Unknown npad index {}", index);
+        return 0;
+    };
+}
+
 Controller_NPad::Controller_NPad() = default;
 Controller_NPad::~Controller_NPad() = default;
 
@@ -190,7 +207,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));
-        AddNewController(PREFERRED_CONTROLLER);
+        AddNewController(NPadControllerType::JoyDual);
     }
 
     for (std::size_t i = 0; i < connected_controllers.size(); ++i) {
@@ -391,9 +408,9 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) {
             libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
             libnx_entry.connection_status.IsConnected.Assign(1);
 
-            dual_entry.pad_states.raw = pad_state.raw;
-            dual_entry.l_stick = lstick_entry;
-            dual_entry.r_stick = rstick_entry;
+            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;
             break;
         case NPadControllerType::JoyLeft:
             left_entry.connection_status.raw = 0;
@@ -461,23 +478,24 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
         if (!controller.is_connected) {
             continue;
         }
-        if (!IsControllerSupported(PREFERRED_CONTROLLER)) {
-            const auto best_type = DecideBestController(PREFERRED_CONTROLLER);
-            const bool is_handheld = (best_type == NPadControllerType::Handheld ||
-                                      PREFERRED_CONTROLLER == NPadControllerType::Handheld);
+        const auto requested_controller =
+            i <= MAX_NPAD_ID ? MapSettingsTypeToNPad(Settings::values.players[i].type)
+                             : NPadControllerType::Handheld;
+        if (!IsControllerSupported(requested_controller)) {
+            const auto is_handheld = requested_controller == NPadControllerType::Handheld;
             if (is_handheld) {
                 controller.type = NPadControllerType::None;
                 controller.is_connected = false;
-                AddNewController(best_type);
+                AddNewController(requested_controller);
             } else {
-                controller.type = best_type;
+                controller.type = requested_controller;
                 InitNewlyAddedControler(i);
             }
             had_controller_update = true;
         }
-    }
-    if (had_controller_update) {
-        styleset_changed_event->Signal();
+        if (had_controller_update) {
+            styleset_changed_event->Signal();
+        }
     }
 }
 
@@ -530,50 +548,6 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
     return last_processed_vibration;
 }
 
-std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) {
-    switch (npad_id) {
-    case 0:
-    case 1:
-    case 2:
-    case 3:
-    case 4:
-    case 5:
-    case 6:
-    case 7:
-        return static_cast<std::size_t>(npad_id);
-    case 8:
-    case 32:
-        return 8;
-    case 9:
-    case 16:
-        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 8:
-        return 32;
-    case 9:
-        return 16;
-    default:
-        UNIMPLEMENTED_MSG("Unknown npad index {}", index);
-        return 0;
-    };
-}
-
 void Controller_NPad::AddNewController(NPadControllerType controller) {
     controller = DecideBestController(controller);
     if (controller == NPadControllerType::Handheld) {
@@ -596,13 +570,13 @@ void Controller_NPad::AddNewController(NPadControllerType controller) {
 void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) {
     controller = DecideBestController(controller);
     if (controller == NPadControllerType::Handheld) {
-        connected_controllers[8] = {controller, true};
-        InitNewlyAddedControler(8);
+        connected_controllers[NPadIdToIndex(NPAD_HANDHELD)] = {controller, true};
+        InitNewlyAddedControler(NPadIdToIndex(NPAD_HANDHELD));
         return;
     }
-    const size_t controller_id = static_cast<std::size_t>(npad_id);
-    connected_controllers[controller_id] = {controller, true};
-    InitNewlyAddedControler(controller_id);
+
+    connected_controllers[npad_id] = {controller, true};
+    InitNewlyAddedControler(npad_id);
 }
 
 void Controller_NPad::ConnectNPad(u32 npad_id) {
@@ -613,97 +587,11 @@ void Controller_NPad::DisconnectNPad(u32 npad_id) {
     connected_controllers[NPadIdToIndex(npad_id)].is_connected = false;
 }
 
-Controller_NPad::NPadControllerType Controller_NPad::DecideBestController(
-    NPadControllerType priority) {
-    if (IsControllerSupported(priority)) {
-        return priority;
-    }
-    const auto is_docked = Settings::values.use_docked_mode;
-    if (is_docked && priority == NPadControllerType::Handheld) {
-        priority = NPadControllerType::JoyDual;
-        if (IsControllerSupported(priority)) {
-            return priority;
-        }
-    }
-    std::vector<NPadControllerType> priority_list{};
-    switch (priority) {
-    case NPadControllerType::ProController:
-        priority_list.push_back(NPadControllerType::JoyDual);
-        if (!is_docked) {
-            priority_list.push_back(NPadControllerType::Handheld);
-        }
-        priority_list.push_back(NPadControllerType::JoyLeft);
-        priority_list.push_back(NPadControllerType::JoyRight);
-        priority_list.push_back(NPadControllerType::Pokeball);
-        break;
-    case NPadControllerType::Handheld:
-        priority_list.push_back(NPadControllerType::JoyDual);
-        priority_list.push_back(NPadControllerType::ProController);
-        priority_list.push_back(NPadControllerType::JoyLeft);
-        priority_list.push_back(NPadControllerType::JoyRight);
-        priority_list.push_back(NPadControllerType::Pokeball);
-        break;
-    case NPadControllerType::JoyDual:
-        if (!is_docked) {
-            priority_list.push_back(NPadControllerType::Handheld);
-        }
-        priority_list.push_back(NPadControllerType::ProController);
-        priority_list.push_back(NPadControllerType::JoyLeft);
-        priority_list.push_back(NPadControllerType::JoyRight);
-        priority_list.push_back(NPadControllerType::Pokeball);
-        break;
-    case NPadControllerType::JoyLeft:
-        priority_list.push_back(NPadControllerType::JoyRight);
-        priority_list.push_back(NPadControllerType::JoyDual);
-        if (!is_docked) {
-            priority_list.push_back(NPadControllerType::Handheld);
-        }
-        priority_list.push_back(NPadControllerType::ProController);
-        priority_list.push_back(NPadControllerType::Pokeball);
-        break;
-    case NPadControllerType::JoyRight:
-        priority_list.push_back(NPadControllerType::JoyLeft);
-        priority_list.push_back(NPadControllerType::JoyDual);
-        if (!is_docked) {
-            priority_list.push_back(NPadControllerType::Handheld);
-        }
-        priority_list.push_back(NPadControllerType::ProController);
-        priority_list.push_back(NPadControllerType::Pokeball);
-        break;
-    case NPadControllerType::Pokeball:
-        priority_list.push_back(NPadControllerType::JoyLeft);
-        priority_list.push_back(NPadControllerType::JoyRight);
-        priority_list.push_back(NPadControllerType::JoyDual);
-        if (!is_docked) {
-            priority_list.push_back(NPadControllerType::Handheld);
-        }
-        priority_list.push_back(NPadControllerType::ProController);
-        break;
-    default:
-        priority_list.push_back(NPadControllerType::JoyDual);
-        if (!is_docked) {
-            priority_list.push_back(NPadControllerType::Handheld);
-        }
-        priority_list.push_back(NPadControllerType::ProController);
-        priority_list.push_back(NPadControllerType::JoyLeft);
-        priority_list.push_back(NPadControllerType::JoyRight);
-        priority_list.push_back(NPadControllerType::JoyDual);
-    }
-
-    for (const auto controller_type : priority_list) {
-        if (IsControllerSupported(controller_type)) {
-            return controller_type;
-        }
-    }
-    UNIMPLEMENTED_MSG("Could not find supported controller!");
-    return priority;
-}
-
 bool Controller_NPad::IsControllerSupported(NPadControllerType controller) {
     if (controller == NPadControllerType::Handheld) {
         // Handheld is not even a supported type, lets stop here
-        if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), 32) ==
-            supported_npad_id_types.end()) {
+        if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
+                      NPAD_HANDHELD) == supported_npad_id_types.end()) {
             return false;
         }
         // Handheld should not be supported in docked mode
@@ -761,13 +649,12 @@ void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
 }
 
 void Controller_NPad::ClearAllConnectedControllers() {
-    std::for_each(connected_controllers.begin(), connected_controllers.end(),
-                  [](ControllerHolder& controller) {
-                      if (controller.is_connected && controller.type != NPadControllerType::None) {
-                          controller.type = NPadControllerType::None;
-                          controller.is_connected = false;
-                      }
-                  });
+    for (auto& controller : connected_controllers) {
+        if (controller.is_connected && controller.type != NPadControllerType::None) {
+            controller.type = NPadControllerType::None;
+            controller.is_connected = false;
+        }
+    }
 }
 void Controller_NPad::DisconnectAllConnectedControllers() {
     std::for_each(connected_controllers.begin(), connected_controllers.end(),
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 52f92a4f14deb4c2e7d7aedf1578955c1a116ad1..ea8057b80a0df079a5be9957fdedabee6427fba5 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -5,13 +5,18 @@
 #pragma once
 
 #include <array>
+#include "common/bit_field.h"
 #include "common/common_types.h"
 #include "core/frontend/input.h"
+#include "core/hle/kernel/event.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
 #include "core/settings.h"
 
 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:
     Controller_NPad();
@@ -118,6 +123,9 @@ public:
     void ConnectAllDisconnectedControllers();
     void ClearAllControllers();
 
+    static std::size_t NPadIdToIndex(u32 npad_id);
+    static u32 IndexToNPad(std::size_t index);
+
 private:
     struct CommonHeader {
         s64_le timestamp;
@@ -304,10 +312,7 @@ private:
     bool IsControllerSupported(NPadControllerType controller) const;
     NPadControllerType DecideBestController(NPadControllerType priority) const;
     void RequestPadStateUpdate(u32 npad_id);
-    std::size_t NPadIdToIndex(u32 npad_id);
-    u32 IndexToNPad(std::size_t index);
     std::array<ControllerPad, 10> npad_pad_states{};
-    NPadControllerType DecideBestController(NPadControllerType priority);
     bool IsControllerSupported(NPadControllerType controller);
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index 8b9763de6e17630912192f2f4fc68f38e2350465..f666b1bd8f100a95e95701e811cd8b0bc40315c5 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -43,9 +43,6 @@ void Controller_Touchscreen::OnUpdate(u8* data, std::size_t size) {
     auto& touch_entry = cur_entry.states[0];
     touch_entry.attribute.raw = 0;
     if (pressed && Settings::values.touchscreen.enabled) {
-        if (cur_entry.entry_count == 0) {
-            touch_entry.attribute.start_touch.Assign(1);
-        }
         touch_entry.x = static_cast<u16>(x * Layout::ScreenUndocked::Width);
         touch_entry.y = static_cast<u16>(y * Layout::ScreenUndocked::Height);
         touch_entry.diameter_x = Settings::values.touchscreen.diameter_x;
@@ -57,9 +54,6 @@ void Controller_Touchscreen::OnUpdate(u8* data, std::size_t size) {
         touch_entry.finger = Settings::values.touchscreen.finger;
         cur_entry.entry_count = 1;
     } else {
-        if (cur_entry.entry_count == 1) {
-            touch_entry.attribute.end_touch.Assign(1);
-        }
         cur_entry.entry_count = 0;
     }
 
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 0da159559b8ed132561f2ee12cce8068f3628e79..26fcd340556ea71f6f09506ccca7383ff16133cf 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -10,6 +10,56 @@
 
 namespace Settings {
 
+namespace NativeButton {
+const std::array<const char*, NumButtons> mapping = {{
+    "button_a",
+    "button_b",
+    "button_x",
+    "button_y",
+    "button_lstick",
+    "button_rstick",
+    "button_l",
+    "button_r",
+    "button_zl",
+    "button_zr",
+    "button_plus",
+    "button_minus",
+    "button_dleft",
+    "button_dup",
+    "button_dright",
+    "button_ddown",
+    "button_lstick_left",
+    "button_lstick_up",
+    "button_lstick_right",
+    "button_lstick_down",
+    "button_rstick_left",
+    "button_rstick_up",
+    "button_rstick_right",
+    "button_rstick_down",
+    "button_sl",
+    "button_sr",
+    "button_home",
+    "button_screenshot",
+}};
+}
+
+namespace NativeAnalog {
+const std::array<const char*, NumAnalogs> mapping = {{
+    "lstick",
+    "rstick",
+}};
+}
+
+namespace NativeMouseButton {
+const std::array<const char*, NumMouseButtons> mapping = {{
+    "left",
+    "right",
+    "middle",
+    "forward",
+    "back",
+}};
+}
+
 Values values = {};
 
 void Apply() {
diff --git a/src/core/settings.h b/src/core/settings.h
index 9cc3c1dc8ee655f74ea2bf2787852f1b547d17f3..e63134f80e3f6044a695b8e4d78e1610f0986370 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -60,36 +60,7 @@ constexpr int BUTTON_NS_END = NumButtons;
 constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN;
 constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN;
 
-static const std::array<const char*, NumButtons> mapping = {{
-    "button_a",
-    "button_b",
-    "button_x",
-    "button_y",
-    "button_lstick",
-    "button_rstick",
-    "button_l",
-    "button_r",
-    "button_zl",
-    "button_zr",
-    "button_plus",
-    "button_minus",
-    "button_dleft",
-    "button_dup",
-    "button_dright",
-    "button_ddown",
-    "button_lstick_left",
-    "button_lstick_up",
-    "button_lstick_right",
-    "button_lstick_down",
-    "button_rstick_left",
-    "button_rstick_up",
-    "button_rstick_right",
-    "button_rstick_down",
-    "button_sl",
-    "button_sr",
-    "button_home",
-    "button_screenshot",
-}};
+extern const std::array<const char*, NumButtons> mapping;
 
 } // namespace NativeButton
 
@@ -105,10 +76,7 @@ constexpr int STICK_HID_BEGIN = LStick;
 constexpr int STICK_HID_END = NumAnalogs;
 constexpr int NUM_STICKS_HID = NumAnalogs;
 
-static const std::array<const char*, NumAnalogs> mapping = {{
-    "lstick",
-    "rstick",
-}};
+extern const std::array<const char*, NumAnalogs> mapping;
 } // namespace NativeAnalog
 
 namespace NativeMouseButton {
@@ -126,13 +94,7 @@ constexpr int MOUSE_HID_BEGIN = Left;
 constexpr int MOUSE_HID_END = NumMouseButtons;
 constexpr int NUM_MOUSE_HID = NumMouseButtons;
 
-static const std::array<const char*, NumMouseButtons> mapping = {{
-    "left",
-    "right",
-    "middle",
-    "forward",
-    "back",
-}};
+extern const std::array<const char*, NumMouseButtons> mapping;
 } // namespace NativeMouseButton
 
 namespace NativeKeyboard {
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index c931c7cd62c0a22cf2f4f2b6e402e4933a79fb33..652f6a0b73b918807a1d29dd1b31f81cf9d38917 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -203,9 +203,8 @@ const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default
     Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight,
 };
 
-void Config::ReadValues() {
-    qt_config->beginGroup("Controls");
-    for (std::size_t p = 0; p < 10; ++p) {
+void Config::ReadPlayerValues() {
+    for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
         Settings::values.players[p].connected =
             qt_config->value(QString("player_%1_connected").arg(p), false).toBool();
 
@@ -265,28 +264,9 @@ void Config::ReadValues() {
 
     std::stable_partition(Settings::values.players.begin(), Settings::values.players.end(),
                           [](const auto& player) { return player.connected; });
+}
 
-    Settings::values.motion_device =
-        qt_config->value("motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01")
-            .toString()
-            .toStdString();
-
-    Settings::values.mouse_enabled = qt_config->value("mouse_enabled", false).toBool();
-
-    for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
-        std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]);
-        Settings::values.mouse_buttons[i] =
-            qt_config
-                ->value(QString("mouse_") + Settings::NativeMouseButton::mapping[i],
-                        QString::fromStdString(default_param))
-                .toString()
-                .toStdString();
-        if (Settings::values.mouse_buttons[i].empty())
-            Settings::values.mouse_buttons[i] = default_param;
-    }
-
-    Settings::values.keyboard_enabled = qt_config->value("keyboard_enabled", false).toBool();
-
+void Config::ReadDebugValues() {
     Settings::values.debug_pad_enabled = qt_config->value("debug_pad_enabled", false).toBool();
     for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
         std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
@@ -313,7 +293,38 @@ void Config::ReadValues() {
         if (Settings::values.debug_pad_analogs[i].empty())
             Settings::values.debug_pad_analogs[i] = default_param;
     }
+}
+
+void Config::ReadKeyboardValues() {
+    Settings::values.keyboard_enabled = qt_config->value("keyboard_enabled", false).toBool();
 
+    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);
+}
+
+void Config::ReadMouseValues() {
+    Settings::values.mouse_enabled = qt_config->value("mouse_enabled", false).toBool();
+
+    for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
+        std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]);
+        Settings::values.mouse_buttons[i] =
+            qt_config
+                ->value(QString("mouse_") + Settings::NativeMouseButton::mapping[i],
+                        QString::fromStdString(default_param))
+                .toString()
+                .toStdString();
+        if (Settings::values.mouse_buttons[i].empty())
+            Settings::values.mouse_buttons[i] = default_param;
+    }
+}
+
+void Config::ReadTouchscreenValues() {
     Settings::values.touchscreen.enabled = qt_config->value("touchscreen_enabled", true).toBool();
     Settings::values.touchscreen.device =
         qt_config->value("touchscreen_device", "engine:emu_window").toString().toStdString();
@@ -325,6 +336,21 @@ void Config::ReadValues() {
     Settings::values.touchscreen.diameter_y =
         qt_config->value("touchscreen_diameter_y", 15).toUInt();
     qt_config->endGroup();
+}
+
+void Config::ReadValues() {
+    qt_config->beginGroup("Controls");
+
+    ReadPlayerValues();
+    ReadDebugValues();
+    ReadKeyboardValues();
+    ReadMouseValues();
+    ReadTouchscreenValues();
+
+    Settings::values.motion_device =
+        qt_config->value("motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01")
+            .toString()
+            .toStdString();
 
     qt_config->beginGroup("Core");
     Settings::values.use_cpu_jit = qt_config->value("use_cpu_jit", true).toBool();
@@ -370,15 +396,6 @@ void Config::ReadValues() {
             .toStdString());
     qt_config->endGroup();
 
-    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);
-
     qt_config->beginGroup("Core");
     Settings::values.use_cpu_jit = qt_config->value("use_cpu_jit", true).toBool();
     Settings::values.use_multi_core = qt_config->value("use_multi_core", false).toBool();
@@ -488,9 +505,8 @@ void Config::ReadValues() {
     qt_config->endGroup();
 }
 
-void Config::SaveValues() {
-    qt_config->beginGroup("Controls");
-    for (int p = 0; p < 10; ++p) {
+void Config::SavePlayerValues() {
+    for (int p = 0; p < Settings::values.players.size(); ++p) {
         qt_config->setValue(QString("player_%1_connected").arg(p),
                             Settings::values.players[p].connected);
         qt_config->setValue(QString("player_%1_type").arg(p),
@@ -516,19 +532,9 @@ void Config::SaveValues() {
                                 QString::fromStdString(Settings::values.players[p].analogs[i]));
         }
     }
+}
 
-    qt_config->setValue("motion_device", QString::fromStdString(Settings::values.motion_device));
-
-    qt_config->setValue("mouse_enabled", Settings::values.mouse_enabled);
-
-    for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
-        qt_config->setValue(QString("mouse_") +
-                                QString::fromStdString(Settings::NativeMouseButton::mapping[i]),
-                            QString::fromStdString(Settings::values.mouse_buttons[i]));
-    }
-
-    qt_config->setValue("keyboard_enabled", Settings::values.keyboard_enabled);
-
+void Config::SaveDebugValues() {
     qt_config->setValue("debug_pad_enabled", Settings::values.debug_pad_enabled);
     for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
         qt_config->setValue(QString("debug_pad_") +
@@ -540,7 +546,19 @@ void Config::SaveValues() {
                                 QString::fromStdString(Settings::NativeAnalog::mapping[i]),
                             QString::fromStdString(Settings::values.debug_pad_analogs[i]));
     }
+}
+
+void Config::SaveMouseValues() {
+    qt_config->setValue("mouse_enabled", Settings::values.mouse_enabled);
+
+    for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
+        qt_config->setValue(QString("mouse_") +
+                                QString::fromStdString(Settings::NativeMouseButton::mapping[i]),
+                            QString::fromStdString(Settings::values.mouse_buttons[i]));
+    }
+}
 
+void Config::SaveTouchscreenValues() {
     qt_config->setValue("touchscreen_enabled", Settings::values.touchscreen.enabled);
     qt_config->setValue("touchscreen_device",
                         QString::fromStdString(Settings::values.touchscreen.device));
@@ -549,6 +567,19 @@ void Config::SaveValues() {
     qt_config->setValue("touchscreen_angle", Settings::values.touchscreen.rotation_angle);
     qt_config->setValue("touchscreen_diameter_x", Settings::values.touchscreen.diameter_x);
     qt_config->setValue("touchscreen_diameter_y", Settings::values.touchscreen.diameter_y);
+}
+
+void Config::SaveValues() {
+    qt_config->beginGroup("Controls");
+
+    SavePlayerValues();
+    SaveDebugValues();
+    SaveMouseValues();
+    SaveTouchscreenValues();
+
+    qt_config->setValue("motion_device", QString::fromStdString(Settings::values.motion_device));
+    qt_config->setValue("keyboard_enabled", Settings::values.keyboard_enabled);
+
     qt_config->endGroup();
 
     qt_config->beginGroup("Core");
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index 1facd6b55ed1a3da60a21ffdfde7b7968926832c..a1c27bbf9c232de998802dc4d0a604a03f73a982 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -29,7 +29,17 @@ public:
 
 private:
     void ReadValues();
+    void ReadPlayerValues();
+    void ReadDebugValues();
+    void ReadKeyboardValues();
+    void ReadMouseValues();
+    void ReadTouchscreenValues();
+
     void SaveValues();
+    void SavePlayerValues();
+    void SaveDebugValues();
+    void SaveMouseValues();
+    void SaveTouchscreenValues();
 
     std::unique_ptr<QSettings> qt_config;
     std::string qt_config_loc;
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 9ae9827feb876dd6088ed8fceb2ef9341d421a93..a52abdd8f1ecd40e0590ef9a2492a9e56bcdd54c 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -11,6 +11,7 @@
 #include "common/param_package.h"
 #include "configuration/configure_touchscreen_advanced.h"
 #include "core/core.h"
+#include "core/hle/service/hid/controllers/npad.h"
 #include "input_common/main.h"
 #include "ui_configure_input.h"
 #include "ui_configure_input_player.h"
@@ -83,9 +84,9 @@ ConfigureInput::ConfigureInput(QWidget* parent)
 }
 
 template <typename Dialog, typename... Args>
-void ConfigureInput::CallConfigureDialog(Args... args) {
+void ConfigureInput::CallConfigureDialog(Args&&... args) {
     this->applyConfiguration();
-    Dialog dialog(this, args...);
+    Dialog dialog(this, std::forward<Args>(args)...);
 
     const auto res = dialog.exec();
     if (res == QDialog::Accepted) {
@@ -94,14 +95,16 @@ void ConfigureInput::CallConfigureDialog(Args... args) {
 }
 
 void ConfigureInput::applyConfiguration() {
-    for (std::size_t i = 0; i < 8; ++i) {
+    for (std::size_t i = 0; i < players_enabled.size(); ++i) {
         Settings::values.players[i].connected = players_enabled[i]->isChecked();
         Settings::values.players[i].type =
             static_cast<Settings::ControllerType>(player_controller[i]->currentIndex());
     }
 
     Settings::values.use_docked_mode = ui->use_docked_mode->isChecked();
-    Settings::values.players[8].connected = ui->handheld_connected->isChecked();
+    Settings::values
+        .players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)]
+        .connected = ui->handheld_connected->isChecked();
     Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked();
     Settings::values.mouse_enabled = ui->mouse_enabled->isChecked();
     Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked();
@@ -109,7 +112,7 @@ void ConfigureInput::applyConfiguration() {
 }
 
 void ConfigureInput::updateUIEnabled() {
-    for (std::size_t i = 0; i < 8; ++i) {
+    for (std::size_t i = 0; i < players_enabled.size(); ++i) {
         const auto enabled = players_enabled[i]->checkState() == Qt::Checked;
 
         player_controller[i]->setEnabled(enabled);
@@ -118,10 +121,7 @@ void ConfigureInput::updateUIEnabled() {
 
     bool hit_disabled = false;
     for (auto* player : players_enabled) {
-        if (hit_disabled)
-            player->setDisabled(true);
-        else
-            player->setEnabled(true);
+        player->setDisabled(hit_disabled);
         if (!player->isChecked())
             hit_disabled = true;
     }
@@ -138,13 +138,16 @@ void ConfigureInput::loadConfiguration() {
     std::stable_partition(Settings::values.players.begin(), Settings::values.players.end(),
                           [](const auto& player) { return player.connected; });
 
-    for (std::size_t i = 0; i < 8; ++i) {
+    for (std::size_t i = 0; i < players_enabled.size(); ++i) {
         players_enabled[i]->setChecked(Settings::values.players[i].connected);
         player_controller[i]->setCurrentIndex(static_cast<u8>(Settings::values.players[i].type));
     }
 
     ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);
-    ui->handheld_connected->setChecked(Settings::values.players[8].connected);
+    ui->handheld_connected->setChecked(
+        Settings::values
+            .players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)]
+            .connected);
     ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled);
     ui->mouse_enabled->setChecked(Settings::values.mouse_enabled);
     ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled);
@@ -157,7 +160,7 @@ void ConfigureInput::restoreDefaults() {
     players_enabled[0]->setCheckState(Qt::Checked);
     player_controller[0]->setCurrentIndex(1);
 
-    for (std::size_t i = 1; i < 8; ++i) {
+    for (std::size_t i = 1; i < players_enabled.size(); ++i) {
         players_enabled[i]->setCheckState(Qt::Unchecked);
         player_controller[i]->setCurrentIndex(0);
     }
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h
index 0ba77c5ef61e8de1b406bbe719ed01522ed3e1af..51b8e609ce9141dc99c23e7ebd2f9108d6b663c0 100644
--- a/src/yuzu/configuration/configure_input.h
+++ b/src/yuzu/configuration/configure_input.h
@@ -41,7 +41,7 @@ private:
     void updateUIEnabled();
 
     template <typename Dialog, typename... Args>
-    void CallConfigureDialog(Args... args);
+    void CallConfigureDialog(Args&&... args);
 
     /// Load configuration settings.
     void loadConfiguration();
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 5de7dd9626f0e438cdcb1649bbe267e553c9ccb5..995725b0f42e29f8d910323a89f47108c8cdab97 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -41,7 +41,7 @@ static void LayerGridElements(QGridLayout* grid, QWidget* item, QWidget* onTopOf
     grid->addWidget(item, row, column, rowSpan, columnSpan);
 }
 
-static QString getKeyName(int key_code) {
+static QString GetKeyName(int key_code) {
     switch (key_code) {
     case Qt::Key_Shift:
         return QObject::tr("Shift");
@@ -71,7 +71,7 @@ static QString ButtonToText(const Common::ParamPackage& param) {
     if (!param.Has("engine")) {
         return QObject::tr("[not set]");
     } else if (param.Get("engine", "") == "keyboard") {
-        return getKeyName(param.Get("code", 0));
+        return GetKeyName(param.Get("code", 0));
     } else if (param.Get("engine", "") == "sdl") {
         if (param.Has("hat")) {
             return QString(QObject::tr("Hat %1 %2"))
@@ -486,7 +486,7 @@ void ConfigureInputPlayer::setPollingResult(const Common::ParamPackage& params,
     }
 
     updateButtonLabels();
-    input_setter = boost::none;
+    input_setter = std::nullopt;
 }
 
 void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index 67cc6a8ca39aad9caf2ca81470a76b1256b6addd..8248cd7de6da6b2d6d55d23c55a00fbe11ecfec6 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -7,11 +7,11 @@
 #include <array>
 #include <functional>
 #include <memory>
+#include <optional>
 #include <string>
 #include <unordered_map>
 #include <QDialog>
 #include <QKeyEvent>
-#include <boost/optional.hpp>
 #include "common/param_package.h"
 #include "core/settings.h"
 #include "input_common/main.h"
@@ -44,7 +44,7 @@ private:
     std::unique_ptr<QTimer> poll_timer;
 
     /// This will be the the setting function when an input is awaiting configuration.
-    boost::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
+    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;
diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp
index 8cfcd1679433d191b5f0dec06c7c85312f360164..ac9c840961c7938f5fa3a927607281612fab22fb 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.cpp
+++ b/src/yuzu/configuration/configure_mouse_advanced.cpp
@@ -16,7 +16,7 @@
 #include "yuzu/configuration/config.h"
 #include "yuzu/configuration/configure_mouse_advanced.h"
 
-static QString getKeyName(int key_code) {
+static QString GetKeyName(int key_code) {
     switch (key_code) {
     case Qt::Key_Shift:
         return QObject::tr("Shift");
@@ -35,7 +35,7 @@ static QString ButtonToText(const Common::ParamPackage& param) {
     if (!param.Has("engine")) {
         return QObject::tr("[not set]");
     } else if (param.Get("engine", "") == "keyboard") {
-        return getKeyName(param.Get("code", 0));
+        return GetKeyName(param.Get("code", 0));
     } else if (param.Get("engine", "") == "sdl") {
         if (param.Has("hat")) {
             return QString(QObject::tr("Hat %1 %2"))
@@ -191,7 +191,7 @@ void ConfigureMouseAdvanced::setPollingResult(const Common::ParamPackage& params
     }
 
     updateButtonLabels();
-    input_setter = boost::none;
+    input_setter = std::nullopt;
 }
 
 void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) {
diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h
index f897d9044db565a35a20db231a7ecfedfc134470..983ac4158c98433c8c523d758ddd3fb5673707cc 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.h
+++ b/src/yuzu/configuration/configure_mouse_advanced.h
@@ -5,9 +5,9 @@
 #pragma once
 
 #include <memory>
+#include <optional>
 #include <QDialog>
 #include <QWidget>
-#include <boost/optional.hpp>
 #include "core/settings.h"
 
 class QCheckBox;
@@ -30,7 +30,7 @@ private:
     std::unique_ptr<Ui::ConfigureMouseAdvanced> ui;
 
     /// This will be the the setting function when an input is awaiting configuration.
-    boost::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
+    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;
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.cpp b/src/yuzu/configuration/configure_touchscreen_advanced.cpp
index 6cf3dab973f0fe6efaa6f1c05e90209240068f10..9c1561e9d137aaa82a4f38aa1675d1c9866f7599 100644
--- a/src/yuzu/configuration/configure_touchscreen_advanced.cpp
+++ b/src/yuzu/configuration/configure_touchscreen_advanced.cpp
@@ -2,15 +2,7 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include <algorithm>
 #include <memory>
-#include <utility>
-#include <QMenu>
-#include <QMessageBox>
-#include <QTimer>
-#include "common/assert.h"
-#include "common/param_package.h"
-#include "input_common/main.h"
 #include "ui_configure_touchscreen_advanced.h"
 #include "yuzu/configuration/config.h"
 #include "yuzu/configuration/configure_touchscreen_advanced.h"
@@ -22,10 +14,12 @@ ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent)
     connect(ui->restore_defaults_button, &QPushButton::pressed, this,
             &ConfigureTouchscreenAdvanced::restoreDefaults);
 
-    this->loadConfiguration();
-    this->resize(0, 0);
+    loadConfiguration();
+    resize(0, 0);
 }
 
+ConfigureTouchscreenAdvanced::~ConfigureTouchscreenAdvanced() = default;
+
 void ConfigureTouchscreenAdvanced::applyConfiguration() {
     Settings::values.touchscreen.finger = ui->finger_box->value();
     Settings::values.touchscreen.diameter_x = ui->diameter_x_box->value();
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.h b/src/yuzu/configuration/configure_touchscreen_advanced.h
index 938a62ed3c2d06f212e2e21fabf7eb5b36f82ca2..41cd255fbfc1a02aa9a79c6d4227099f81965e92 100644
--- a/src/yuzu/configuration/configure_touchscreen_advanced.h
+++ b/src/yuzu/configuration/configure_touchscreen_advanced.h
@@ -18,6 +18,7 @@ class ConfigureTouchscreenAdvanced : public QDialog {
 
 public:
     explicit ConfigureTouchscreenAdvanced(QWidget* parent);
+    ~ConfigureTouchscreenAdvanced() override;
 
     void applyConfiguration();