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