diff --git a/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs b/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs
index fd89e8f644..0597cf9b4e 100644
--- a/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs
+++ b/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs
@@ -4,6 +4,7 @@ using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using Ryujinx.Common.Logging;
 using Ryujinx.HLE.HOS.Services.Hid;
+using Ryujinx.HLE.HOS.Services.Hid.Types;
 using Ryujinx.HLE.HOS.Services.Am.AppletAE;
 
 using static Ryujinx.HLE.HOS.Services.Hid.HidServer.HidUtils;
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Hid.cs b/Ryujinx.HLE/HOS/Services/Hid/Hid.cs
index 18a7ba11d6..1e85dbf750 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Hid.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Hid.cs
@@ -3,6 +3,14 @@ using Ryujinx.HLE.Exceptions;
 using Ryujinx.Common.Configuration.Hid;
 using System.Collections.Generic;
 using System.Runtime.CompilerServices;
+using Ryujinx.Common.Memory;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugPad;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.TouchScreen;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad;
 
 namespace Ryujinx.HLE.HOS.Services.Hid
 {
@@ -12,7 +20,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
 
         private readonly ulong _hidMemoryAddress;
 
-        internal ref HidSharedMemory SharedMemory => ref _device.Memory.GetRef<HidSharedMemory>(_hidMemoryAddress);
+        internal ref SharedMemory SharedMemory => ref _device.Memory.GetRef<SharedMemory>(_hidMemoryAddress);
 
         internal const int SharedMemEntryCount = 17;
 
@@ -22,32 +30,22 @@ namespace Ryujinx.HLE.HOS.Services.Hid
         public KeyboardDevice Keyboard;
         public NpadDevices    Npads;
 
+        private static void CheckTypeSizeOrThrow<T>(int expectedSize)
+        {
+            if (Unsafe.SizeOf<T>() != expectedSize)
+            {
+                throw new InvalidStructLayoutException<T>(expectedSize);
+            }
+        }
+
         static Hid()
         {
-            if (Unsafe.SizeOf<ShMemDebugPad>() != 0x400)
-            {
-                throw new InvalidStructLayoutException<ShMemDebugPad>(0x400);
-            }
-            if (Unsafe.SizeOf<ShMemTouchScreen>() != 0x3000)
-            {
-                throw new InvalidStructLayoutException<ShMemTouchScreen>(0x3000);
-            }
-            if (Unsafe.SizeOf<ShMemKeyboard>() != 0x400)
-            {
-                throw new InvalidStructLayoutException<ShMemKeyboard>(0x400);
-            }
-            if (Unsafe.SizeOf<ShMemMouse>() != 0x400)
-            {
-                throw new InvalidStructLayoutException<ShMemMouse>(0x400);
-            }
-            if (Unsafe.SizeOf<ShMemNpad>() != 0x5000)
-            {
-                throw new InvalidStructLayoutException<ShMemNpad>(0x5000);
-            }
-            if (Unsafe.SizeOf<HidSharedMemory>() != Horizon.HidSize)
-            {
-                throw new InvalidStructLayoutException<HidSharedMemory>(Horizon.HidSize);
-            }
+            CheckTypeSizeOrThrow<RingLifo<DebugPadState>>(0x2c8);
+            CheckTypeSizeOrThrow<RingLifo<TouchScreenState>>(0x2C38);
+            CheckTypeSizeOrThrow<RingLifo<MouseState>>(0x350);
+            CheckTypeSizeOrThrow<RingLifo<KeyboardState>>(0x3D8);
+            CheckTypeSizeOrThrow<Array10<NpadState>>(0x32000);
+            CheckTypeSizeOrThrow<SharedMemory>(Horizon.HidSize);
         }
 
         public Hid(in Switch device, ulong sharedHidMemoryAddress)
@@ -55,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
             _device           = device;
             _hidMemoryAddress = sharedHidMemoryAddress;
 
-            device.Memory.ZeroFill(sharedHidMemoryAddress, Horizon.HidSize);
+            SharedMemory = SharedMemory.Create();
         }
 
         public void InitDevices()
diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/BaseDevice.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/BaseDevice.cs
index 59d6dfa3eb..e8bf628a21 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/BaseDevice.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/BaseDevice.cs
@@ -12,18 +12,5 @@ namespace Ryujinx.HLE.HOS.Services.Hid
             _device = device;
             Active = active;
         }
