From 61582efeb976b0852e73b734835d60c73b38f3cf Mon Sep 17 00:00:00 2001
From: Narr the Reg <juangerman-13@hotmail.com>
Date: Tue, 19 Apr 2022 15:30:32 -0500
Subject: [PATCH] service: hid: Access shared memory directly

---
 .../hid/controllers/console_sixaxis.cpp       |  20 +-
 .../service/hid/controllers/console_sixaxis.h |   7 +-
 .../service/hid/controllers/controller_base.h |   7 +-
 .../hle/service/hid/controllers/debug_pad.cpp |  19 +-
 .../hle/service/hid/controllers/debug_pad.h   |  18 +-
 .../hle/service/hid/controllers/gesture.cpp   |  32 +-
 .../hle/service/hid/controllers/gesture.h     |  17 +-
 .../hle/service/hid/controllers/keyboard.cpp  |  19 +-
 .../hle/service/hid/controllers/keyboard.h    |  17 +-
 .../hle/service/hid/controllers/mouse.cpp     |  19 +-
 src/core/hle/service/hid/controllers/mouse.h  |  19 +-
 src/core/hle/service/hid/controllers/npad.cpp | 290 +++++++++---------
 src/core/hle/service/hid/controllers/npad.h   |  27 +-
 .../hle/service/hid/controllers/stubbed.cpp   |  11 +-
 .../hle/service/hid/controllers/stubbed.h     |   5 +-
 .../service/hid/controllers/touchscreen.cpp   |  21 +-
 .../hle/service/hid/controllers/touchscreen.h |  18 +-
 src/core/hle/service/hid/controllers/xpad.cpp |  20 +-
 src/core/hle/service/hid/controllers/xpad.h   |  16 +-
 src/core/hle/service/hid/hid.cpp              |  41 ++-
 src/core/hle/service/hid/hid.h                |   9 +-
 21 files changed, 347 insertions(+), 305 deletions(-)

diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
index f5a0b94dd..c93bcd678 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
@@ -9,9 +9,14 @@
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
 
-Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_)
+Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_,
+                                                     u8* raw_shared_memory_)
     : ControllerBase{hid_core_} {
     console = hid_core.GetEmulatedConsole();
+    static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
+                  "ConsoleSharedMemory is bigger than the shared memory");
+    shared_memory =
+        std::construct_at(reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
 }
 
 Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default;
@@ -20,8 +25,7 @@ void Controller_ConsoleSixAxis::OnInit() {}
 
 void Controller_ConsoleSixAxis::OnRelease() {}
 
-void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                                         std::size_t size) {
+void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
     if (!IsControllerActivated() || !is_transfer_memory_set) {
         seven_sixaxis_lifo.buffer_count = 0;
         seven_sixaxis_lifo.buffer_tail = 0;
@@ -48,13 +52,11 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
         -motion_status.quaternion.xyz.z,
     };
 
-    console_six_axis.sampling_number++;
-    console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
-    console_six_axis.verticalization_error = motion_status.verticalization_error;
-    console_six_axis.gyro_bias = motion_status.gyro_bias;
+    shared_memory->sampling_number++;
+    shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
+    shared_memory->verticalization_error = motion_status.verticalization_error;
+    shared_memory->gyro_bias = motion_status.gyro_bias;
 
-    // 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
     seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
     std::memcpy(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo));
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h
index 6da5e9454..85b281957 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.h
@@ -17,7 +17,7 @@ class EmulatedConsole;
 namespace Service::HID {
 class Controller_ConsoleSixAxis final : public ControllerBase {
 public:
-    explicit Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_);
+    explicit Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
     ~Controller_ConsoleSixAxis() override;
 
     // Called when the controller is initialized
@@ -27,7 +27,7 @@ public:
     void OnRelease() override;
 
     // When the controller is requesting an update for the shared memory
-    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override;
+    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 
     // Called on InitializeSevenSixAxisSensor
     void SetTransferMemoryPointer(u8* t_mem);
@@ -61,12 +61,13 @@ private:
     Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{};
     static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size");
 
+    ConsoleSharedMemory* shared_memory;
+
     Core::HID::EmulatedConsole* console;
     u8* transfer_memory = nullptr;
     bool is_transfer_memory_set = false;
     u64 last_saved_timestamp{};
     u64 last_global_timestamp{};
-    ConsoleSharedMemory console_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 bb01ea643..d6f7a5073 100644
--- a/src/core/hle/service/hid/controllers/controller_base.h
+++ b/src/core/hle/service/hid/controllers/controller_base.h
@@ -26,12 +26,10 @@ public:
     virtual void OnRelease() = 0;
 
     // When the controller is requesting an update for the shared memory
-    virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                          std::size_t size) = 0;
+    virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing) = 0;
 
     // When the controller is requesting a motion update for the shared memory
-    virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                                std::size_t size) {}
+    virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {}
 
     void ActivateController();
 
@@ -40,6 +38,7 @@ public:
     bool IsControllerActivated() const;
 
     static const std::size_t hid_entry_count = 17;
+    static const std::size_t shared_memory_size = 0x40000;
 
 protected:
     bool is_activated{false};
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index 73309d64e..8ec9f4a95 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -13,8 +13,12 @@
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
 
-Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_)
+Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
     : ControllerBase{hid_core_} {
+    static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size,
+                  "DebugPadSharedMemory is bigger than the shared memory");
+    shared_memory = std::construct_at(
+        reinterpret_cast<DebugPadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
     controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
 }
 
