diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AtomicStorage.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AtomicStorage.cs
index 45b92ba98f..da53e4211b 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AtomicStorage.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AtomicStorage.cs
@@ -2,7 +2,7 @@
 
 namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
 {
-    struct AtomicStorage<T> where T: unmanaged
+    struct AtomicStorage<T> where T: unmanaged, ISampledDataStruct
     {
         public ulong SamplingNumber;
         public T Object;
@@ -14,9 +14,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
 
         public void SetObject(ref T obj)
         {
-            ISampledData samplingProvider = obj as ISampledData;
+            ulong samplingNumber = ISampledDataStruct.GetSamplingNumber(ref obj);
 
-            Interlocked.Exchange(ref SamplingNumber, samplingProvider.SamplingNumber);
+            Interlocked.Exchange(ref SamplingNumber, samplingNumber);
 
             Thread.MemoryBarrier();
 
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledData.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledData.cs
deleted file mode 100644
index 08f76747e1..0000000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledData.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-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/ISampledDataStruct.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledDataStruct.cs
new file mode 100644
index 0000000000..a382c0c284
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledDataStruct.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Buffers.Binary;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
+{
+    /// <summary>
+    /// This is a "marker interface" to add some compile-time safety to a convention-based optimization.
+    ///
+    /// Any struct implementing this interface should:
+    ///   - use <c>StructLayoutAttribute</c> (and related attributes) to explicity control how the struct is laid out in memory.
+    ///   - ensure that the method <c>ISampledDataStruct.GetSamplingNumberFieldOffset()</c> correctly returns the offset, in bytes,
+    ///     to the ulong "Sampling Number" field within the struct. Most types have it as the first field, so the default offset is 0.
+    /// 
+    /// Example:
+    /// 
+    /// <c>
+    ///         [StructLayout(LayoutKind.Sequential, Pack = 8)]
+    ///         struct DebugPadState : ISampledDataStruct
+    ///         {
+    ///             public ulong SamplingNumber;    // 1st field, so no need to add special handling to GetSamplingNumberFieldOffset()
+    ///             // other members...
+    ///         }
+    ///
+    ///         [StructLayout(LayoutKind.Sequential, Pack = 8)]
+    ///         struct SixAxisSensorState : ISampledDataStruct
+    ///         {
+    ///             public ulong DeltaTime;
+    ///             public ulong SamplingNumber;    // Not the first field - needs special handling in GetSamplingNumberFieldOffset()
+    ///             // other members...
+    ///         }
+    /// </c>
+    /// </summary>
+    internal interface ISampledDataStruct
+    {
+        // No Instance Members - marker interface only
+
+        public static ulong GetSamplingNumber<T>(ref T sampledDataStruct) where T : unmanaged, ISampledDataStruct
+        {
+            ReadOnlySpan<T> structSpan = MemoryMarshal.CreateReadOnlySpan(ref sampledDataStruct, 1);
+
+            ReadOnlySpan<byte> byteSpan = MemoryMarshal.Cast<T, byte>(structSpan);
+
+            int fieldOffset = GetSamplingNumberFieldOffset(ref sampledDataStruct);
+
+            if (fieldOffset > 0)
+            {
+                byteSpan = byteSpan.Slice(fieldOffset);
+            }
+
+            ulong value = BinaryPrimitives.ReadUInt64LittleEndian(byteSpan);
+
+            return value;
+        }
+
+        private static int GetSamplingNumberFieldOffset<T>(ref T sampledDataStruct) where T : unmanaged, ISampledDataStruct
+        {
+            return sampledDataStruct switch
+            {
+                Npad.SixAxisSensorState _ => sizeof(ulong),
+                _ => 0
+            };
+        }
+    }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs
index 615e389303..ae654d6f85 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs
@@ -5,7 +5,7 @@ using System.Threading;
 
 namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common
 {
-    struct RingLifo<T> where T: unmanaged
+    struct RingLifo<T> where T: unmanaged, ISampledDataStruct
     {
         private const ulong MaxEntries = 17;
 
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadState.cs
index 3e1e1ad8e7..0846cfc73f 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadState.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadState.cs
@@ -1,15 +1,15 @@
 using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using System.Runtime.InteropServices;
 
 namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugPad
 {
-    struct DebugPadState : ISampledData
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    struct DebugPadState : ISampledDataStruct
     {
         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/KeyboardModifier.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardModifier.cs
index 72d1603aa9..839a4e8298 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardModifier.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardModifier.cs
@@ -2,9 +2,8 @@
 
 namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard
 {
-    // TODO: This seems entirely wrong
     [Flags]
-    enum KeyboardModifier : uint
+    enum KeyboardModifier : ulong
     {
         None = 0,
         Control = 1 << 0,
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardState.cs
index 3760850660..4de92813ba 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardState.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardState.cs
@@ -1,13 +1,13 @@
 using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using System.Runtime.InteropServices;
 
 namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard
 {
-    struct KeyboardState : ISampledData
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    struct KeyboardState : ISampledDataStruct
     {
         public ulong SamplingNumber;
         public KeyboardModifier Modifiers;
         public KeyboardKey Keys;
-
-        ulong ISampledData.SamplingNumber => SamplingNumber;
     }
 }
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseState.cs
index 67ad6bf1ad..c953c79452 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseState.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseState.cs
@@ -1,8 +1,10 @@
 using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using System.Runtime.InteropServices;
 
 namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse
 {
-    struct MouseState : ISampledData
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    struct MouseState : ISampledDataStruct
     {
         public ulong SamplingNumber;
         public int X;
@@ -13,7 +15,5 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse
         public int WheelDeltaY;
         public MouseButton Buttons;
         public MouseAttribute Attributes;
-
-        ulong ISampledData.SamplingNumber => SamplingNumber;
     }
 }
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCommonState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCommonState.cs
index eaccef8029..64f75ce9ac 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCommonState.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCommonState.cs
@@ -1,8 +1,10 @@
 using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using System.Runtime.InteropServices;
 
 namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
 {
-    struct NpadCommonState : ISampledData
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    struct NpadCommonState : ISampledDataStruct
     {
         public ulong SamplingNumber;
         public NpadButton Buttons;
@@ -10,7 +12,5 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
         public AnalogStickState AnalogStickR;
         public NpadAttribute Attributes;
         private uint _reserved;
-
-        ulong ISampledData.SamplingNumber => SamplingNumber;
     }
 }
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadGcTriggerState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadGcTriggerState.cs
index 52668f85e7..bddd6212de 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadGcTriggerState.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadGcTriggerState.cs
@@ -1,15 +1,15 @@
 using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using System.Runtime.InteropServices;
 
 namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
 {
-    struct NpadGcTriggerState : ISampledData
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    struct NpadGcTriggerState : ISampledDataStruct
     {
 #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/SixAxisSensorState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/SixAxisSensorState.cs
index d024b0b0ea..18be32763f 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/SixAxisSensorState.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/SixAxisSensorState.cs
@@ -1,9 +1,11 @@
 using Ryujinx.Common.Memory;
 using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using System.Runtime.InteropServices;
 
 namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
 {
-    struct SixAxisSensorState : ISampledData
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    struct SixAxisSensorState : ISampledDataStruct
     {
         public ulong DeltaTime;
         public ulong SamplingNumber;
@@ -13,7 +15,5 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
         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/TouchScreen/TouchScreenState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchScreenState.cs
index 8203e49b55..cdd4cc45ef 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchScreenState.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchScreenState.cs
@@ -1,15 +1,15 @@
 using Ryujinx.Common.Memory;
 using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common;
+using System.Runtime.InteropServices;
 
 namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.TouchScreen
 {
-    struct TouchScreenState : ISampledData
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    struct TouchScreenState : ISampledDataStruct
     {
         public ulong SamplingNumber;
         public int TouchesCount;
         private int _reserved;
         public Array16<TouchState> Touches;
-
-        ulong ISampledData.SamplingNumber => SamplingNumber;
     }
 }