-
-        internal static int UpdateEntriesHeader(ref CommonEntriesHeader header, out int previousEntry)
-        {
-            header.NumEntries = SharedMemEntryCount;
-            header.MaxEntryIndex = SharedMemEntryCount - 1;
-
-            previousEntry = (int)header.LatestEntry;
-            header.LatestEntry = (header.LatestEntry + 1) % SharedMemEntryCount;
-
-            header.TimestampTicks = GetTimestampTicks();
-
-            return (int)header.LatestEntry; // EntryCount shouldn't overflow int
-        }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/DebugPadDevice.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/DebugPadDevice.cs
index 7e708e32c9..e3b95390b0 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/DebugPadDevice.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/DebugPadDevice.cs
@@ -1,3 +1,6 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugPad;
+
 namespace Ryujinx.HLE.HOS.Services.Hid
 {
     public class DebugPadDevice : BaseDevice
@@ -6,20 +9,20 @@ namespace Ryujinx.HLE.HOS.Services.Hid
 
         public void Update()
         {
-            ref ShMemDebugPad debugPad = ref _device.Hid.SharedMemory.DebugPad;
+            ref RingLifo<DebugPadState> lifo = ref _device.Hid.SharedMemory.DebugPad;
 
-            int currentIndex = UpdateEntriesHeader(ref debugPad.Header, out int previousIndex);
+            ref DebugPadState previousEntry = ref lifo.GetCurrentEntryRef();
 
-            if (!Active)
+            DebugPadState newState = new DebugPadState();
+
+            if (Active)
             {
-                return;
+                // TODO: This is a debug device only present in dev environment, do we want to support it?
             }
 
-            ref DebugPadEntry currentEntry = ref debugPad.Entries[currentIndex];
-            DebugPadEntry previousEntry = debugPad.Entries[previousIndex];
+            newState.SamplingNumber = previousEntry.SamplingNumber + 1;
 
-            currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1;
-            currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1;
+            lifo.Write(ref newState);
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/KeyboardDevice.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/KeyboardDevice.cs
index e8ed6a3e6a..99dc078dac 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/KeyboardDevice.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/KeyboardDevice.cs
@@ -1,3 +1,7 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard;
+using System;
+
 namespace Ryujinx.HLE.HOS.Services.Hid
 {
     public class KeyboardDevice : BaseDevice
@@ -6,27 +10,26 @@ namespace Ryujinx.HLE.HOS.Services.Hid
 
         public unsafe void Update(KeyboardInput keyState)
         {
-            ref ShMemKeyboard keyboard = ref _device.Hid.SharedMemory.Keyboard;
-
-            int currentIndex = UpdateEntriesHeader(ref keyboard.Header, out int previousIndex);
+            ref RingLifo<KeyboardState> lifo = ref _device.Hid.SharedMemory.Keyboard;
 
             if (!Active)
             {
+                lifo.Clear();
+
                 return;
             }
 
-            ref KeyboardState currentEntry = ref keyboard.Entries[currentIndex];
-            KeyboardState previousEntry = keyboard.Entries[previousIndex];
+            ref KeyboardState previousEntry = ref lifo.GetCurrentEntryRef();
 
-            currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1;
-            currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1;
-
-            for (int i = 0; i < 8; ++i)
+            KeyboardState newState = new KeyboardState
             {
-                currentEntry.Keys[i] = (uint)keyState.Keys[i];
-            }
+                SamplingNumber = previousEntry.SamplingNumber + 1,
+            };
 
-            currentEntry.Modifier = (ulong)keyState.Modifier;
+            keyState.Keys.AsSpan().CopyTo(newState.Keys.RawData.ToSpan());
+            newState.Modifiers = (KeyboardModifier)keyState.Modifier;
+
+            lifo.Write(ref newState);
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/MouseDevice.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/MouseDevice.cs
index ee58a563f8..e07c1d2068 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/MouseDevice.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/MouseDevice.cs
@@ -1,37 +1,35 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse;
+
 namespace Ryujinx.HLE.HOS.Services.Hid
 {
     public class MouseDevice : BaseDevice
     {
         public MouseDevice(Switch device, bool active) : base(device, active) { }
 
-        public void Update(int mouseX, int mouseY, int buttons = 0, int scrollX = 0, int scrollY = 0)
+        public void Update(int mouseX, int mouseY, uint buttons = 0, int scrollX = 0, int scrollY = 0)
         {
-            ref ShMemMouse mouse = ref _device.Hid.SharedMemory.Mouse;
+            ref RingLifo<MouseState> lifo = ref _device.Hid.SharedMemory.Mouse;
 
-            int currentIndex = UpdateEntriesHeader(ref mouse.Header, out int previousIndex);
-
-            if (!Active)
+            ref MouseState previousEntry = ref lifo.GetCurrentEntryRef();
+            
+            MouseState newState = new MouseState()
             {
-                return;
+                SamplingNumber = previousEntry.SamplingNumber + 1,
+            };
+
+            if (Active)
+            {
+                newState.Buttons = (MouseButton)buttons;
+                newState.X = mouseX;
+                newState.Y = mouseY;
+                newState.DeltaX = mouseX - previousEntry.DeltaX;
+                newState.DeltaY = mouseY - previousEntry.DeltaY;
+                newState.WheelDeltaX = scrollX;
+                newState.WheelDeltaY = scrollY;
             }
 
-            ref MouseState currentEntry = ref mouse.Entries[currentIndex];
-            MouseState previousEntry = mouse.Entries[previousIndex];
-
-            currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1;
-            currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1;
-
-            currentEntry.Buttons = (ulong)buttons;
-
-            currentEntry.Position = new MousePosition
-            {
-                X = mouseX,
-                Y = mouseY,
-                VelocityX = mouseX - previousEntry.Position.X,
-                VelocityY = mouseY - previousEntry.Position.Y,
-                ScrollVelocityX = scrollX,
-                ScrollVelocityY = scrollY
-            };
+            lifo.Write(ref newState);
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs
index 2150f278e8..3ff7e7338c 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs
@@ -1,16 +1,17 @@
 using System;
 using System.Collections.Generic;
+using System.Runtime.CompilerServices;
 using Ryujinx.Common;
 using Ryujinx.Common.Logging;
-using Ryujinx.Common.Memory;
 using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.HLE.HOS.Services.Hid.Types;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad;
 
 namespace Ryujinx.HLE.HOS.Services.Hid
 {
     public class NpadDevices : BaseDevice
     {
-        private const BatteryCharge DefaultBatteryCharge = BatteryCharge.Percent100;
-
         private const int NoMatchNotifyFrequencyMs = 2000;
         private int _activeCount;
         private long _lastNotifyTimestamp;
@@ -86,7 +87,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
                     continue;
                 }
 
-                ControllerType currentType = _device.Hid.SharedMemory.Npads[i].Header.Type;
+                ControllerType currentType = (ControllerType)_device.Hid.SharedMemory.Npads[i].InternalState.StyleSet;
 
                 if (currentType != ControllerType.None && (npad & acceptedTypes) != 0 && _supportedPlayers[i])
                 {
@@ -135,12 +136,24 @@ namespace Ryujinx.HLE.HOS.Services.Hid
         {
             Remap();
 
-            UpdateAllEntries();
+            Span<bool> updated = stackalloc bool[10];
 
             // Update configured inputs
             for (int i = 0; i < states.Count; ++i)
             {
-                UpdateInput(states[i]);
+                GamepadInput state = states[i];
+
+                updated[(int)state.PlayerId] = true;
+
+                UpdateInput(state);
+            }
+
+            for (int i = 0; i < updated.Length; i++)
+            {
+                if (!updated[i])
+                {
+                    UpdateDisconnectedInput((PlayerIndex)i);
+                }
             }
         }
 
@@ -185,16 +198,16 @@ namespace Ryujinx.HLE.HOS.Services.Hid
 
         private void SetupNpad(PlayerIndex player, ControllerType type)
         {
-            ref ShMemNpad controller = ref _device.Hid.SharedMemory.Npads[(int)player];
+            ref NpadInternalState controller = ref _device.Hid.SharedMemory.Npads[(int)player].InternalState;
 
-            ControllerType oldType = controller.Header.Type;
+            ControllerType oldType = (ControllerType)controller.StyleSet;
 
             if (oldType == type)
             {
                 return; // Already configured
             }
 
-            controller = new ShMemNpad(); // Zero it
+            controller = NpadInternalState.Create(); // Reset it
 
             if (type == ControllerType.None)
             {
@@ -207,87 +220,151 @@ namespace Ryujinx.HLE.HOS.Services.Hid
             }
 
             // TODO: Allow customizing colors at config
-            NpadStateHeader defaultHeader = new NpadStateHeader
-            {
-                IsHalf             = false,
-                SingleColorBody    = NpadColor.BodyGray,
-                SingleColorButtons = NpadColor.ButtonGray,
-                LeftColorBody      = NpadColor.BodyNeonBlue,
-                LeftColorButtons   = NpadColor.ButtonGray,
-                RightColorBody     = NpadColor.BodyNeonRed,
-                RightColorButtons  = NpadColor.ButtonGray
-            };
+            controller.JoyAssignmentMode = NpadJoyAssignmentMode.Dual;
+            controller.FullKeyColor.FullKeyBody = (uint)NpadColor.BodyGray;
+            controller.FullKeyColor.FullKeyButtons = (uint)NpadColor.ButtonGray;
+            controller.JoyColor.LeftBody = (uint)NpadColor.BodyNeonBlue;
+            controller.JoyColor.LeftButtons = (uint)NpadColor.ButtonGray;
+            controller.JoyColor.RightBody = (uint)NpadColor.BodyNeonRed;
+            controller.JoyColor.RightButtons = (uint)NpadColor.ButtonGray;
 
-            controller.SystemProperties = NpadSystemProperties.PowerInfo0Connected |
-                                          NpadSystemProperties.PowerInfo1Connected |
-                                          NpadSystemProperties.PowerInfo2Connected;
+            controller.SystemProperties = NpadSystemProperties.IsPoweredJoyDual |
+                                          NpadSystemProperties.IsPoweredJoyLeft |
+                                          NpadSystemProperties.IsPoweredJoyRight;
 
-            controller.BatteryState.ToSpan().Fill(DefaultBatteryCharge);
+            controller.BatteryLevelJoyDual = NpadBatteryLevel.Percent100;
+            controller.BatteryLevelJoyLeft = NpadBatteryLevel.Percent100;
+            controller.BatteryLevelJoyRight = NpadBatteryLevel.Percent100;
 
             switch (type)
             {
                 case ControllerType.ProController:
-                    defaultHeader.Type           = ControllerType.ProController;
+                    controller.StyleSet          = NpadStyleTag.FullKey;
                     controller.DeviceType        = DeviceType.FullKey;
-                    controller.SystemProperties |= NpadSystemProperties.AbxyButtonOriented |
-                                                   NpadSystemProperties.PlusButtonCapability |
-                                                   NpadSystemProperties.MinusButtonCapability;
+                    controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
+                                                   NpadSystemProperties.IsPlusAvailable      |
+                                                   NpadSystemProperties.IsMinusAvailable;
                     break;
                 case ControllerType.Handheld:
-                    defaultHeader.Type           = ControllerType.Handheld;
+                    controller.StyleSet          = NpadStyleTag.Handheld;
                     controller.DeviceType        = DeviceType.HandheldLeft |
                                                    DeviceType.HandheldRight;
-                    controller.SystemProperties |= NpadSystemProperties.AbxyButtonOriented |
-                                                   NpadSystemProperties.PlusButtonCapability |
-                                                   NpadSystemProperties.MinusButtonCapability;
+                    controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
+                                                   NpadSystemProperties.IsPlusAvailable      |
+                                                   NpadSystemProperties.IsMinusAvailable;
                     break;
                 case ControllerType.JoyconPair:
-                    defaultHeader.Type           = ControllerType.JoyconPair;
+                    controller.StyleSet          = NpadStyleTag.JoyDual;
                     controller.DeviceType        = DeviceType.JoyLeft |
                                                    DeviceType.JoyRight;
-                    controller.SystemProperties |= NpadSystemProperties.AbxyButtonOriented |
-                                                   NpadSystemProperties.PlusButtonCapability |
-                                                   NpadSystemProperties.MinusButtonCapability;
+                    controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
+                                                   NpadSystemProperties.IsPlusAvailable      |
+                                                   NpadSystemProperties.IsMinusAvailable;
                     break;
                 case ControllerType.JoyconLeft:
-                    defaultHeader.Type           = ControllerType.JoyconLeft;
-                    defaultHeader.IsHalf         = true;
+                    controller.StyleSet          = NpadStyleTag.JoyLeft;
+                    controller.JoyAssignmentMode = NpadJoyAssignmentMode.Single;
                     controller.DeviceType        = DeviceType.JoyLeft;
-                    controller.SystemProperties |= NpadSystemProperties.SlSrButtonOriented |
-                                                   NpadSystemProperties.MinusButtonCapability;
+                    controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented |
+                                                   NpadSystemProperties.IsMinusAvailable;
                     break;
                 case ControllerType.JoyconRight:
-                    defaultHeader.Type           = ControllerType.JoyconRight;
-                    defaultHeader.IsHalf         = true;
+                    controller.StyleSet          = NpadStyleTag.JoyRight;
+                    controller.JoyAssignmentMode = NpadJoyAssignmentMode.Single;
                     controller.DeviceType        = DeviceType.JoyRight;
-                    controller.SystemProperties |= NpadSystemProperties.SlSrButtonOriented |
-                                                   NpadSystemProperties.PlusButtonCapability;
+                    controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented |
+                                                   NpadSystemProperties.IsPlusAvailable;
                     break;
                 case ControllerType.Pokeball:
-                    defaultHeader.Type    = ControllerType.Pokeball;
+                    controller.StyleSet   = NpadStyleTag.Palma;
                     controller.DeviceType = DeviceType.Palma;
                     break;
             }
 
-            controller.Header = defaultHeader;
-
             _styleSetUpdateEvents[(int)player].ReadableEvent.Signal();
             _activeCount++;
 
             Logger.Info?.Print(LogClass.Hid, $"Connected Controller {type} to {player}");
         }
 
-        private static NpadLayoutsIndex ControllerTypeToNpadLayout(ControllerType controllerType)
-        => controllerType switch
+        private ref RingLifo<NpadCommonState> GetCommonStateLifo(ref NpadInternalState npad)
         {
-            ControllerType.ProController => NpadLayoutsIndex.ProController,
-            ControllerType.Handheld      => NpadLayoutsIndex.Handheld,
-            ControllerType.JoyconPair    => NpadLayoutsIndex.JoyDual,
-            ControllerType.JoyconLeft    => NpadLayoutsIndex.JoyLeft,
-            ControllerType.JoyconRight   => NpadLayoutsIndex.JoyRight,
-            ControllerType.Pokeball      => NpadLayoutsIndex.Pokeball,
-            _                            => NpadLayoutsIndex.SystemExternal
-        };
+            switch (npad.StyleSet)
+            {
+                case NpadStyleTag.FullKey:
+                    return ref npad.FullKey;
+                case NpadStyleTag.Handheld:
+                    return ref npad.Handheld;
+                case NpadStyleTag.JoyDual:
+                    return ref npad.JoyDual;
+                case NpadStyleTag.JoyLeft:
+                    return ref npad.JoyLeft;
+                case NpadStyleTag.JoyRight:
+                    return ref npad.JoyRight;
+                case NpadStyleTag.Palma:
+                    return ref npad.Palma;
+                default:
+                    return ref npad.SystemExt;
+            }
+        }
+
+        private void UpdateUnusedInputIfNotEqual(ref RingLifo<NpadCommonState> currentlyUsed, ref RingLifo<NpadCommonState> possiblyUnused)
+        {
+            bool isEquals;
+
+            unsafe
+            {
+                var aPointer = Unsafe.AsPointer(ref currentlyUsed);
+                var bPointer = Unsafe.AsPointer(ref possiblyUnused);
+
+                isEquals = aPointer == bPointer;
+            }
+
+            if (!isEquals)
+            {
+                NpadCommonState newState = new NpadCommonState();
+
+                WriteNewInputEntry(ref possiblyUnused, ref newState);
+            }
+        }
+
+        private void WriteNewInputEntry(ref RingLifo<NpadCommonState> lifo, ref NpadCommonState state)
+        {
+            ref NpadCommonState previousEntry = ref lifo.GetCurrentEntryRef();
+
+            state.SamplingNumber = previousEntry.SamplingNumber + 1;
+
+            lifo.Write(ref state);
+        }
+
+        private void UpdateUnusedSixInputIfNotEqual(ref RingLifo<SixAxisSensorState> currentlyUsed, ref RingLifo<SixAxisSensorState> possiblyUnused)
+        {
+            bool isEquals;
+
+            unsafe
+            {
+                var aPointer = Unsafe.AsPointer(ref currentlyUsed);
+                var bPointer = Unsafe.AsPointer(ref possiblyUnused);
+
+                isEquals = aPointer == bPointer;
+            }
+
+            if (!isEquals)
+            {
+                SixAxisSensorState newState = new SixAxisSensorState();
+
+                WriteNewSixInputEntry(ref possiblyUnused, ref newState);
+            }
+        }
+
+        private void WriteNewSixInputEntry(ref RingLifo<SixAxisSensorState> lifo, ref SixAxisSensorState state)
+        {
+            ref SixAxisSensorState previousEntry = ref lifo.GetCurrentEntryRef();
+
+            state.SamplingNumber = previousEntry.SamplingNumber + 1;
+
+            lifo.Write(ref state);
+        }
 
         private void UpdateInput(GamepadInput state)
         {
@@ -296,43 +373,88 @@ namespace Ryujinx.HLE.HOS.Services.Hid
                 return;
             }
 
-            ref ShMemNpad currentNpad = ref _device.Hid.SharedMemory.Npads[(int)state.PlayerId];
+            ref NpadInternalState currentNpad = ref _device.Hid.SharedMemory.Npads[(int)state.PlayerId].InternalState;
 
-            if (currentNpad.Header.Type == ControllerType.None)
+            if (currentNpad.StyleSet == NpadStyleTag.None)
             {
                 return;
             }
 
-            ref NpadLayout currentLayout = ref currentNpad.Layouts[(int)ControllerTypeToNpadLayout(currentNpad.Header.Type)];
-            ref NpadState  currentEntry  = ref currentLayout.Entries[(int)currentLayout.Header.LatestEntry];
+            ref RingLifo<NpadCommonState> lifo = ref GetCommonStateLifo(ref currentNpad);
 
-            currentEntry.Buttons = state.Buttons;
-            currentEntry.LStickX = state.LStick.Dx;
-            currentEntry.LStickY = state.LStick.Dy;
-            currentEntry.RStickX = state.RStick.Dx;
-            currentEntry.RStickY = state.RStick.Dy;
+            NpadCommonState newState = new NpadCommonState
+            {
+                Buttons      = (NpadButton)state.Buttons,
+                AnalogStickL = new AnalogStickState
+                {
+                    X        = state.LStick.Dx,
+                    Y        = state.LStick.Dy,
+                },
+                AnalogStickR = new AnalogStickState
+                {
+                    X        = state.RStick.Dx,
+                    Y        = state.RStick.Dy,
+                }
+            };
+
+            newState.Attributes = NpadAttribute.IsConnected;
+
+            switch (currentNpad.StyleSet)
+            {
+                case NpadStyleTag.Handheld:
+                case NpadStyleTag.FullKey:
+                    newState.Attributes |= NpadAttribute.IsWired;
+                    break;
+                case NpadStyleTag.JoyDual:
+                    newState.Attributes |= NpadAttribute.IsLeftConnected |
+                                           NpadAttribute.IsRightConnected;
+                    break;
+                case NpadStyleTag.JoyLeft:
+                    newState.Attributes |= NpadAttribute.IsLeftConnected;
+                    break;
+                case NpadStyleTag.JoyRight:
+                    newState.Attributes |= NpadAttribute.IsRightConnected;
+                    break;
+            }
+
+            WriteNewInputEntry(ref lifo, ref newState);
 
             // Mirror data to Default layout just in case
-            ref NpadLayout mainLayout = ref currentNpad.Layouts[(int)NpadLayoutsIndex.SystemExternal];
-            mainLayout.Entries[(int)mainLayout.Header.LatestEntry] = currentEntry;
+            if (!currentNpad.StyleSet.HasFlag(NpadStyleTag.SystemExt))
+            {
+                WriteNewInputEntry(ref currentNpad.SystemExt, ref newState);
+            }
+
+            UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.FullKey);
+            UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.Handheld);
+            UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.JoyDual);
+            UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.JoyLeft);
+            UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.JoyRight);
+            UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.Palma);
         }
 