@@ -24,16 +28,14 @@ void Controller_DebugPad::OnInit() {}
 
 void Controller_DebugPad::OnRelease() {}
 
-void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                                   std::size_t size) {
+void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
     if (!IsControllerActivated()) {
-        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));
+        shared_memory->debug_pad_lifo.buffer_count = 0;
+        shared_memory->debug_pad_lifo.buffer_tail = 0;
         return;
     }
 
-    const auto& last_entry = debug_pad_lifo.ReadCurrentEntry().state;
+    const auto& last_entry = shared_memory->debug_pad_lifo.ReadCurrentEntry().state;
     next_state.sampling_number = last_entry.sampling_number + 1;
 
     if (Settings::values.debug_pad_enabled) {
@@ -47,8 +49,7 @@ void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing,
         next_state.r_stick = stick_state.right;
     }
 
-    debug_pad_lifo.WriteNextEntry(next_state);
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo));
+    shared_memory->debug_pad_lifo.WriteNextEntry(next_state);
 }
 
 } // 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 388d25b3c..543e9f3a6 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -17,7 +17,7 @@ struct AnalogStickState;
 namespace Service::HID {
 class Controller_DebugPad final : public ControllerBase {
 public:
-    explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_);
+    explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
     ~Controller_DebugPad() override;
 
     // Called when the controller is initialized
@@ -27,7 +27,7 @@ public:
     void OnRelease() override;
 
     // When the controller is requesting an update for the shared memory
-    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
+    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 
 private:
     // This is nn::hid::DebugPadAttribute
@@ -49,11 +49,17 @@ private:
     };
     static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
 
-    // This is nn::hid::detail::DebugPadLifo
-    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{};
+    struct DebugPadSharedMemory {
+        // This is nn::hid::detail::DebugPadLifo
+        Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{};
+        static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
+        INSERT_PADDING_WORDS(0x4E);
+    };
+    static_assert(sizeof(DebugPadSharedMemory) == 0x400, "DebugPadSharedMemory is an invalid size");
 
+    DebugPadSharedMemory* shared_memory;
+
+    DebugPadState next_state{};
     Core::HID::EmulatedController* controller;
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index c8dd131dd..e03d47ef3 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -23,25 +23,28 @@ constexpr f32 Square(s32 num) {
     return static_cast<f32>(num * num);
 }
 
-Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_) : ControllerBase(hid_core_) {
+Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
+    : ControllerBase(hid_core_) {
+    static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size,
+                  "GestureSharedMemory is bigger than the shared memory");
+    shared_memory =
+        std::construct_at(reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
     console = hid_core.GetEmulatedConsole();
 }
 Controller_Gesture::~Controller_Gesture() = default;
 
 void Controller_Gesture::OnInit() {
-    gesture_lifo.buffer_count = 0;
-    gesture_lifo.buffer_tail = 0;
+    shared_memory->gesture_lifo.buffer_count = 0;
+    shared_memory->gesture_lifo.buffer_tail = 0;
     force_update = true;
 }
 
 void Controller_Gesture::OnRelease() {}
 
-void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                                  std::size_t size) {
+void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
     if (!IsControllerActivated()) {
-        gesture_lifo.buffer_count = 0;
-        gesture_lifo.buffer_tail = 0;
-        std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo));
+        shared_memory->gesture_lifo.buffer_count = 0;
+        shared_memory->gesture_lifo.buffer_tail = 0;
         return;
     }
 
@@ -49,15 +52,15 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
 
     GestureProperties gesture = GetGestureProperties();
     f32 time_difference =
-        static_cast<f32>(gesture_lifo.timestamp - last_update_timestamp) / (1000 * 1000 * 1000);
+        static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) /
+        (1000 * 1000 * 1000);
 
     // Only update if necesary
     if (!ShouldUpdateGesture(gesture, time_difference)) {
         return;
     }
 
-    last_update_timestamp = gesture_lifo.timestamp;
-    UpdateGestureSharedMemory(data, size, gesture, time_difference);
+    last_update_timestamp = shared_memory->gesture_lifo.timestamp;
 }
 
 void Controller_Gesture::ReadTouchInput() {
@@ -97,7 +100,7 @@ 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_lifo.ReadCurrentEntry().state;
 
     // Reset next state to default
     next_state.sampling_number = last_entry.sampling_number + 1;
@@ -127,8 +130,7 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
     next_state.points = gesture.points;
     last_gesture = gesture;
 
-    gesture_lifo.WriteNextEntry(next_state);
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo));
+    shared_memory->gesture_lifo.WriteNextEntry(next_state);
 }
 
 void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
