aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs1
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Hid.cs48
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidDevices/BaseDevice.cs13
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidDevices/DebugPadDevice.cs19
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidDevices/KeyboardDevice.cs27
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidDevices/MouseDevice.cs42
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs420
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidDevices/TouchDevice.cs51
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/KeyboardInput.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs3
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/Boolean32.cs9
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/HidVector.cs (renamed from Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/HidVector.cs)2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/Npad/NpadColor.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/NpadJoyHoldType.cs (renamed from Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadJoyHoldType.cs)4
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/CommonEntriesHeader.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPad.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPadEntry.cs9
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/HidSharedMemory.cs23
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/Keyboard.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/KeyboardState.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/Mouse.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/MousePosition.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/MouseState.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/BatterCharge.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/DeviceType.cs26
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/Npad.cs23
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadColorDescription.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadConnectionState.cs13
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayout.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayoutsIndex.cs13
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSixAxis.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadState.cs14
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadStatesHeader.cs16
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSystemProperties.cs22
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/SixAxisLayoutsIndex.cs14
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/SixAxisState.cs14
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreen.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenState.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenStateData.cs19
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AnalogStickState.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/AtomicStorage.cs26
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/ISampledData.cs7
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs149
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadAttribute.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadButton.cs24
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugPad/DebugPadState.cs15
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardKey.cs29
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardKeyShift.cs138
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardModifier.cs21
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Keyboard/KeyboardState.cs13
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseAttribute.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseButton.cs15
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Mouse/MouseState.cs19
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/DeviceType.cs29
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadAttribute.cs16
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadBatteryLevel.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadButton.cs44
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadColorAttribute.cs9
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCommonState.cs16
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadFullKeyColorState.cs9
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadGcTriggerState.cs15
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs61
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadJoyAssignmentMode.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadJoyColorState.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadLarkType.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadLuciaType.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadState.cs18
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadStyleTag.cs76
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadSystemButtonProperties.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadSystemProperties.cs24
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/SixAxisSensorAttribute.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/SixAxisSensorState.cs19
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs66
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchAttribute.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchScreenState.cs15
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/TouchScreen/TouchState.cs19
-rw-r--r--Ryujinx.Input/HLE/NpadController.cs6
77 files changed, 1388 insertions, 617 deletions
diff --git a/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs b/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs
index fd89e8f6..0597cf9b 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 18a7ba11..1e85dbf7 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,40 +30,30 @@ namespace Ryujinx.HLE.HOS.Services.Hid
public KeyboardDevice Keyboard;
public NpadDevices Npads;
- static Hid()
+ private static void CheckTypeSizeOrThrow<T>(int expectedSize)
{
- 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)
+ if (Unsafe.SizeOf<T>() != expectedSize)
{
- 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);
+ throw new InvalidStructLayoutException<T>(expectedSize);
}
}
+ static Hid()
+ {
+ 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)
{
_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 59d6dfa3..e8bf628a 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 7e708e32..e3b95390 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;
+
+ ref DebugPadState previousEntry = ref lifo.GetCurrentEntryRef();
- int currentIndex = UpdateEntriesHeader(ref debugPad.Header, out int previousIndex);
+ DebugPadState newState = new DebugPadState();
- if (!Active)
+ 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 e8ed6a3e..99dc078d 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,
+ };
+
+ keyState.Keys.AsSpan().CopyTo(newState.Keys.RawData.ToSpan());
+ newState.Modifiers = (KeyboardModifier)keyState.Modifier;
- currentEntry.Modifier = (ulong)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 ee58a563..e07c1d20 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);
+ ref MouseState previousEntry = ref lifo.GetCurrentEntryRef();
+
+ MouseState newState = new MouseState()
+ {
+ SamplingNumber = previousEntry.SamplingNumber + 1,
+ };
- if (!Active)
+ if (Active)
{
- return;
+ 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 2150f278..3ff7e733 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.SystemProperties = NpadSystemProperties.PowerInfo0Connected |
- NpadSystemProperties.PowerInfo1Connected |
- NpadSystemProperties.PowerInfo2Connected;
-
- controller.BatteryState.ToSpan().Fill(DefaultBatteryCharge);
+ 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.IsPoweredJoyDual |
+ NpadSystemProperties.IsPoweredJoyLeft |
+ NpadSystemProperties.IsPoweredJoyRight;
+
+ 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)
+ {
+ 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)
{
- 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
- };
+ 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);
+
+ 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;
+ }
- currentEntry.Buttons = state.Buttons;
- currentEntry.LStickX = state.LStick.Dx;
- currentEntry.LStickY = state.LStick.Dy;
- currentEntry.RStickX = state.RStick.Dx;
- currentEntry.RStickY = state.RStick.Dy;
+ 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];
+ SixAxisSensorState newState = new SixAxisSensorState
+ {
+ Acceleration = accel,
+ AngularVelocity = gyro,
+ Angle = rotation,
+ Attributes = SixAxisSensorAttribute.IsConnected
+ };
- int previousEntryIndex = (int)(currentLayout.Header.LatestEntry == 0 ?
- currentLayout.Header.MaxEntryIndex : currentLayout.Header.LatestEntry - 1);
+ state.Orientation.AsSpan().CopyTo(newState.Direction.ToSpan());
- ref SixAxisState previousEntry = ref currentLayout.Entries[previousEntryIndex];
+ ref RingLifo<SixAxisSensorState> lifo = ref GetSixAxisSensorLifo(ref currentNpad, isRightPair);
- currentEntry.Accelerometer = accel;
- currentEntry.Gyroscope = gyro;
- currentEntry.Rotations = rotation;
+ WriteNewSixInputEntry(ref lifo, ref newState);
- unsafe
+ bool needUpdateRight = currentNpad.StyleSet == NpadStyleTag.JoyDual && !isRightPair;
+
+ if (!isRightPair)
{
- for (int i = 0; i < 9; i++)
- {
- currentEntry.Orientation[i] = state.Orientation[i];
- }
+ 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;
- }
-
- private void UpdateAllEntries()
- {
- ref Array10<ShMemNpad> controllers = ref _device.Hid.SharedMemory.Npads;
- for (int i = 0; i < controllers.Length; ++i)
+ if (!needUpdateRight)
{
- 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);
+ SixAxisSensorState emptyState = new SixAxisSensorState();
- ref NpadState currentEntry = ref currentLayout.Entries[currentIndex];
- NpadState previousEntry = currentLayout.Entries[previousIndex];
+ emptyState.Attributes = SixAxisSensorAttribute.IsConnected;
- currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1;
- currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1;
-
- if (controllers[i].Header.Type == ControllerType.None)
- {
- continue;
- }
-
- currentEntry.ConnectionState = NpadConnectionState.ControllerStateConnected;
+ WriteNewSixInputEntry(ref currentNpad.JoyDualRightSixAxisSensor, ref emptyState);
+ }
- 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;
- }
- }
+ return needUpdateRight;
+ }
- 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);
+ private void UpdateDisconnectedInputSixAxis(PlayerIndex index)
+ {
+ ref NpadInternalState currentNpad = ref _device.Hid.SharedMemory.Npads[(int)index].InternalState;
- ref SixAxisState currentEntry = ref currentLayout.Entries[currentIndex];
- SixAxisState previousEntry = currentLayout.Entries[previousIndex];
+ SixAxisSensorState newState = new SixAxisSensorState();
- currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1;
- currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1;
+ newState.Attributes = SixAxisSensorAttribute.IsConnected;
- 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 10c34453..432a37e3 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;
- }
-
- ref TouchScreenState currentEntry = ref touchscreen.Entries[currentIndex];
- TouchScreenState previousEntry = touchscreen.Entries[previousIndex];
-
- currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1;
- currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1;
+ SamplingNumber = previousEntry.SamplingNumber + 1
+ };
- currentEntry.NumTouches = (ulong)points.Length;
+ if (Active)
+ {
+ newState.TouchesCount = points.Length;
- int pointsLength = Math.Min(points.Length, currentEntry.Touches.Length);
+ int pointsLength = Math.Min(points.Length, newState.Touches.Length);
- for (int i = 0; i < pointsLength; ++i)
- {
- TouchPoint pi = points[i];
- currentEntry.Touches[i] = new TouchScreenStateData
+ 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 26681270..be6857fb 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 2ab305ac..e3c22edf 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 5a8d51c6..00000000
--- 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
index b41bcb2e..18d9fd9c 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 57b4b366..3c311e21 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
index a6f29760..d3b51a24 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 f83fdcdf..00000000
--- 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 3fbaa304..00000000
--- 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 3089fc5b..00000000
--- 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 d950425d..00000000
--- 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 e2c1844f..00000000
--- 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 1f54a4fd..00000000
--- 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 6b99e04a..00000000
--- 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 e94c9e0c..00000000
--- 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 7856b09d..00000000
--- 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 b94ab172..00000000
--- 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 f6d7b783..00000000
--- 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 4ef83f3d..00000000
--- 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 ccc7cb8d..00000000
--- 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 60f64fd3..00000000
--- 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 24c4f4d4..00000000
--- 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 c4419336..00000000
--- 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 a0a39fdc..00000000
--- 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 60a5f9d3..00000000
--- 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 006d4357..00000000
--- 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 708f7da9..00000000
--- 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 a8795fc0..00000000
--- 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 12974e7e..00000000
--- 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 5f12295c..00000000
--- 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 1c85e291..00000000
--- 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 4d4c48d1..00000000
--- 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 00000000..bf4b5888
--- /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 00000000..45b92ba9
--- /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 00000000..08f76747
--- /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 00000000..615e3893
--- /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 00000000..ec5bd3c8
--- /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 00000000..e8f28317
--- /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 00000000..3e1e1ad8
--- /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 00000000..22df7c79
--- /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 00000000..01c2bb30
--- /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 00000000..72d1603a
--- /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 00000000..37608506
--- /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 00000000..5ffba0d7
--- /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 00000000..7e35140c
--- /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 00000000..67ad6bf1
--- /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 00000000..b0201835
--- /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 00000000..0960b7bf
--- /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 00000000..477dfd10
--- /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 00000000..5b3e13a7
--- /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 00000000..1e547cc8
--- /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 00000000..eaccef80
--- /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 00000000..990eafb2
--- /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 00000000..52668f85
--- /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 00000000..f225ff67
--- /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 00000000..871c4c5a
--- /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 00000000..3986dd5e
--- /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 00000000..a487a911
--- /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 00000000..95148485
--- /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 00000000..ed9e7c0d
--- /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 00000000..f31978e2
--- /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 00000000..68603271
--- /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 00000000..13444555
--- /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 00000000..7ed46d98
--- /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 00000000..d024b0b0
--- /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 00000000..48acfc3f
--- /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 00000000..8a8f9cc1
--- /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 00000000..8203e49b
--- /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 00000000..ba621a2b
--- /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 d3553d64..e1a8e2d7 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)