-        private static SixAxixLayoutsIndex ControllerTypeToSixAxisLayout(ControllerType controllerType)
-        => controllerType switch
+        private void UpdateDisconnectedInput(PlayerIndex index)
         {
-            ControllerType.ProController => SixAxixLayoutsIndex.ProController,
-            ControllerType.Handheld      => SixAxixLayoutsIndex.Handheld,
-            ControllerType.JoyconPair    => SixAxixLayoutsIndex.JoyDualLeft,
-            ControllerType.JoyconLeft    => SixAxixLayoutsIndex.JoyLeft,
-            ControllerType.JoyconRight   => SixAxixLayoutsIndex.JoyRight,
-            ControllerType.Pokeball      => SixAxixLayoutsIndex.Pokeball,
-            _                            => SixAxixLayoutsIndex.SystemExternal
-        };
+            ref NpadInternalState currentNpad = ref _device.Hid.SharedMemory.Npads[(int)index].InternalState;
+
+            NpadCommonState newState = new NpadCommonState();
+
+            WriteNewInputEntry(ref currentNpad.FullKey, ref newState);
+            WriteNewInputEntry(ref currentNpad.Handheld, ref newState);
+            WriteNewInputEntry(ref currentNpad.JoyDual, ref newState);
+            WriteNewInputEntry(ref currentNpad.JoyLeft, ref newState);
+            WriteNewInputEntry(ref currentNpad.JoyRight, ref newState);
+            WriteNewInputEntry(ref currentNpad.Palma, ref newState);
+        }
 
         public void UpdateSixAxis(IList<SixAxisInput> states)
         {
+            Span<bool> updated = stackalloc bool[10];
+
             for (int i = 0; i < states.Count; ++i)
             {
+                updated[(int)states[i].PlayerId] = true;
+
                 if (SetSixAxisState(states[i]))
                 {
                     i++;
@@ -345,6 +467,40 @@ namespace Ryujinx.HLE.HOS.Services.Hid
                     SetSixAxisState(states[i], true);
                 }
             }
+
+            for (int i = 0; i < updated.Length; i++)
+            {
+                if (!updated[i])
+                {
+                    UpdateDisconnectedInputSixAxis((PlayerIndex)i);
+                }
+            }
+        }
+
+        private ref RingLifo<SixAxisSensorState> GetSixAxisSensorLifo(ref NpadInternalState npad, bool isRightPair)
+        {
+            switch (npad.StyleSet)
+            {
+                case NpadStyleTag.FullKey:
+                    return ref npad.FullKeySixAxisSensor;
+                case NpadStyleTag.Handheld:
+                    return ref npad.HandheldSixAxisSensor;
+                case NpadStyleTag.JoyDual:
+                    if (isRightPair)
+                    {
+                        return ref npad.JoyDualRightSixAxisSensor;
+                    }
+                    else
+                    {
+                        return ref npad.JoyDualSixAxisSensor;
+                    }
+                case NpadStyleTag.JoyLeft:
+                    return ref npad.JoyLeftSixAxisSensor;
+                case NpadStyleTag.JoyRight:
+                    return ref npad.JoyRightSixAxisSensor;
+                default:
+                    throw new NotImplementedException($"{npad.StyleSet}");
+            }
         }
 
         private bool SetSixAxisState(SixAxisInput state, bool isRightPair = false)
@@ -354,9 +510,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid
                 return false;
             }
 
-            ref ShMemNpad currentNpad = ref _device.Hid.SharedMemory.Npads[(int)state.PlayerId];
+            ref NpadInternalState currentNpad = ref _device.Hid.SharedMemory.Npads[(int)state.PlayerId].InternalState;
 
-            if (currentNpad.Header.Type == ControllerType.None)
+            if (currentNpad.StyleSet == NpadStyleTag.None)
             {
                 return false;
             }
@@ -382,87 +538,57 @@ namespace Ryujinx.HLE.HOS.Services.Hid
                 Z = state.Rotation.Z
             };
 
-            ref NpadSixAxis currentLayout = ref currentNpad.Sixaxis[(int)ControllerTypeToSixAxisLayout(currentNpad.Header.Type) + (isRightPair ? 1 : 0)];
-            ref SixAxisState currentEntry = ref currentLayout.Entries[(int)currentLayout.Header.LatestEntry];
-
-            int previousEntryIndex = (int)(currentLayout.Header.LatestEntry == 0 ?
-                                           currentLayout.Header.MaxEntryIndex : currentLayout.Header.LatestEntry - 1);
-
-            ref SixAxisState previousEntry = ref currentLayout.Entries[previousEntryIndex];
-
-            currentEntry.Accelerometer = accel;
-            currentEntry.Gyroscope     = gyro;
-            currentEntry.Rotations     = rotation;
-
-            unsafe
+            SixAxisSensorState newState = new SixAxisSensorState
             {
-                for (int i = 0; i < 9; i++)
-                {
-                    currentEntry.Orientation[i] = state.Orientation[i];
-                }
+                Acceleration    = accel,
+                AngularVelocity = gyro,
+                Angle           = rotation,
+                Attributes      = SixAxisSensorAttribute.IsConnected
+            };
+
+            state.Orientation.AsSpan().CopyTo(newState.Direction.ToSpan());
+
+            ref RingLifo<SixAxisSensorState> lifo = ref GetSixAxisSensorLifo(ref currentNpad, isRightPair);
+
+            WriteNewSixInputEntry(ref lifo, ref newState);
+
+            bool needUpdateRight = currentNpad.StyleSet == NpadStyleTag.JoyDual && !isRightPair;
+
+            if (!isRightPair)
+            {
+                UpdateUnusedSixInputIfNotEqual(ref lifo, ref currentNpad.FullKeySixAxisSensor);
+                UpdateUnusedSixInputIfNotEqual(ref lifo, ref currentNpad.HandheldSixAxisSensor);
+                UpdateUnusedSixInputIfNotEqual(ref lifo, ref currentNpad.JoyDualSixAxisSensor);
+                UpdateUnusedSixInputIfNotEqual(ref lifo, ref currentNpad.JoyLeftSixAxisSensor);
+                UpdateUnusedSixInputIfNotEqual(ref lifo, ref currentNpad.JoyRightSixAxisSensor);
             }
 