@@ -305,7 +307,7 @@ void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
 }
 
 const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const {
-    return gesture_lifo.ReadCurrentEntry().state;
+    return shared_memory->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 7a9d28dc6..c8edb35e1 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -14,7 +14,7 @@
 namespace Service::HID {
 class Controller_Gesture final : public ControllerBase {
 public:
-    explicit Controller_Gesture(Core::HID::HIDCore& hid_core_);
+    explicit Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
     ~Controller_Gesture() override;
 
     // Called when the controller is initialized
@@ -24,7 +24,7 @@ public:
     void OnRelease() override;
 
     // When the controller is requesting an update for the shared memory
-    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override;
+    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 
 private:
     static constexpr size_t MAX_FINGERS = 16;
@@ -92,6 +92,14 @@ private:
         f32 angle{};
     };
 
+    struct GestureSharedMemory {
+        // This is nn::hid::detail::GestureLifo
+        Lifo<GestureState, hid_entry_count> gesture_lifo{};
+        static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
+        INSERT_PADDING_WORDS(0x3E);
+    };
+    static_assert(sizeof(GestureSharedMemory) == 0x800, "GestureSharedMemory is an invalid size");
+
     // Reads input from all available input engines
     void ReadTouchInput();
 
@@ -134,11 +142,8 @@ private:
     // Returns the average distance, angle and middle point of the active fingers
     GestureProperties GetGestureProperties();
 
-    // This is nn::hid::detail::GestureLifo
-    Lifo<GestureState, hid_entry_count> gesture_lifo{};
-    static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
+    GestureSharedMemory* shared_memory;
     GestureState next_state{};
-
     Core::HID::EmulatedConsole* console;
 
     std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{};
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 8dc67757b..534a3ff18 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -12,8 +12,12 @@
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
 
-Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_)
+Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
     : ControllerBase{hid_core_} {
+    static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size,
+                  "KeyboardSharedMemory is bigger than the shared memory");
+    shared_memory =
+        std::construct_at(reinterpret_cast<KeyboardSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
     emulated_devices = hid_core.GetEmulatedDevices();
 }
 
@@ -23,16 +27,14 @@ void Controller_Keyboard::OnInit() {}
 
 void Controller_Keyboard::OnRelease() {}
 
-void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                                   std::size_t size) {
+void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
     if (!IsControllerActivated()) {
-        keyboard_lifo.buffer_count = 0;
-        keyboard_lifo.buffer_tail = 0;
-        std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo));
+        shared_memory->keyboard_lifo.buffer_count = 0;
+        shared_memory->keyboard_lifo.buffer_tail = 0;
         return;
     }
 
-    const auto& last_entry = keyboard_lifo.ReadCurrentEntry().state;
+    const auto& last_entry = shared_memory->keyboard_lifo.ReadCurrentEntry().state;
     next_state.sampling_number = last_entry.sampling_number + 1;
 
     if (Settings::values.keyboard_enabled) {
@@ -44,8 +46,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
         next_state.attribute.is_connected.Assign(1);
     }
 
-    keyboard_lifo.WriteNextEntry(next_state);
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo));
+    shared_memory->keyboard_lifo.WriteNextEntry(next_state);
 }
 
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index 39c6085f1..4c9c06a39 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -16,7 +16,7 @@ struct KeyboardKey;
 namespace Service::HID {
 class Controller_Keyboard final : public ControllerBase {
 public:
-    explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_);
+    explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
     ~Controller_Keyboard() override;
 
     // Called when the controller is initialized
@@ -26,7 +26,7 @@ public:
     void OnRelease() override;
 
     // When the controller is requesting an update for the shared memory
-    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
+    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 
 private:
     // This is nn::hid::detail::KeyboardState
@@ -38,11 +38,16 @@ private:
     };
     static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
 
-    // This is nn::hid::detail::KeyboardLifo
-    Lifo<KeyboardState, hid_entry_count> keyboard_lifo{};
-    static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
-    KeyboardState next_state{};
+    struct KeyboardSharedMemory {
+        // This is nn::hid::detail::KeyboardLifo
+        Lifo<KeyboardState, hid_entry_count> keyboard_lifo{};
+        static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
+        INSERT_PADDING_WORDS(0xA);
+    };
+    static_assert(sizeof(KeyboardSharedMemory) == 0x400, "KeyboardSharedMemory is an invalid size");
 
+    KeyboardSharedMemory* shared_memory;
+    KeyboardState next_state{};
     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 a0292f586..730be33cd 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -12,7 +12,11 @@
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
 
-Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {
+Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
+    : ControllerBase{hid_core_} {
+    static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size,
+                  "MouseSharedMemory is bigger than the shared memory");
+    shared_memory = std::construct_at(reinterpret_cast<MouseSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
     emulated_devices = hid_core.GetEmulatedDevices();
 }
 
@@ -21,16 +25,14 @@ Controller_Mouse::~Controller_Mouse() = default;
 void Controller_Mouse::OnInit() {}
 void Controller_Mouse::OnRelease() {}
 
-void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                                std::size_t size) {
+void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
     if (!IsControllerActivated()) {
-        mouse_lifo.buffer_count = 0;
-        mouse_lifo.buffer_tail = 0;
-        std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo));
+        shared_memory->mouse_lifo.buffer_count = 0;
+        shared_memory->mouse_lifo.buffer_tail = 0;
         return;
     }
 
-    const auto& last_entry = mouse_lifo.ReadCurrentEntry().state;
+    const auto& last_entry = shared_memory->mouse_lifo.ReadCurrentEntry().state;
     next_state.sampling_number = last_entry.sampling_number + 1;
 
     next_state.attribute.raw = 0;
@@ -50,8 +52,7 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
         next_state.button = mouse_button_state;
     }
 