-            return currentNpad.Header.Type == ControllerType.JoyconPair && !isRightPair;
+            if (!needUpdateRight)
+            {
+                SixAxisSensorState emptyState = new SixAxisSensorState();
+
+                emptyState.Attributes = SixAxisSensorAttribute.IsConnected;
+
+                WriteNewSixInputEntry(ref currentNpad.JoyDualRightSixAxisSensor, ref emptyState);
+            }
+
+            return needUpdateRight;
         }
 
-        private void UpdateAllEntries()
+        private void UpdateDisconnectedInputSixAxis(PlayerIndex index)
         {
-            ref Array10<ShMemNpad> controllers = ref _device.Hid.SharedMemory.Npads;
-            for (int i = 0; i < controllers.Length; ++i)
-            {
-                ref Array7<NpadLayout> layouts = ref controllers[i].Layouts;
-                for (int l = 0; l < layouts.Length; ++l)
-                {
-                    ref NpadLayout currentLayout = ref layouts[l];
-                    int currentIndex = UpdateEntriesHeader(ref currentLayout.Header, out int previousIndex);
+            ref NpadInternalState currentNpad = ref _device.Hid.SharedMemory.Npads[(int)index].InternalState;
 
-                    ref NpadState currentEntry = ref currentLayout.Entries[currentIndex];
-                    NpadState previousEntry    = currentLayout.Entries[previousIndex];
+            SixAxisSensorState newState = new SixAxisSensorState();
 
-                    currentEntry.SampleTimestamp  = previousEntry.SampleTimestamp + 1;
-                    currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1;
+            newState.Attributes = SixAxisSensorAttribute.IsConnected;
 
-                    if (controllers[i].Header.Type == ControllerType.None)
-                    {
-                        continue;
-                    }
-
-                    currentEntry.ConnectionState = NpadConnectionState.ControllerStateConnected;
-
-                    switch (controllers[i].Header.Type)
-                    {
-                        case ControllerType.Handheld:
-                        case ControllerType.ProController:
-                            currentEntry.ConnectionState |= NpadConnectionState.ControllerStateWired;
-                            break;
-                        case ControllerType.JoyconPair:
-                            currentEntry.ConnectionState |= NpadConnectionState.JoyLeftConnected |
-                                                            NpadConnectionState.JoyRightConnected;
-                            break;
-                        case ControllerType.JoyconLeft:
-                            currentEntry.ConnectionState |= NpadConnectionState.JoyLeftConnected;
-                            break;
-                        case ControllerType.JoyconRight:
-                            currentEntry.ConnectionState |= NpadConnectionState.JoyRightConnected;
-                            break;
-                    }
-                }
-
-                ref Array6<NpadSixAxis> sixaxis = ref controllers[i].Sixaxis;
-                for (int l = 0; l < sixaxis.Length; ++l)
-                {
-                    ref NpadSixAxis currentLayout = ref sixaxis[l];
-                    int currentIndex = UpdateEntriesHeader(ref currentLayout.Header, out int previousIndex);
-
-                    ref SixAxisState currentEntry = ref currentLayout.Entries[currentIndex];
-                    SixAxisState previousEntry = currentLayout.Entries[previousIndex];
-
-                    currentEntry.SampleTimestamp  = previousEntry.SampleTimestamp + 1;
-                    currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1;
-
-                    currentEntry._unknown2 = 1;
-                }
-            }
+            WriteNewSixInputEntry(ref currentNpad.FullKeySixAxisSensor, ref newState);
+            WriteNewSixInputEntry(ref currentNpad.HandheldSixAxisSensor, ref newState);
+            WriteNewSixInputEntry(ref currentNpad.JoyDualSixAxisSensor, ref newState);
+            WriteNewSixInputEntry(ref currentNpad.JoyDualRightSixAxisSensor, ref newState);
+            WriteNewSixInputEntry(ref currentNpad.JoyLeftSixAxisSensor, ref newState);
+            WriteNewSixInputEntry(ref currentNpad.JoyRightSixAxisSensor, ref newState);
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/TouchDevice.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/TouchDevice.cs
index 10c3445304..432a37e337 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/TouchDevice.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/TouchDevice.cs
@@ -1,3 +1,5 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.TouchScreen;
 using System;
 
 namespace Ryujinx.HLE.HOS.Services.Hid
@@ -8,39 +10,38 @@ namespace Ryujinx.HLE.HOS.Services.Hid
 
         public void Update(params TouchPoint[] points)
         {
-            ref ShMemTouchScreen touchscreen = ref _device.Hid.SharedMemory.TouchScreen;
+            ref RingLifo<TouchScreenState> lifo = ref _device.Hid.SharedMemory.TouchScreen;
 
-            int currentIndex = UpdateEntriesHeader(ref touchscreen.Header, out int previousIndex);
+            ref TouchScreenState previousEntry = ref lifo.GetCurrentEntryRef();
 
-            if (!Active)
+            TouchScreenState newState = new TouchScreenState
             {
-                return;
-            }
+                SamplingNumber = previousEntry.SamplingNumber + 1
+            };
 
-            ref TouchScreenState currentEntry = ref touchscreen.Entries[currentIndex];
-            TouchScreenState previousEntry = touchscreen.Entries[previousIndex];
-
-            currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1;
-            currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1;
-
-            currentEntry.NumTouches = (ulong)points.Length;
-
-            int pointsLength = Math.Min(points.Length, currentEntry.Touches.Length);
-
-            for (int i = 0; i < pointsLength; ++i)
+            if (Active)
             {
-                TouchPoint pi = points[i];
-                currentEntry.Touches[i] = new TouchScreenStateData
+                newState.TouchesCount = points.Length;
+
+                int pointsLength = Math.Min(points.Length, newState.Touches.Length);
+
+                for (int i = 0; i < pointsLength; ++i)
                 {
-                    SampleTimestamp = currentEntry.SampleTimestamp,
-                    X = pi.X,
-                    Y = pi.Y,
-                    TouchIndex = (uint)i,
-                    DiameterX = pi.DiameterX,
-                    DiameterY = pi.DiameterY,
-                    Angle = pi.Angle
-                };
+                    TouchPoint pi = points[i];
+                    newState.Touches[i] = new TouchState
+                    {
+                        DeltaTime = newState.SamplingNumber,
+                        X = pi.X,
+                        Y = pi.Y,
+                        FingerId = (uint)i,
+                        DiameterX = pi.DiameterX,
+                        DiameterY = pi.DiameterY,
+                        RotationAngle = pi.Angle
+                    };
+                }
             }
+
+            lifo.Write(ref newState);
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/KeyboardInput.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/KeyboardInput.cs
index 2668127092..be6857fb34 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/KeyboardInput.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/KeyboardInput.cs
@@ -3,6 +3,6 @@ namespace Ryujinx.HLE.HOS.Services.Hid
     public struct KeyboardInput
     {
         public int Modifier;
-        public int[] Keys;
+        public ulong[] Keys;
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
index 2ab305ac69..e3c22edf69 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
@@ -3,6 +3,7 @@ using Ryujinx.HLE.HOS.Ipc;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Services.Hid.HidServer;
+using Ryujinx.HLE.HOS.Services.Hid.Types;
 using System;
 using System.Collections.Generic;
 using System.Runtime.InteropServices;
@@ -134,7 +135,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
             // Initialize entries to avoid issues with some games.
 
             KeyboardInput emptyInput = new KeyboardInput();
-            emptyInput.Keys = new int[8];
+            emptyInput.Keys = new ulong[4];
 
             for (int entry = 0; entry < Hid.SharedMemEntryCount; entry++)
             {
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/Boolean32.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/Boolean32.cs
deleted file mode 100644
index 5a8d51c6e3..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/Boolean32.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    struct Boolean32
-    {
-        private uint _value;
-        public static implicit operator bool(Boolean32 value) => (value._value & 1) != 0;
-        public static implicit operator Boolean32(bool value) => new Boolean32() { _value = value ? 1u : 0u };
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/HidVector.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/HidVector.cs
similarity index 70%
rename from Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/HidVector.cs
rename to Ryujinx.HLE/HOS/Services/Hid/Types/HidVector.cs
index b41bcb2e8e..18d9fd9c9c 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/HidVector.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/HidVector.cs
@@ -1,4 +1,4 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
+namespace Ryujinx.HLE.HOS.Services.Hid.Types
 {
     struct HidVector
     {
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/NpadColor.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/NpadColor.cs
index 57b4b36669..3c311e218b 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/NpadColor.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/NpadColor.cs
@@ -1,6 +1,6 @@
 namespace Ryujinx.HLE.HOS.Services.Hid
 {
-    public enum NpadColor : int 
+    public enum NpadColor : uint 
     {
         BodyGray                                      = 0x828282,
         BodyNeonRed                                   = 0xFF3C28,
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadJoyHoldType.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/NpadJoyHoldType.cs
similarity index 60%
rename from Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadJoyHoldType.cs
rename to Ryujinx.HLE/HOS/Services/Hid/Types/NpadJoyHoldType.cs
index a6f2976065..d3b51a24c5 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadJoyHoldType.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/NpadJoyHoldType.cs
@@ -1,8 +1,8 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
+namespace Ryujinx.HLE.HOS.Services.Hid.Types
 {
     enum NpadJoyHoldType
     {
         Vertical,
         Horizontal
     }
-}
\ No newline at end of file
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/CommonEntriesHeader.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/CommonEntriesHeader.cs
deleted file mode 100644
index f83fdcdf52..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/CommonEntriesHeader.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    struct CommonEntriesHeader
-    {
-        public ulong TimestampTicks;
-        public ulong NumEntries;
-        public ulong LatestEntry;
-        public ulong MaxEntryIndex;
-    }
-}
-
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPad.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPad.cs
deleted file mode 100644
index 3fbaa304ca..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPad.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Ryujinx.Common.Memory;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    unsafe struct ShMemDebugPad
-    {
-        public CommonEntriesHeader Header;
-        public Array17<DebugPadEntry> Entries;
-        fixed byte _padding[0x138];
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPadEntry.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPadEntry.cs
deleted file mode 100644
index 3089fc5b1d..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPadEntry.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    unsafe struct DebugPadEntry
-    {
-        public ulong SampleTimestamp;
-        public ulong SampleTimestamp2;
-        fixed byte _unknown[0x18];
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/HidSharedMemory.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/HidSharedMemory.cs
deleted file mode 100644
index d950425d9a..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/HidSharedMemory.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using Ryujinx.Common.Memory;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    // TODO: Add missing structs
-    unsafe struct HidSharedMemory
-    {
-        public ShMemDebugPad DebugPad;
-        public ShMemTouchScreen TouchScreen;
-        public ShMemMouse Mouse;
-        public ShMemKeyboard Keyboard;
-        public fixed byte BasicXpad[0x4 * 0x400];
-        public fixed byte HomeButton[0x200];
-        public fixed byte SleepButton[0x200];
-        public fixed byte CaptureButton[0x200];
-        public fixed byte InputDetector[0x10 * 0x80];
-        public fixed byte UniquePad[0x10 * 0x400];
-        public Array10<ShMemNpad> Npads;
-        public fixed byte Gesture[0x800];
-        public fixed byte ConsoleSixAxisSensor[0x20];
-        fixed byte _padding[0x3de0];
-    }
-}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/Keyboard.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/Keyboard.cs
deleted file mode 100644
index e2c1844f4a..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/Keyboard.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Ryujinx.Common.Memory;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    unsafe struct ShMemKeyboard
-    {
-        public CommonEntriesHeader Header;
-        public Array17<KeyboardState> Entries;
-        fixed byte _padding[0x28];
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/KeyboardState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/KeyboardState.cs
deleted file mode 100644
index 1f54a4fd57..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/KeyboardState.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    unsafe struct KeyboardState
-    {
-        public ulong SampleTimestamp;
-        public ulong SampleTimestamp2;
-        public ulong Modifier;
-        public fixed uint Keys[8];
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/Mouse.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/Mouse.cs
deleted file mode 100644
index 6b99e04a84..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/Mouse.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-
-using Ryujinx.Common.Memory;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    unsafe struct ShMemMouse
-    {
-        public CommonEntriesHeader Header;
-        public Array17<MouseState> Entries;
-        fixed byte _padding[0xB0];
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/MousePosition.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/MousePosition.cs
deleted file mode 100644
index e94c9e0cd8..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/MousePosition.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    struct MousePosition
-    {
-        public int X;
-        public int Y;
-        public int VelocityX;
-        public int VelocityY;
-        public int ScrollVelocityX;
-        public int ScrollVelocityY;
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/MouseState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/MouseState.cs
deleted file mode 100644
index 7856b09d2d..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/MouseState.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    struct MouseState
-    {
-        public ulong SampleTimestamp;
-        public ulong SampleTimestamp2;
-        public MousePosition Position;
-        public ulong Buttons;
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/BatterCharge.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/BatterCharge.cs
deleted file mode 100644
index b94ab172c0..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/BatterCharge.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    enum BatteryCharge : int
-    {
-        Percent0 = 0,
-        Percent25 = 1,
-        Percent50 = 2,
-        Percent75 = 3,
-        Percent100 = 4
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/DeviceType.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/DeviceType.cs
deleted file mode 100644
index f6d7b783c7..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/DeviceType.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    [Flags]
-    enum DeviceType : int
-    {
-        FullKey = 1 << 0,
-        DebugPad = 1 << 1,
-        HandheldLeft = 1 << 2,
-        HandheldRight = 1 << 3,
-        JoyLeft = 1 << 4,
-        JoyRight = 1 << 5,
-        Palma = 1 << 6, // Poké Ball Plus
-        FamicomLeft = 1 << 7,
-        FamicomRight = 1 << 8,
-        NESLeft = 1 << 9,
-        NESRight = 1 << 10,
-        HandheldFamicomLeft = 1 << 11,
-        HandheldFamicomRight = 1 << 12,
-        HandheldNESLeft = 1 << 13,
-        HandheldNESRight = 1 << 14,
-        Lucia = 1 << 15,
-        System = 1 << 31
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/Npad.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/Npad.cs
deleted file mode 100644
index 4ef83f3d13..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/Npad.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using Ryujinx.Common.Memory;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    // TODO: Add missing structs
-    unsafe struct ShMemNpad
-    {
-        public NpadStateHeader Header;
-        public Array7<NpadLayout> Layouts; // One for each NpadLayoutsIndex
-        public Array6<NpadSixAxis> Sixaxis;
-        public DeviceType DeviceType;
-        uint _padding1;
-        public NpadSystemProperties SystemProperties;
-        public uint NpadSystemButtonProperties;
-        public Array3<BatteryCharge> BatteryState;
-        public fixed byte NfcXcdDeviceHandleHeader[0x20];
-        public fixed byte NfcXcdDeviceHandleState[0x20 * 2];
-        public ulong Mutex;
-        public fixed byte NpadGcTriggerHeader[0x20];
-        public fixed byte NpadGcTriggerState[0x18 * 17];
-        fixed byte _padding2[0xC38];
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadColorDescription.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadColorDescription.cs
deleted file mode 100644
index ccc7cb8df8..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadColorDescription.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    [Flags]
-    enum NpadColorDescription : int
-    {
-        ColorDescriptionColorsNonexistent = (1 << 1)
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadConnectionState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadConnectionState.cs
deleted file mode 100644
index 60f64fd37c..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadConnectionState.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    [Flags]
-    enum NpadConnectionState : long
-    {
-        ControllerStateConnected = (1 << 0),
-        ControllerStateWired = (1 << 1),
-        JoyLeftConnected = (1 << 2),
-        JoyRightConnected = (1 << 4)
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayout.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayout.cs
deleted file mode 100644
index 24c4f4d44f..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayout.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using Ryujinx.Common.Memory;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    struct NpadLayout
-    {
-        public CommonEntriesHeader Header;
-        public Array17<NpadState> Entries;
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayoutsIndex.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayoutsIndex.cs
deleted file mode 100644
index c44193369d..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayoutsIndex.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    enum NpadLayoutsIndex : int
-    {
-        ProController  = 0,
-        Handheld       = 1,
-        JoyDual        = 2,
-        JoyLeft        = 3,
-        JoyRight       = 4,
-        Pokeball       = 5,
-        SystemExternal = 6
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSixAxis.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSixAxis.cs
deleted file mode 100644
index a0a39fdca9..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSixAxis.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using Ryujinx.Common.Memory;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    struct NpadSixAxis
-    {
-        public CommonEntriesHeader Header;
-        public Array17<SixAxisState> Entries;
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadState.cs
deleted file mode 100644
index 60a5f9d36d..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadState.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    struct NpadState
-    {
-        public ulong SampleTimestamp;
-        public ulong SampleTimestamp2;
-        public ControllerKeys Buttons;
-        public int LStickX;
-        public int LStickY;
-        public int RStickX;
-        public int RStickY;
-        public NpadConnectionState ConnectionState;
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadStatesHeader.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadStatesHeader.cs
deleted file mode 100644
index 006d4357f4..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadStatesHeader.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    struct NpadStateHeader
-    {
-        public ControllerType Type;
-        public Boolean32 IsHalf;
-        public NpadColorDescription SingleColorsDescriptor;
-        public NpadColor SingleColorBody;
-        public NpadColor SingleColorButtons;
-        public NpadColorDescription SplitColorsDescriptor;
-        public NpadColor LeftColorBody;
-        public NpadColor LeftColorButtons;
-        public NpadColor RightColorBody;
-        public NpadColor RightColorButtons;
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSystemProperties.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSystemProperties.cs
deleted file mode 100644
index 708f7da9c4..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSystemProperties.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    [Flags]
-    enum NpadSystemProperties : long
-    {
-        PowerInfo0Charging = 1 << 0,
-        PowerInfo1Charging = 1 << 1,
-        PowerInfo2Charging = 1 << 2,
-        PowerInfo0Connected = 1 << 3,
-        PowerInfo1Connected = 1 << 4,
-        PowerInfo2Connected = 1 << 5,
-        UnsupportedButtonPressedNpadSystem = 1 << 9,
-        UnsupportedButtonPressedNpadSystemExt = 1 << 10,
-        AbxyButtonOriented = 1 << 11,
-        SlSrButtonOriented = 1 << 12,
-        PlusButtonCapability = 1 << 13,
-        MinusButtonCapability = 1 << 14,
-        DirectionalButtonsSupported = 1 << 15
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/SixAxisLayoutsIndex.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/SixAxisLayoutsIndex.cs
deleted file mode 100644
index a8795fc05b..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/SixAxisLayoutsIndex.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    enum SixAxixLayoutsIndex : int
-    {
-        ProController  = 0,
-        Handheld       = 1,
-        JoyDualLeft    = 2,
-        JoyDualRight   = 3,
-        JoyLeft        = 4,
-        JoyRight       = 5,
-        Pokeball       = 6,
-        SystemExternal = 7
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/SixAxisState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/SixAxisState.cs
deleted file mode 100644
index 12974e7e31..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/SixAxisState.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    unsafe struct SixAxisState
-    {
-        public ulong SampleTimestamp;
-        ulong _unknown1;
-        public ulong SampleTimestamp2;
-        public HidVector Accelerometer;
-        public HidVector Gyroscope;
-        public HidVector Rotations;
-        public fixed float Orientation[9];
-        public ulong _unknown2;
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreen.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreen.cs
deleted file mode 100644
index 5f12295cf1..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreen.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Ryujinx.Common.Memory;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    unsafe struct ShMemTouchScreen
-    {
-        public CommonEntriesHeader Header;
-        public Array17<TouchScreenState> Entries;
-        fixed byte _padding[0x3c8];
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenState.cs
deleted file mode 100644
index 1c85e29148..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenState.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using Ryujinx.Common.Memory;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    struct TouchScreenState
-    {
-        public ulong SampleTimestamp;
-        public ulong SampleTimestamp2;
-        public ulong NumTouches;
-        public Array16<TouchScreenStateData> Touches;
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenStateData.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenStateData.cs
deleted file mode 100644
index 4d4c48d1a2..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenStateData.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-    struct TouchScreenStateData
-    {
-        public ulong SampleTimestamp;
-#pragma warning disable CS0169
-        uint _padding;
-#pragma warning restore CS0169
-        public uint TouchIndex;
-        public uint X;
-        public uint Y;
-        public uint DiameterX;
-        public uint DiameterY;
-        public uint Angle;
-#pragma warning disable CS0169
-        uint _padding2;
-#pragma warning restore CS0169
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AnalogStickState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AnalogStickState.cs
new file mode 100644
index 0000000000..bf4b588855
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AnalogStickState.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
+{
+    struct AnalogStickState
+    {
+        public int X;
+        public int Y;
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AtomicStorage.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AtomicStorage.cs
new file mode 100644
index 0000000000..45b92ba98f
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AtomicStorage.cs
@@ -0,0 +1,26 @@
+using System.Threading;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
+{
+    struct AtomicStorage<T> where T: unmanaged
+    {
+        public ulong SamplingNumber;
+        public T Object;
+
+        public ulong ReadSamplingNumberAtomic()
+        {
+            return Interlocked.Read(ref SamplingNumber);
+        }
+
+        public void SetObject(ref T obj)
+        {
+            ISampledData samplingProvider = obj as ISampledData;
+
+            Interlocked.Exchange(ref SamplingNumber, samplingProvider.SamplingNumber);
+
+            Thread.MemoryBarrier();
+
+            Object = obj;
+        }
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledData.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledData.cs
new file mode 100644
index 0000000000..08f76747e1
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledData.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
+{
+    interface ISampledData
+    {
+        ulong SamplingNumber { get; }
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs
new file mode 100644
index 0000000000..615e389303
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs
@@ -0,0 +1,149 @@
+using Ryujinx.Common.Memory;
+using System;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
+{
+    struct RingLifo<T> where T: unmanaged
+    {
+        private const ulong MaxEntries = 17;
+
+#pragma warning disable CS0169
+        private ulong _unused;
+#pragma warning restore CS0169
+#pragma warning disable CS0414
+        private ulong _bufferCount;
+#pragma warning restore CS0414
+        private ulong _index;
+        private ulong _count;
+        private Array17<AtomicStorage<T>> _storage;
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private ulong ReadCurrentIndex()
+        {
+            return Interlocked.Read(ref _index);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private ulong ReadCurrentCount()
+        {
+            return Interlocked.Read(ref _count);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static ulong GetNextIndexForWrite(ulong index)
+        {
+            return (index + 1) % MaxEntries;
+        }
+
+        public ref AtomicStorage<T> GetCurrentAtomicEntryRef()
+        {
+            ulong countAvailaible = Math.Min(Math.Max(0, ReadCurrentCount()), 1);
+
+            if (countAvailaible == 0)
+            {
+                _storage[0] = default;
+
+                return ref _storage[0];
+            }
+
+            ulong index = ReadCurrentIndex();
+
+            while (true)
+            {
+                int inputEntryIndex = (int)((index + MaxEntries + 1 - countAvailaible) % MaxEntries);
+
+                ref AtomicStorage<T> result = ref _storage[inputEntryIndex];
+
+                ulong samplingNumber0 = result.ReadSamplingNumberAtomic();
+                ulong samplingNumber1 = result.ReadSamplingNumberAtomic();
+
+                if (samplingNumber0 != samplingNumber1 && (result.SamplingNumber - result.SamplingNumber) != 1)
+                {
+                    ulong tempCount = Math.Min(ReadCurrentCount(), countAvailaible);
+
+                    countAvailaible = Math.Min(tempCount, 1);
+                    index = ReadCurrentIndex();
+
+                    continue;
+                }
+
+                return ref result;
+            }
+        }
+
+        public ref T GetCurrentEntryRef()
+        {
+            return ref GetCurrentAtomicEntryRef().Object;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public ReadOnlySpan<AtomicStorage<T>> ReadEntries(uint maxCount)
+        {
+            ulong countAvailaible = Math.Min(Math.Max(0, ReadCurrentCount()), maxCount);
+
+            if (countAvailaible == 0)
+            {
+                return ReadOnlySpan<AtomicStorage<T>>.Empty;
+            }
+
+            ulong index = ReadCurrentIndex();
+
+            AtomicStorage<T>[] result = new AtomicStorage<T>[countAvailaible];
+
+            for (ulong i = 0; i < countAvailaible; i++)
+            {
+                int inputEntryIndex = (int)((index + MaxEntries + 1 - countAvailaible + i) % MaxEntries);
+                int outputEntryIndex = (int)(countAvailaible - i - 1);
+
+                ulong samplingNumber0 = _storage[inputEntryIndex].ReadSamplingNumberAtomic();
+                result[outputEntryIndex] = _storage[inputEntryIndex];
+                ulong samplingNumber1 = _storage[inputEntryIndex].ReadSamplingNumberAtomic();
+
+                if (samplingNumber0 != samplingNumber1 && (i > 0 && (result[outputEntryIndex].SamplingNumber - result[outputEntryIndex].SamplingNumber) != 1))
+                {
+                    ulong tempCount = Math.Min(ReadCurrentCount(), countAvailaible);
+
+                    countAvailaible = Math.Min(tempCount, maxCount);
+                    index = ReadCurrentIndex();
+
+                    i -= 1;
+                }
+            }
+
+            return result;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Write(ref T value)
+        {
+            ulong targetIndex = GetNextIndexForWrite(ReadCurrentIndex());
+
+            _storage[(int)targetIndex].SetObject(ref value);
+
+            Interlocked.Exchange(ref _index, targetIndex);
+
+            ulong count = ReadCurrentCount();
+
+            if (count < (MaxEntries - 1))
+            {
+                Interlocked.Increment(ref _count);
+            }
+        }
+
+        public void Clear()
+        {
+            Interlocked.Exchange(ref _count, 0);
+            Interlocked.Exchange(ref _index, 0);
+        }
+
+        public static RingLifo<T> Create()
+        {
+            return new RingLifo<T>
+            {
+                _bufferCount = MaxEntries
+            };
+        }
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadAttribute.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadAttribute.cs
new file mode 100644
index 0000000000..ec5bd3c882
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadAttribute.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugPad
+{
+    [Flags]
+    enum DebugPadAttribute : uint
+    {
+        None = 0,
+        Connected = 1 << 0
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadButton.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadButton.cs
new file mode 100644
index 0000000000..e8f2831707
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadButton.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugPad
+{
+    [Flags]
+    enum DebugPadButton : uint
+    {
+        None = 0,
+        A = 1 << 0,
+        B = 1 << 1,
+        X = 1 << 2,
+        Y = 1 << 3,
+        L = 1 << 4,
+        R = 1 << 5,
+        ZL = 1 << 6,
+        ZR = 1 << 7,
+        Start = 1 << 8,
+        Select = 1 << 9,
+        Left = 1 << 10,
+        Up = 1 << 11,
+        Right = 1 << 12,
+        Down = 1 << 13
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadState.cs
new file mode 100644
index 0000000000..3e1e1ad8e7
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadState.cs
@@ -0,0 +1,15 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugPad
+{
+    struct DebugPadState : ISampledData
+    {
+        public ulong SamplingNumber;
+        public DebugPadAttribute Attributes;
+        public DebugPadButton Buttons;
+        public AnalogStickState AnalogStickR;
+        public AnalogStickState AnalogStickL;
+
+        ulong ISampledData.SamplingNumber => SamplingNumber;
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardKey.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardKey.cs
new file mode 100644
index 0000000000..22df7c7914
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardKey.cs
@@ -0,0 +1,29 @@
+using Ryujinx.Common.Memory;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard
+{
+    struct KeyboardKey
+    {
+        public Array4<ulong> RawData;
+
+        public bool this[KeyboardKeyShift index]
+        {
+            get
+            {
+                return (RawData[(int)index / 64] & (1UL << ((int)index & 63))) != 0;
+            }
+            set
+            {
+                int arrayIndex = (int)index / 64;
+                ulong mask = 1UL << ((int)index & 63);
+
+                RawData[arrayIndex] &= ~mask;
+
+                if (value)
+                {
+                    RawData[arrayIndex] |= mask;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardKeyShift.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardKeyShift.cs
new file mode 100644
index 0000000000..01c2bb3045
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardKeyShift.cs
@@ -0,0 +1,138 @@
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard
+{
+    enum KeyboardKeyShift
+    {
+        A = 4,
+        B = 5,
+        C = 6,
+        D = 7,
+        E = 8,
+        F = 9,
+        G = 10,
+        H = 11,
+        I = 12,
+        J = 13,
+        K = 14,
+        L = 15,
+        M = 16,
+        N = 17,
+        O = 18,
+        P = 19,
+        Q = 20,
+        R = 21,
+        S = 22,
+        T = 23,
+        U = 24,
+        V = 25,
+        W = 26,
+        X = 27,
+        Y = 28,
+        Z = 29,
+        D1 = 30,
+        D2 = 31,
+        D3 = 32,
+        D4 = 33,
+        D5 = 34,
+        D6 = 35,
+        D7 = 36,
+        D8 = 37,
+        D9 = 38,
+        D0 = 39,
+        Return = 40,
+        Escape = 41,
+        Backspace = 42,
+        Tab = 43,
+        Space = 44,
+        Minus = 45,
+        Plus = 46,
+        OpenBracket = 47,
+        CloseBracket = 48,
+        Pipe = 49,
+        Tilde = 50,
+        Semicolon = 51,
+        Quote = 52,
+        Backquote = 53,
+        Comma = 54,
+        Period = 55,
+        Slash = 56,
+        CapsLock = 57,
+        F1 = 58,
+        F2 = 59,
+        F3 = 60,
+        F4 = 61,
+        F5 = 62,
+        F6 = 63,
+        F7 = 64,
+        F8 = 65,
+        F9 = 66,
+        F10 = 67,
+        F11 = 68,
+        F12 = 69,
+        PrintScreen = 70,
+        ScrollLock = 71,
+        Pause = 72,
+        Insert = 73,
+        Home = 74,
+        PageUp = 75,
+        Delete = 76,
+        End = 77,
+        PageDown = 78,
+        RightArrow = 79,
+        LeftArrow = 80,
+        DownArrow = 81,
+        UpArrow = 82,
+        NumLock = 83,
+        NumPadDivide = 84,
+        NumPadMultiply = 85,
+        NumPadSubtract = 86,
+        NumPadAdd = 87,
+        NumPadEnter = 88,
+        NumPad1 = 89,
+        NumPad2 = 90,
+        NumPad3 = 91,
+        NumPad4 = 92,
+        NumPad5 = 93,
+        NumPad6 = 94,
+        NumPad7 = 95,
+        NumPad8 = 96,
+        NumPad9 = 97,
+        NumPad0 = 98,
+        NumPadDot = 99,
+        Backslash = 100,
+        Application = 101,
+        Power = 102,
+        NumPadEquals = 103,
+        F13 = 104,
+        F14 = 105,
+        F15 = 106,
+        F16 = 107,
+        F17 = 108,
+        F18 = 109,
+        F19 = 110,
+        F20 = 111,
+        F21 = 112,
+        F22 = 113,
+        F23 = 114,
+        F24 = 115,
+        NumPadComma = 133,
+        Ro = 135,
+        KatakanaHiragana = 136,
+        Yen = 137,
+        Henkan = 138,
+        Muhenkan = 139,
+        NumPadCommaPc98 = 140,
+        HangulEnglish = 144,
+        Hanja = 145,
+        Katakana = 146,
+        Hiragana = 147,
+        ZenkakuHankaku = 148,
+        LeftControl = 224,
+        LeftShift = 225,
+        LeftAlt = 226,
+        LeftGui = 227,
+        RightControl = 228,
+        RightShift = 229,
+        RightAlt = 230,
+        RightGui = 231
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardModifier.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardModifier.cs
new file mode 100644
index 0000000000..72d1603aa9
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardModifier.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard
+{
+    // TODO: This seems entirely wrong
+    [Flags]
+    enum KeyboardModifier : uint
+    {
+        None = 0,
+        Control = 1 << 0,
+        Shift = 1 << 1,
+        LeftAlt = 1 << 2,
+        RightAlt = 1 << 3,
+        Gui = 1 << 4,
+        CapsLock = 1 << 8,
+        ScrollLock = 1 << 9,
+        NumLock = 1 << 10,
+        Katakana = 1 << 11,
+        Hiragana = 1 << 12
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardState.cs
new file mode 100644
index 0000000000..3760850660
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardState.cs
@@ -0,0 +1,13 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard
+{
+    struct KeyboardState : ISampledData
+    {
+        public ulong SamplingNumber;
+        public KeyboardModifier Modifiers;
+        public KeyboardKey Keys;
+
+        ulong ISampledData.SamplingNumber => SamplingNumber;
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseAttribute.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseAttribute.cs
new file mode 100644
index 0000000000..5ffba0d7b5
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse
+{
+    [Flags]
+    enum MouseAttribute : uint
+    {
+        None = 0,
+        Transferable = 1 << 0,
+        IsConnected = 1 << 1
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseButton.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseButton.cs
new file mode 100644
index 0000000000..7e35140c68
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseButton.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse
+{
+    [Flags]
+    enum MouseButton : uint
+    {
+        None = 0,
+        Left = 1 << 0,
+        Right = 1 << 1,
+        Middle = 1 << 2,
+        Forward = 1 << 3,
+        Back = 1 << 4
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseState.cs
new file mode 100644
index 0000000000..67ad6bf1ad
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseState.cs
@@ -0,0 +1,19 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse
+{
+    struct MouseState : ISampledData
+    {
+        public ulong SamplingNumber;
+        public int X;
+        public int Y;
+        public int DeltaX;
+        public int DeltaY;
+        public int WheelDeltaX;
+        public int WheelDeltaY;
+        public MouseButton Buttons;
+        public MouseAttribute Attributes;
+
+        ulong ISampledData.SamplingNumber => SamplingNumber;
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/DeviceType.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/DeviceType.cs
new file mode 100644
index 0000000000..b020183536
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/DeviceType.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    [Flags]
+    enum DeviceType : int
+    {
+        None = 0,
+
+        FullKey = 1 << 0,
+        DebugPad = 1 << 1,
+        HandheldLeft = 1 << 2,
+        HandheldRight = 1 << 3,
+        JoyLeft = 1 << 4,
+        JoyRight = 1 << 5,
+        Palma = 1 << 6,
+        LarkHvcLeft = 1 << 7,
+        LarkHvcRight = 1 << 8,
+        LarkNesLeft = 1 << 9,
+        LarkNesRight = 1 << 10,
+        HandheldLarkHvcLeft = 1 << 11,
+        HandheldLarkHvcRight = 1 << 12,
+        HandheldLarkNesLeft = 1 << 13,
+        HandheldLarkNesRight = 1 << 14,
+        Lucia = 1 << 15,
+
+        System = 1 << 31
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadAttribute.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadAttribute.cs
new file mode 100644
index 0000000000..0960b7bf3c
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadAttribute.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    [Flags]
+    enum NpadAttribute : uint
+    {
+        None = 0,
+        IsConnected = 1 << 0,
+        IsWired = 1 << 1,
+        IsLeftConnected = 1 << 2,
+        IsLeftWired = 1 << 3,
+        IsRightConnected = 1 << 4,
+        IsRightWired = 1 << 5
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadBatteryLevel.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadBatteryLevel.cs
new file mode 100644
index 0000000000..477dfd10f9
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadBatteryLevel.cs
@@ -0,0 +1,11 @@
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    enum NpadBatteryLevel : int
+    {
+        Percent0,
+        Percent25,
+        Percent50,
+        Percent75,
+        Percent100
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadButton.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadButton.cs
new file mode 100644
index 0000000000..5b3e13a72d
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadButton.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    [Flags]
+    enum NpadButton : ulong
+    {
+        None = 0,
+        A = 1 << 0,
+        B = 1 << 1,
+        X = 1 << 2,
+        Y = 1 << 3,
+        StickL = 1 << 4,
+        StickR = 1 << 5,
+        L = 1 << 6,
+        R = 1 << 7,
+        ZL = 1 << 8,
+        ZR = 1 << 9,
+        Plus = 1 << 10,
+        Minus = 1 << 11,
+        Left = 1 << 12,
+        Up = 1 << 13,
+        Right = 1 << 14,
+        Down = 1 << 15,
+        StickLLeft = 1 << 16,
+        StickLUp = 1 << 17,
+        StickLRight = 1 << 18,
+        StickLDown = 1 << 19,
+        StickRLeft = 1 << 20,
+        StickRUp = 1 << 21,
+        StickRRight = 1 << 22,
+        StickRDown = 1 << 23,
+        LeftSL = 1 << 24,
+        LeftSR = 1 << 25,
+        RightSL = 1 << 26,
+        RightSR = 1 << 27,
+        Palma = 1 << 28,
+
+        // FIXME: Probably a button on Lark.
+        Unknown29 = 1 << 29,
+
+        HandheldLeftB = 1 << 30
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadColorAttribute.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadColorAttribute.cs
new file mode 100644
index 0000000000..1e547cc8f1
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadColorAttribute.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    enum NpadColorAttribute : uint
+    {
+        Ok,
+        ReadError,
+        NoController
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCommonState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCommonState.cs
new file mode 100644
index 0000000000..eaccef8029
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCommonState.cs
@@ -0,0 +1,16 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    struct NpadCommonState : ISampledData
+    {
+        public ulong SamplingNumber;
+        public NpadButton Buttons;
+        public AnalogStickState AnalogStickL;
+        public AnalogStickState AnalogStickR;
+        public NpadAttribute Attributes;
+        private uint _reserved;
+
+        ulong ISampledData.SamplingNumber => SamplingNumber;
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadFullKeyColorState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadFullKeyColorState.cs
new file mode 100644
index 0000000000..990eafb261
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadFullKeyColorState.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    struct NpadFullKeyColorState
+    {
+        public NpadColorAttribute Attribute;
+        public uint FullKeyBody;
+        public uint FullKeyButtons;
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadGcTriggerState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadGcTriggerState.cs
new file mode 100644
index 0000000000..52668f85e7
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadGcTriggerState.cs
@@ -0,0 +1,15 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    struct NpadGcTriggerState : ISampledData
+    {
+#pragma warning disable CS0649
+        public ulong SamplingNumber;
+        public uint TriggerL;
+        public uint TriggerR;
+#pragma warning restore CS0649
+
+        ulong ISampledData.SamplingNumber => SamplingNumber;
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs
new file mode 100644
index 0000000000..f225ff6772
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs
@@ -0,0 +1,61 @@
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    struct NpadInternalState
+    {
+        public NpadStyleTag StyleSet;
+        public NpadJoyAssignmentMode JoyAssignmentMode;
+        public NpadFullKeyColorState FullKeyColor;
+        public NpadJoyColorState JoyColor;
+        public RingLifo<NpadCommonState> FullKey;
+        public RingLifo<NpadCommonState> Handheld;
+        public RingLifo<NpadCommonState> JoyDual;
+        public RingLifo<NpadCommonState> JoyLeft;
+        public RingLifo<NpadCommonState> JoyRight;
+        public RingLifo<NpadCommonState> Palma;
+        public RingLifo<NpadCommonState> SystemExt;
+        public RingLifo<SixAxisSensorState> FullKeySixAxisSensor;
+        public RingLifo<SixAxisSensorState> HandheldSixAxisSensor;
+        public RingLifo<SixAxisSensorState> JoyDualSixAxisSensor;
+        public RingLifo<SixAxisSensorState> JoyDualRightSixAxisSensor;
+        public RingLifo<SixAxisSensorState> JoyLeftSixAxisSensor;
+        public RingLifo<SixAxisSensorState> JoyRightSixAxisSensor;
+        public DeviceType DeviceType;
+        private uint _reserved1;
+        public NpadSystemProperties SystemProperties;
+        public NpadSystemButtonProperties SystemButtonProperties;
+        public NpadBatteryLevel BatteryLevelJoyDual;
+        public NpadBatteryLevel BatteryLevelJoyLeft;
+        public NpadBatteryLevel BatteryLevelJoyRight;
+        public uint AppletFooterUiAttributes;
+        public byte AppletFooterUiType;
+        private unsafe fixed byte _reserved2[0x7B];
+        public RingLifo<NpadGcTriggerState> GcTrigger;
+        public NpadLarkType LarkTypeLeftAndMain;
+        public NpadLarkType LarkTypeRight;
+        public NpadLuciaType LuciaType;
+        public uint Unknown43EC;
+
+        public static NpadInternalState Create()
+        {
+            return new NpadInternalState
+            {
+                FullKey = RingLifo<NpadCommonState>.Create(),
+                Handheld = RingLifo<NpadCommonState>.Create(),
+                JoyDual = RingLifo<NpadCommonState>.Create(),
+                JoyLeft = RingLifo<NpadCommonState>.Create(),
+                JoyRight = RingLifo<NpadCommonState>.Create(),
+                Palma = RingLifo<NpadCommonState>.Create(),
+                SystemExt = RingLifo<NpadCommonState>.Create(),
+                FullKeySixAxisSensor = RingLifo<SixAxisSensorState>.Create(),
+                HandheldSixAxisSensor = RingLifo<SixAxisSensorState>.Create(),
+                JoyDualSixAxisSensor = RingLifo<SixAxisSensorState>.Create(),
+                JoyDualRightSixAxisSensor = RingLifo<SixAxisSensorState>.Create(),
+                JoyLeftSixAxisSensor = RingLifo<SixAxisSensorState>.Create(),
+                JoyRightSixAxisSensor = RingLifo<SixAxisSensorState>.Create(),
+                GcTrigger = RingLifo<NpadGcTriggerState>.Create(),
+            };
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadJoyAssignmentMode.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadJoyAssignmentMode.cs
new file mode 100644
index 0000000000..871c4c5a4e
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadJoyAssignmentMode.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    enum NpadJoyAssignmentMode : uint
+    {
+        Dual,
+        Single
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadJoyColorState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadJoyColorState.cs
new file mode 100644
index 0000000000..3986dd5e0d
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadJoyColorState.cs
@@ -0,0 +1,11 @@
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    struct NpadJoyColorState
+    {
+        public NpadColorAttribute Attribute;
+        public uint LeftBody;
+        public uint LeftButtons;
+        public uint RightBody;
+        public uint RightButtons;
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadLarkType.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadLarkType.cs
new file mode 100644
index 0000000000..a487a911ac
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadLarkType.cs
@@ -0,0 +1,11 @@
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    enum NpadLarkType : uint
+    {
+        Invalid,
+        H1,
+        H2,
+        NL,
+        NR
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadLuciaType.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadLuciaType.cs
new file mode 100644
index 0000000000..9514848571
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadLuciaType.cs
@@ -0,0 +1,10 @@
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    enum NpadLuciaType
+    {
+        Invalid,
+        J,
+        E,
+        U
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadState.cs
new file mode 100644
index 0000000000..ed9e7c0dfc
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadState.cs
@@ -0,0 +1,18 @@
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    [StructLayout(LayoutKind.Sequential, Size = 0x5000)]
+    struct NpadState
+    {
+        public NpadInternalState InternalState;
+
+        public static NpadState Create()
+        {
+            return new NpadState
+            {
+                InternalState = NpadInternalState.Create()
+            };
+        }
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadStyleTag.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadStyleTag.cs
new file mode 100644
index 0000000000..f31978e245
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadStyleTag.cs
@@ -0,0 +1,76 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    /// <summary>
+    /// Nintendo pad style
+    /// </summary>
+    [Flags]
+    enum NpadStyleTag : uint
+    {
+        /// <summary>
+        /// No type.
+        /// </summary>
+        None = 0,
+
+        /// <summary>
+        /// Pro controller.
+        /// </summary>
+        FullKey = 1 << 0,
+
+        /// <summary>
+        /// Joy-Con controller in handheld mode.
+        /// </summary>
+        Handheld = 1 << 1,
+
+        /// <summary>
+        /// Joy-Con controller in dual mode.
+        /// </summary>
+        JoyDual = 1 << 2,
+
+        /// <summary>
+        /// Joy-Con left controller in single mode.
+        /// </summary>
+        JoyLeft = 1 << 3,
+
+        /// <summary>
+        /// Joy-Con right controller in single mode.
+        /// </summary>
+        JoyRight = 1 << 4,
+
+        /// <summary>
+        /// GameCube controller.
+        /// </summary>
+        Gc = 1 << 5,
+
+        /// <summary>
+        /// Poké Ball Plus controller.
+        /// </summary>
+        Palma = 1 << 6,
+
+        /// <summary>
+        /// NES and Famicom controller.
+        /// </summary>
+        Lark = 1 << 7,
+
+        /// <summary>
+        /// NES and Famicom controller in handheld mode.
+        /// </summary>
+        HandheldLark = 1 << 8,
+
+        /// <summary>
+        /// SNES controller.
+        /// </summary>
+        Lucia = 1 << 9,
+
+        /// <summary>
+        /// Generic external controller.
+        /// </summary>
+        SystemExt = 1 << 29,
+
+        /// <summary>
+        /// Generic controller.
+        /// </summary>
+        System = 1 << 30
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadSystemButtonProperties.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadSystemButtonProperties.cs
new file mode 100644
index 0000000000..686032714c
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadSystemButtonProperties.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    [Flags]
+    enum NpadSystemButtonProperties : uint
+    {
+        None = 0,
+        IsUnintendedHomeButtonInputProtectionEnabled = 1 << 0
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadSystemProperties.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadSystemProperties.cs
new file mode 100644
index 0000000000..13444555e0
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadSystemProperties.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    [Flags]
+    enum NpadSystemProperties : ulong
+    {
+        None = 0,
+
+        IsChargingJoyDual = 1 << 0,
+        IsChargingJoyLeft = 1 << 1,
+        IsChargingJoyRight = 1 << 2,
+        IsPoweredJoyDual = 1 << 3,
+        IsPoweredJoyLeft = 1 << 4,
+        IsPoweredJoyRight = 1 << 5,
+        IsUnsuportedButtonPressedOnNpadSystem = 1 << 9,
+        IsUnsuportedButtonPressedOnNpadSystemExt = 1 << 10,
+        IsAbxyButtonOriented = 1 << 11,
+        IsSlSrButtonOriented = 1 << 12,
+        IsPlusAvailable = 1 << 13,
+        IsMinusAvailable = 1 << 14,
+        IsDirectionalButtonsAvailable = 1 << 15
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/SixAxisSensorAttribute.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/SixAxisSensorAttribute.cs
new file mode 100644
index 0000000000..7ed46d9815
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/SixAxisSensorAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    [Flags]
+    enum SixAxisSensorAttribute : uint
+    {
+        None = 0,
+        IsConnected = 1 << 0,
+        IsInterpolated = 1 << 1
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/SixAxisSensorState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/SixAxisSensorState.cs
new file mode 100644
index 0000000000..d024b0b0ea
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/SixAxisSensorState.cs
@@ -0,0 +1,19 @@
+using Ryujinx.Common.Memory;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
+{
+    struct SixAxisSensorState : ISampledData
+    {
+        public ulong DeltaTime;
+        public ulong SamplingNumber;
+        public HidVector Acceleration;
+        public HidVector AngularVelocity;
+        public HidVector Angle;
+        public Array9<float> Direction;
+        public SixAxisSensorAttribute Attributes;
+        private uint _reserved;
+
+        ulong ISampledData.SamplingNumber => SamplingNumber;
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs
new file mode 100644
index 0000000000..48acfc3f34
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs
@@ -0,0 +1,66 @@
+using Ryujinx.Common.Memory;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugPad;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.TouchScreen;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory
+{
+    /// <summary>
+    /// Represent the shared memory shared between applications for input.
+    /// </summary>
+    [StructLayout(LayoutKind.Explicit, Size = 0x40000)]
+    struct SharedMemory
+    {
+        /// <summary>
+        /// Debug controller.
+        /// </summary>
+        [FieldOffset(0)]
+        public RingLifo<DebugPadState> DebugPad;
+
+        /// <summary>
+        /// Touchscreen.
+        /// </summary>
+        [FieldOffset(0x400)]
+        public RingLifo<TouchScreenState> TouchScreen;
+
+        /// <summary>
+        /// Mouse.
+        /// </summary>
+        [FieldOffset(0x3400)]
+        public RingLifo<MouseState> Mouse;
+
+        /// <summary>
+        /// Keyboard.
+        /// </summary>
+        [FieldOffset(0x3800)]
+        public RingLifo<KeyboardState> Keyboard;
+
+        /// <summary>
+        /// Nintendo Pads.
+        /// </summary>
+        [FieldOffset(0x9A00)]
+        public Array10<NpadState> Npads;
+
+        public static SharedMemory Create()
+        {
+            SharedMemory result = new SharedMemory
+            {
+                DebugPad = RingLifo<DebugPadState>.Create(),
+                TouchScreen = RingLifo<TouchScreenState>.Create(),
+                Mouse = RingLifo<MouseState>.Create(),
+                Keyboard = RingLifo<KeyboardState>.Create(),
+            };
+
+            for (int i = 0; i < result.Npads.Length; i++)
+            {
+                result.Npads[i] = NpadState.Create();
+            }
+
+            return result;
+        }
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchAttribute.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchAttribute.cs
new file mode 100644
index 0000000000..8a8f9cc1e7
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.TouchScreen
+{
+    [Flags]
+    enum TouchAttribute : uint
+    {
+        None = 0,
+        Start = 1 << 0,
+        End = 1 << 1
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchScreenState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchScreenState.cs
new file mode 100644
index 0000000000..8203e49b55
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchScreenState.cs
@@ -0,0 +1,15 @@
+using Ryujinx.Common.Memory;
+using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.TouchScreen
+{
+    struct TouchScreenState : ISampledData
+    {
+        public ulong SamplingNumber;
+        public int TouchesCount;
+        private int _reserved;
+        public Array16<TouchState> Touches;
+
+        ulong ISampledData.SamplingNumber => SamplingNumber;
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchState.cs
new file mode 100644
index 0000000000..ba621a2b07
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchState.cs
@@ -0,0 +1,19 @@
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.TouchScreen
+{
+    struct TouchState
+    {
+        public ulong DeltaTime;
+#pragma warning disable CS0649
+        public TouchAttribute Attribute;
+#pragma warning restore CS0649
+        public uint FingerId;
+        public uint X;
+        public uint Y;
+        public uint DiameterX;
+        public uint DiameterY;
+        public uint RotationAngle;
+#pragma warning disable CS0169
+        private uint _reserved;
+#pragma warning restore CS0169
+    }
+}
diff --git a/Ryujinx.Input/HLE/NpadController.cs b/Ryujinx.Input/HLE/NpadController.cs
index d3553d6468..e1a8e2d753 100644
--- a/Ryujinx.Input/HLE/NpadController.cs
+++ b/Ryujinx.Input/HLE/NpadController.cs
@@ -456,14 +456,14 @@ namespace Ryujinx.Input.HLE
                 KeyboardInput hidKeyboard = new KeyboardInput
                 {
                     Modifier = 0,
-                    Keys = new int[0x8]
+                    Keys = new ulong[0x4]
                 };
 
                 foreach (HLEKeyboardMappingEntry entry in KeyMapping)
                 {
-                    int value = keyboardState.IsPressed(entry.TargetKey) ? 1 : 0;
+                    ulong value = keyboardState.IsPressed(entry.TargetKey) ? 1UL : 0UL;
 
-                    hidKeyboard.Keys[entry.Target / 0x20] |= (value << (entry.Target % 0x20));
+                    hidKeyboard.Keys[entry.Target / 0x40] |= (value << (entry.Target % 0x40));
                 }
 
                 foreach (HLEKeyboardMappingEntry entry in KeyModifierMapping)