-    mouse_lifo.WriteNextEntry(next_state);
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo));
+    shared_memory->mouse_lifo.WriteNextEntry(next_state);
 }
 
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 62acdfb77..a9395c44b 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -16,7 +16,7 @@ struct AnalogStickState;
 namespace Service::HID {
 class Controller_Mouse final : public ControllerBase {
 public:
-    explicit Controller_Mouse(Core::HID::HIDCore& hid_core_);
+    explicit Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
     ~Controller_Mouse() override;
 
     // Called when the controller is initialized
@@ -26,15 +26,20 @@ public:
     void OnRelease() override;
 
     // When the controller is requesting an update for the shared memory
-    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
+    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 
 private:
-    // This is nn::hid::detail::MouseLifo
-    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{};
+    struct MouseSharedMemory {
+        // This is nn::hid::detail::MouseLifo
+        Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{};
+        static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
+        INSERT_PADDING_WORDS(0x2C);
+    };
+    static_assert(sizeof(MouseSharedMemory) == 0x400, "MouseSharedMemory is an invalid size");
 
-    Core::HID::AnalogStickState last_mouse_wheel_state;
+    MouseSharedMemory* shared_memory;
+    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/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 16e973b25..17f71beaf 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -61,11 +61,14 @@ bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle&
     return npad_id && npad_type && device_index;
 }
 
-Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
+Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
                                  KernelHelpers::ServiceContext& service_context_)
     : ControllerBase{hid_core_}, service_context{service_context_} {
+    static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);
     for (std::size_t i = 0; i < controller_data.size(); ++i) {
         auto& controller = controller_data[i];
+        controller.shared_memory = std::construct_at(reinterpret_cast<NpadInternalState*>(
+            raw_shared_memory_ + NPAD_OFFSET + (i * sizeof(NpadInternalState))));
         controller.device = hid_core.GetEmulatedControllerByIndex(i);
         controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
             Core::HID::DEFAULT_VIBRATION_VALUE;
@@ -115,11 +118,11 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
         if (!controller.device->IsConnected()) {
             return;
         }
-        auto& shared_memory = controller.shared_memory_entry;
+        auto* shared_memory = controller.shared_memory;
         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;
+        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:
@@ -134,99 +137,100 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
     }
     LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
     const auto controller_type = controller.device->GetNpadStyleIndex();
-    auto& shared_memory = controller.shared_memory_entry;
+    auto* shared_memory = controller.shared_memory;
     if (controller_type == Core::HID::NpadStyleIndex::None) {
         controller.styleset_changed_event->GetWritableEvent().Signal();
         return;
     }
-    shared_memory.style_tag.raw = Core::HID::NpadStyleSet::None;
-    shared_memory.device_type.raw = 0;
-    shared_memory.system_properties.raw = 0;
+    shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None;
+    shared_memory->device_type.raw = 0;
+    shared_memory->system_properties.raw = 0;
     switch (controller_type) {
     case Core::HID::NpadStyleIndex::None:
         UNREACHABLE();
         break;
     case Core::HID::NpadStyleIndex::ProController:
-        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);
-        shared_memory.system_properties.use_minus.Assign(1);
-        shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController;
+        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);
+        shared_memory->system_properties.use_minus.Assign(1);
+        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController;
         break;
     case Core::HID::NpadStyleIndex::Handheld:
-        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);
-        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;
+        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);
+        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_nfc_xcd.applet_footer.type =
+            AppletFooterUiType::HandheldJoyConLeftJoyConRight;
         break;
     case Core::HID::NpadStyleIndex::JoyconDual:
-        shared_memory.style_tag.joycon_dual.Assign(1);
+        shared_memory->style_tag.joycon_dual.Assign(1);
         if (controller.is_dual_left_connected) {
-            shared_memory.device_type.joycon_left.Assign(1);
-            shared_memory.system_properties.use_minus.Assign(1);
+            shared_memory->device_type.joycon_left.Assign(1);
+            shared_memory->system_properties.use_minus.Assign(1);
         }
         if (controller.is_dual_right_connected) {
-            shared_memory.device_type.joycon_right.Assign(1);
-            shared_memory.system_properties.use_plus.Assign(1);
+            shared_memory->device_type.joycon_right.Assign(1);
+            shared_memory->system_properties.use_plus.Assign(1);
         }
-        shared_memory.system_properties.use_directional_buttons.Assign(1);
-        shared_memory.system_properties.is_vertical.Assign(1);
-        shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
+        shared_memory->system_properties.use_directional_buttons.Assign(1);
+        shared_memory->system_properties.is_vertical.Assign(1);
+        shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
         if (controller.is_dual_left_connected && controller.is_dual_right_connected) {
-            shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
+            shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDual;
         } else if (controller.is_dual_left_connected) {
-            shared_memory.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly;
+            shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly;
         } else {
-            shared_memory.applet_footer.type = AppletFooterUiType::JoyDualRightOnly;
+            shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualRightOnly;
         }
         break;
     case Core::HID::NpadStyleIndex::JoyconLeft:
-        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);
-        shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
+        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);
+        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
         break;
     case Core::HID::NpadStyleIndex::JoyconRight:
-        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);
-        shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
+        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);
+        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
         break;
     case Core::HID::NpadStyleIndex::GameCube:
-        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);
+        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_tag.palma.Assign(1);
-        shared_memory.device_type.palma.Assign(1);
+        shared_memory->style_tag.palma.Assign(1);
+        shared_memory->device_type.palma.Assign(1);
         break;
     case Core::HID::NpadStyleIndex::NES:
-        shared_memory.style_tag.lark.Assign(1);
-        shared_memory.device_type.fullkey.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_tag.lucia.Assign(1);
-        shared_memory.device_type.fullkey.Assign(1);
-        shared_memory.applet_footer.type = AppletFooterUiType::Lucia;
+        shared_memory->style_tag.lucia.Assign(1);
+        shared_memory->device_type.fullkey.Assign(1);
+        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lucia;
         break;
     case Core::HID::NpadStyleIndex::N64:
-        shared_memory.style_tag.lagoon.Assign(1);
-        shared_memory.device_type.fullkey.Assign(1);
-        shared_memory.applet_footer.type = AppletFooterUiType::Lagon;
+        shared_memory->style_tag.lagoon.Assign(1);
+        shared_memory->device_type.fullkey.Assign(1);
+        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lagon;
         break;
     case Core::HID::NpadStyleIndex::SegaGenesis:
-        shared_memory.style_tag.lager.Assign(1);
-        shared_memory.device_type.fullkey.Assign(1);
+        shared_memory->style_tag.lager.Assign(1);
+        shared_memory->device_type.fullkey.Assign(1);
         break;
     default:
         break;
@@ -234,23 +238,23 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
 
     const auto& body_colors = controller.device->GetColors();
 
-    shared_memory.fullkey_color.attribute = ColorAttribute::Ok;
-    shared_memory.fullkey_color.fullkey = body_colors.fullkey;
+    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;
+    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
     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;
+    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;
 
     controller.is_connected = true;
     controller.device->Connect();
     SignalStyleSetChangedEvent(npad_id);
-    WriteEmptyEntry(controller.shared_memory_entry);
+    WriteEmptyEntry(controller.shared_memory);
 }
 
 void Controller_NPad::OnInit() {
@@ -270,12 +274,12 @@ void Controller_NPad::OnInit() {
 
     // Prefill controller buffers
     for (auto& controller : controller_data) {
-        auto& npad = controller.shared_memory_entry;
-        npad.fullkey_color = {
+        auto* npad = controller.shared_memory;
+        npad->fullkey_color = {
             .attribute = ColorAttribute::NoController,
             .fullkey = {},
         };
-        npad.joycon_color = {
+        npad->joycon_color = {
             .attribute = ColorAttribute::NoController,
             .left = {},
             .right = {},
@@ -287,25 +291,25 @@ void Controller_NPad::OnInit() {
     }
 }
 
-void Controller_NPad::WriteEmptyEntry(NpadInternalState& 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);
+    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() {
@@ -371,23 +375,19 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
     }
 }
 
-void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                               std::size_t data_len) {
+void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
     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;
+        auto* npad = controller.shared_memory;
 
         const auto& controller_type = controller.device->GetNpadStyleIndex();
 
         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));
             continue;
         }
 
@@ -415,8 +415,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
 
             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);
+                npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->fullkey_lifo.WriteNextEntry(pad_state);
             break;
         case Core::HID::NpadStyleIndex::Handheld:
             pad_state.connection_status.raw = 0;
@@ -433,8 +433,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             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);
+                npad->handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->handheld_lifo.WriteNextEntry(pad_state);
             break;
         case Core::HID::NpadStyleIndex::JoyconDual:
             pad_state.connection_status.raw = 0;
@@ -449,8 +449,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             }
 
             pad_state.sampling_number =
-                npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
-            npad.joy_dual_lifo.WriteNextEntry(pad_state);
+                npad->joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->joy_dual_lifo.WriteNextEntry(pad_state);
             break;
         case Core::HID::NpadStyleIndex::JoyconLeft:
             pad_state.connection_status.raw = 0;
@@ -459,8 +459,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
 
             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);
+                npad->joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->joy_left_lifo.WriteNextEntry(pad_state);
             break;
         case Core::HID::NpadStyleIndex::JoyconRight:
             pad_state.connection_status.raw = 0;
@@ -469,8 +469,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
 
             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);
+                npad->joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->joy_right_lifo.WriteNextEntry(pad_state);
             break;
         case Core::HID::NpadStyleIndex::GameCube:
             pad_state.connection_status.raw = 0;
@@ -479,18 +479,18 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
 
             libnx_state.connection_status.is_wired.Assign(1);
             pad_state.sampling_number =
-                npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+                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);
+                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::NpadStyleIndex::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);
+                npad->palma_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->palma_lifo.WriteNextEntry(pad_state);
             break;
         default:
             break;
@@ -499,17 +499,13 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
         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);
+        npad->system_ext_lifo.WriteNextEntry(pad_state);
 
         press_state |= static_cast<u64>(pad_state.npad_buttons.raw);
-
-        std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
-                    &controller.shared_memory_entry, sizeof(NpadInternalState));
     }
 }
 
-void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                                     std::size_t data_len) {
+void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {
     if (!IsControllerActivated()) {
         return;
     }
@@ -524,7 +520,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
             continue;
         }
 
-        auto& npad = controller.shared_memory_entry;
+        auto* npad = controller.shared_memory;
         const auto& motion_state = controller.device->GetMotions();
         auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
         auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
@@ -610,32 +606,30 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
         }
 
         sixaxis_fullkey_state.sampling_number =
-            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
         sixaxis_handheld_state.sampling_number =
-            npad.sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
         sixaxis_dual_left_state.sampling_number =
-            npad.sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
         sixaxis_dual_right_state.sampling_number =
-            npad.sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
         sixaxis_left_lifo_state.sampling_number =
-            npad.sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
         sixaxis_right_lifo_state.sampling_number =
-            npad.sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
+            npad->sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
 
         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);
+            npad->sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
         } else {
             // Handheld doesn't update this buffer on HW
-            npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
+            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);
-        npad.sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
-        std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
-                    &controller.shared_memory_entry, sizeof(NpadInternalState));
+        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);
     }
 }
 
@@ -713,8 +707,8 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceTy
     }
 
     auto& controller = GetControllerFromNpadIdType(npad_id);
-    if (controller.shared_memory_entry.assignment_mode != assignment_mode) {
-        controller.shared_memory_entry.assignment_mode = assignment_mode;
+    if (controller.shared_memory->assignment_mode != assignment_mode) {
+        controller.shared_memory->assignment_mode = assignment_mode;
     }
 
     if (!controller.device->IsConnected()) {
@@ -981,32 +975,32 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
         controller.vibration[device_idx].device_mounted = false;
     }
 
-    auto& shared_memory_entry = controller.shared_memory_entry;
-    // Don't reset shared_memory_entry.assignment_mode this value is persistent
-    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;
-    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 = {
+    auto* shared_memory = controller.shared_memory;
+    // Don't reset shared_memory->assignment_mode this value is persistent
+    shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out
+    shared_memory->device_type.raw = 0;
+    shared_memory->system_properties.raw = 0;
+    shared_memory->button_properties.raw = 0;
+    shared_memory->battery_level_dual = 0;
+    shared_memory->battery_level_left = 0;
+    shared_memory->battery_level_right = 0;
+    shared_memory->fullkey_color = {
         .attribute = ColorAttribute::NoController,
         .fullkey = {},
     };
-    shared_memory_entry.joycon_color = {
+    shared_memory->joycon_color = {
         .attribute = ColorAttribute::NoController,
         .left = {},
         .right = {},
     };
-    shared_memory_entry.applet_footer.type = AppletFooterUiType::None;
+    shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::None;
 
     controller.is_dual_left_connected = true;
     controller.is_dual_right_connected = true;
     controller.is_connected = false;
     controller.device->Disconnect();
     SignalStyleSetChangedEvent(npad_id);
-    WriteEmptyEntry(controller.shared_memory_entry);
+    WriteEmptyEntry(shared_memory);
 }
 
 ResultCode Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index b42532b68..425b84abd 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -35,7 +35,7 @@ namespace Service::HID {
 
 class Controller_NPad final : public ControllerBase {
 public:
-    explicit Controller_NPad(Core::HID::HIDCore& hid_core_,
+    explicit Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
                              KernelHelpers::ServiceContext& service_context_);
     ~Controller_NPad() override;
 
@@ -46,11 +46,10 @@ public:
     void OnRelease() override;
 
     // When the controller is requesting an update for the shared memory
-    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
+    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 
     // When the controller is requesting a motion update for the shared memory
-    void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                        std::size_t size) override;
+    void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) override;
 
     // This is nn::hid::GyroscopeZeroDriftMode
     enum class GyroscopeZeroDriftMode : u32 {
@@ -188,6 +187,8 @@ public:
     static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
 
 private:
+    static const std::size_t NPAD_COUNT = 10;
+
     // This is nn::hid::detail::ColorAttribute
     enum class ColorAttribute : u32 {
         Ok = 0,
@@ -409,6 +410,13 @@ private:
         U,
     };
 
+    struct AppletNfcXcd {
+        union {
+            AppletFooterUi applet_footer{};
+            Lifo<NfcXcdDeviceHandleStateImpl, 0x2> nfc_xcd_device_lifo;
+        };
+    };
+
     // This is nn::hid::detail::NpadInternalState
     struct NpadInternalState {
         Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None};
@@ -435,10 +443,7 @@ private:
         Core::HID::NpadBatteryLevel battery_level_dual{};
         Core::HID::NpadBatteryLevel battery_level_left{};
         Core::HID::NpadBatteryLevel battery_level_right{};
-        union {
-            AppletFooterUi applet_footer{};
-            Lifo<NfcXcdDeviceHandleStateImpl, 0x2> nfc_xcd_device_lifo;
-        };
+        AppletNfcXcd applet_nfc_xcd{};
         INSERT_PADDING_BYTES(0x20); // Unknown
         Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo{};
         NpadLarkType lark_type_l_and_main{};
@@ -467,7 +472,7 @@ private:
     struct NpadControllerData {
         Core::HID::EmulatedController* device;
         Kernel::KEvent* styleset_changed_event{};
-        NpadInternalState shared_memory_entry{};
+        NpadInternalState* shared_memory;
 
         std::array<VibrationData, 2> vibration{};
         bool unintended_home_button_input_protection{};
@@ -505,7 +510,7 @@ private:
     void InitNewlyAddedController(Core::HID::NpadIdType npad_id);
     bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const;
     void RequestPadStateUpdate(Core::HID::NpadIdType npad_id);
-    void WriteEmptyEntry(NpadInternalState& npad);
+    void WriteEmptyEntry(NpadInternalState* npad);
 
     NpadControllerData& GetControllerFromHandle(
         const Core::HID::SixAxisSensorHandle& device_handle);
@@ -520,7 +525,7 @@ private:
 
     std::atomic<u64> press_state{};
 
-    std::array<NpadControllerData, 10> controller_data{};
+    std::array<NpadControllerData, NPAD_COUNT> controller_data{};
     KernelHelpers::ServiceContext& service_context;
     std::mutex mutex;
     std::vector<Core::HID::NpadIdType> supported_npad_id_types{};
diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp
index 4d3b9d2be..df9ee0c3f 100644
--- a/src/core/hle/service/hid/controllers/stubbed.cpp
+++ b/src/core/hle/service/hid/controllers/stubbed.cpp
@@ -9,15 +9,18 @@
 
 namespace Service::HID {
 
-Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {}
+Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
+    : ControllerBase{hid_core_} {
+    raw_shared_memory = raw_shared_memory_;
+}
+
 Controller_Stubbed::~Controller_Stubbed() = default;
 
 void Controller_Stubbed::OnInit() {}
 
 void Controller_Stubbed::OnRelease() {}
 
-void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                                  std::size_t size) {
+void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
     if (!smart_update) {
         return;
     }
@@ -28,7 +31,7 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
     header.entry_count = 0;
     header.last_entry_index = 0;
 
-    std::memcpy(data + common_offset, &header, sizeof(CommonHeader));
+    std::memcpy(raw_shared_memory + common_offset, &header, sizeof(CommonHeader));
 }
 
 void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) {
diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h
index 512066eb3..5973358bc 100644
--- a/src/core/hle/service/hid/controllers/stubbed.h
+++ b/src/core/hle/service/hid/controllers/stubbed.h
@@ -9,7 +9,7 @@
 namespace Service::HID {
 class Controller_Stubbed final : public ControllerBase {
 public:
-    explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_);
+    explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
     ~Controller_Stubbed() override;
 
     // Called when the controller is initialized
@@ -19,7 +19,7 @@ public:
     void OnRelease() override;
 
     // When the controller is requesting an update for the shared memory
-    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
+    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 
     void SetCommonHeaderOffset(std::size_t off);
 
@@ -32,6 +32,7 @@ private:
     };
     static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
 
+    u8* raw_shared_memory;
     bool smart_update{};
     std::size_t common_offset{};
 };
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index 5b4b51a69..5f584586b 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -15,8 +15,12 @@
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
 
-Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_)
+Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_,
+                                               u8* raw_shared_memory_)
     : ControllerBase{hid_core_} {
+    static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size,
+                  "TouchSharedMemory is bigger than the shared memory");
+    shared_memory = std::construct_at(reinterpret_cast<TouchSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
     console = hid_core.GetEmulatedConsole();
 }
 
@@ -26,14 +30,12 @@ void Controller_Touchscreen::OnInit() {}
 
 void Controller_Touchscreen::OnRelease() {}
 
-void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                                      std::size_t size) {
-    touch_screen_lifo.timestamp = core_timing.GetCPUTicks();
+void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+    shared_memory->touch_screen_lifo.timestamp = core_timing.GetCPUTicks();
 
     if (!IsControllerActivated()) {
-        touch_screen_lifo.buffer_count = 0;
-        touch_screen_lifo.buffer_tail = 0;
-        std::memcpy(data, &touch_screen_lifo, sizeof(touch_screen_lifo));
+        shared_memory->touch_screen_lifo.buffer_count = 0;
+        shared_memory->touch_screen_lifo.buffer_tail = 0;
         return;
     }
 
@@ -74,7 +76,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
         static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
 
     const u64 tick = core_timing.GetCPUTicks();
-    const auto& last_entry = touch_screen_lifo.ReadCurrentEntry().state;
+    const auto& last_entry = shared_memory->touch_screen_lifo.ReadCurrentEntry().state;
 
     next_state.sampling_number = last_entry.sampling_number + 1;
     next_state.entry_count = static_cast<s32>(active_fingers_count);
@@ -106,8 +108,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
         }
     }
 
-    touch_screen_lifo.WriteNextEntry(next_state);
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &touch_screen_lifo, sizeof(touch_screen_lifo));
+    shared_memory->touch_screen_lifo.WriteNextEntry(next_state);
 }
 
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index 424973b38..2e1dde2f1 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -32,7 +32,7 @@ public:
     static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17,
                   "TouchScreenConfigurationForNx is an invalid size");
 
-    explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_);
+    explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
     ~Controller_Touchscreen() override;
 
     // Called when the controller is initialized
@@ -42,7 +42,7 @@ public:
     void OnRelease() override;
 
     // When the controller is requesting an update for the shared memory
-    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
+    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 
 private:
     static constexpr std::size_t MAX_FINGERS = 16;
@@ -56,11 +56,17 @@ private:
     };
     static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
 
-    // This is nn::hid::detail::TouchScreenLifo
-    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{};
+    struct TouchSharedMemory {
+        // This is nn::hid::detail::TouchScreenLifo
+        Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{};
+        static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
+        INSERT_PADDING_WORDS(0xF2);
+    };
+    static_assert(sizeof(TouchSharedMemory) == 0x3000, "TouchSharedMemory is an invalid size");
 
+    TouchSharedMemory* shared_memory;
+
+    TouchScreenState next_state{};
     std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers;
     Core::HID::EmulatedConsole* console;
 };
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp
index fc6ac6457..a35632560 100644
--- a/src/core/hle/service/hid/controllers/xpad.cpp
+++ b/src/core/hle/service/hid/controllers/xpad.cpp
@@ -10,28 +10,30 @@
 namespace Service::HID {
 constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00;
 
-Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {}
+Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
+    : ControllerBase{hid_core_} {
+    static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size,
+                  "XpadSharedMemory is bigger than the shared memory");
+    shared_memory = std::construct_at(reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
+}
 Controller_XPad::~Controller_XPad() = default;
 
 void Controller_XPad::OnInit() {}
 
 void Controller_XPad::OnRelease() {}
 
-void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
-                               std::size_t size) {
+void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
     if (!IsControllerActivated()) {
-        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));
+        shared_memory->basic_xpad_lifo.buffer_count = 0;
+        shared_memory->basic_xpad_lifo.buffer_tail = 0;
         return;
     }
 
-    const auto& last_entry = basic_xpad_lifo.ReadCurrentEntry().state;
+    const auto& last_entry = shared_memory->basic_xpad_lifo.ReadCurrentEntry().state;
     next_state.sampling_number = last_entry.sampling_number + 1;
     // TODO(ogniK): Update xpad states
 
-    basic_xpad_lifo.WriteNextEntry(next_state);
-    std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
+    shared_memory->basic_xpad_lifo.WriteNextEntry(next_state);
 }
 
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index 8211b6ee3..7ed8d5d97 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -12,7 +12,7 @@
 namespace Service::HID {
 class Controller_XPad final : public ControllerBase {
 public:
-    explicit Controller_XPad(Core::HID::HIDCore& hid_core_);
+    explicit Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
     ~Controller_XPad() override;
 
     // Called when the controller is initialized
@@ -22,7 +22,7 @@ public:
     void OnRelease() override;
 
     // When the controller is requesting an update for the shared memory
-    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
+    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 
 private:
     // This is nn::hid::BasicXpadAttributeSet
@@ -98,9 +98,15 @@ private:
     };
     static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size");
 
-    // This is nn::hid::detail::BasicXpadLifo
-    Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{};
-    static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size");
+    struct XpadSharedMemory {
+        // This is nn::hid::detail::BasicXpadLifo
+        Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{};
+        static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size");
+        INSERT_PADDING_WORDS(0x4E);
+    };
+    static_assert(sizeof(XpadSharedMemory) == 0x400, "XpadSharedMemory is an invalid size");
+
+    XpadSharedMemory* shared_memory;
     BasicXpadState next_state{};
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index fb1ec52b2..36162ac97 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -39,7 +39,6 @@ constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000};
 constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
 // TODO: Correct update rate for motion is 5ms. Check why some games don't behave at that speed
 constexpr auto motion_update_ns = std::chrono::nanoseconds{10 * 1000 * 1000}; // (10ms, 100Hz)
-constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
 
 IAppletResource::IAppletResource(Core::System& system_,
                                  KernelHelpers::ServiceContext& service_context_)
@@ -48,20 +47,20 @@ IAppletResource::IAppletResource(Core::System& system_,
         {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
     };
     RegisterHandlers(functions);
-
-    MakeController<Controller_DebugPad>(HidController::DebugPad);
-    MakeController<Controller_Touchscreen>(HidController::Touchscreen);
-    MakeController<Controller_Mouse>(HidController::Mouse);
-    MakeController<Controller_Keyboard>(HidController::Keyboard);
-    MakeController<Controller_XPad>(HidController::XPad);
-    MakeController<Controller_Stubbed>(HidController::HomeButton);
-    MakeController<Controller_Stubbed>(HidController::SleepButton);
-    MakeController<Controller_Stubbed>(HidController::CaptureButton);
-    MakeController<Controller_Stubbed>(HidController::InputDetector);
-    MakeController<Controller_Stubbed>(HidController::UniquePad);
-    MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad);
-    MakeController<Controller_Gesture>(HidController::Gesture);
-    MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor);
+    u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
+    MakeController<Controller_DebugPad>(HidController::DebugPad, shared_memory);
+    MakeController<Controller_Touchscreen>(HidController::Touchscreen, shared_memory);
+    MakeController<Controller_Mouse>(HidController::Mouse, shared_memory);
+    MakeController<Controller_Keyboard>(HidController::Keyboard, shared_memory);
+    MakeController<Controller_XPad>(HidController::XPad, shared_memory);
+    MakeController<Controller_Stubbed>(HidController::HomeButton, shared_memory);
+    MakeController<Controller_Stubbed>(HidController::SleepButton, shared_memory);
+    MakeController<Controller_Stubbed>(HidController::CaptureButton, shared_memory);
+    MakeController<Controller_Stubbed>(HidController::InputDetector, shared_memory);
+    MakeController<Controller_Stubbed>(HidController::UniquePad, shared_memory);
+    MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad, shared_memory);
+    MakeController<Controller_Gesture>(HidController::Gesture, shared_memory);
+    MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor, shared_memory);
 
     // Homebrew doesn't try to activate some controllers, so we activate them by default
     GetController<Controller_NPad>(HidController::NPad).ActivateController();
@@ -135,8 +134,7 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
         if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {
             continue;
         }
-        controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(),
-                             SHARED_MEMORY_SIZE);
+        controller->OnUpdate(core_timing);
     }
 
     // If ns_late is higher than the update rate ignore the delay
@@ -151,10 +149,8 @@ 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);
+    controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(core_timing);
+    controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(core_timing);
 
     // If ns_late is higher than the update rate ignore the delay
     if (ns_late > mouse_keyboard_update_ns) {
@@ -167,8 +163,7 @@ void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,
 void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
     auto& core_timing = system.CoreTiming();
 
-    controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(
-        core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
+    controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(core_timing);
 
     // If ns_late is higher than the update rate ignore the delay
     if (ns_late > motion_update_ns) {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 95778e673..e61f8ed08 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -58,13 +58,14 @@ public:
 
 private:
     template <typename T>
-    void MakeController(HidController controller) {
-        controllers[static_cast<std::size_t>(controller)] = std::make_unique<T>(system.HIDCore());
+    void MakeController(HidController controller, u8* shared_memory) {
+        controllers[static_cast<std::size_t>(controller)] =
+            std::make_unique<T>(system.HIDCore(), shared_memory);
     }
     template <typename T>
-    void MakeControllerWithServiceContext(HidController controller) {
+    void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) {
         controllers[static_cast<std::size_t>(controller)] =
-            std::make_unique<T>(system.HIDCore(), service_context);
+            std::make_unique<T>(system.HIDCore(), shared_memory, service_context);
     }
 
     void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);