aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Services
diff options
context:
space:
mode:
authormageven <62494521+mageven@users.noreply.github.com>2020-08-24 02:24:11 +0530
committerGitHub <noreply@github.com>2020-08-23 22:54:11 +0200
commit27179d02180396750cc2ea08ac1e2cc5a91a8763 (patch)
treed9fb3e03f4553b0aad2c9dec7e74e38f864e199c /Ryujinx.HLE/HOS/Services
parent01ff648bdf46b85409d1a834987a69150de7adb9 (diff)
Improve multi-controller support in HID and Controller Applet (#1453)
* Initial commit Enable proper LED patterns Toggle Hotkeys only on focus Ignore Handheld on Docked mode Remove PrimaryController Validate NpadIdType Rewrite NpadDevices to process config in update loop Cleanup * Notify in log periodically when no matched controllers * Remove duplicate StructArrayHelpers in favor of Common.Memory Fix struct padding CS0169 warns in Touchscreen * Remove GTK markup from Controller Applet Use IList instead of List Explicit list capacity in 1ms loop Fix formatting * Restrict ControllerWindow to show valid controller types Add selected player name to ControllerWindow title * ControllerWindow: Fix controller type initial value NpadDevices: Simplify default battery charge * Address AcK's comments Use explicit types and fix formatting * Remove HashSet for SupportedPlayers Fixes potential exceptions due to race * Fix ControllerSupportArg struct packing Also comes with two revisions of struct for 4/8 players max.
Diffstat (limited to 'Ryujinx.HLE/HOS/Services')
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Hid.cs20
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs261
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs14
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs15
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPad.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/HidSharedMemory.cs3
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/Keyboard.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/Mouse.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/Npad.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayout.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSixAxis.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/StructArrayHelpers.cs55
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreen.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenState.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenStateData.cs4
15 files changed, 214 insertions, 174 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Hid.cs b/Ryujinx.HLE/HOS/Services/Hid/Hid.cs
index c355a050..2db67619 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Hid.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Hid.cs
@@ -1,5 +1,7 @@
using Ryujinx.Common;
using Ryujinx.HLE.Exceptions;
+using Ryujinx.Common.Configuration.Hid;
+using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Ryujinx.HLE.HOS.Services.Hid
@@ -65,6 +67,24 @@ namespace Ryujinx.HLE.HOS.Services.Hid
Npads = new NpadDevices(_device, true);
}
+ internal void RefreshInputConfig(List<InputConfig> inputConfig)
+ {
+ ControllerConfig[] npadConfig = new ControllerConfig[inputConfig.Count];
+
+ for (int i = 0; i < npadConfig.Length; ++i)
+ {
+ npadConfig[i].Player = (PlayerIndex)inputConfig[i].PlayerIndex;
+ npadConfig[i].Type = (ControllerType)inputConfig[i].ControllerType;
+ }
+
+ _device.Hid.Npads.Configure(npadConfig);
+ }
+
+ internal void RefreshInputConfigEvent(object _, ReactiveEventArgs<List<InputConfig>> args)
+ {
+ RefreshInputConfig(args.NewValue);
+ }
+
public ControllerKeys UpdateStickButtons(JoystickPosition leftStick, JoystickPosition rightStick)
{
ControllerKeys result = 0;
diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs
index 1c882887..334af975 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs
@@ -1,74 +1,118 @@
-using System;
+using Ryujinx.Common;
using Ryujinx.Common.Logging;
+using Ryujinx.Common.Memory;
using Ryujinx.HLE.HOS.Kernel.Threading;
+using System;
+using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Hid
{
public class NpadDevices : BaseDevice
{
- internal NpadJoyHoldType JoyHold = NpadJoyHoldType.Vertical;
+ private const BatteryCharge DefaultBatteryCharge = BatteryCharge.Percent100;
+
+ private const int NoMatchNotifyFrequencyMs = 2000;
+ private int _activeCount;
+ private long _lastNotifyTimestamp;
+
+ public const int MaxControllers = 9; // Players 1-8 and Handheld
+ private ControllerType[] _configuredTypes;
+ private KEvent[] _styleSetUpdateEvents;
+ private bool[] _supportedPlayers;
+
+ internal NpadJoyHoldType JoyHold { get; set; }
internal bool SixAxisActive = false; // TODO: link to hidserver when implemented
+ internal ControllerType SupportedStyleSets { get; set; }
- private enum FilterState
+ public NpadDevices(Switch device, bool active = true) : base(device, active)
{
- Unconfigured = 0,
- Configured = 1,
- Accepted = 2
+ _configuredTypes = new ControllerType[MaxControllers];
+
+ SupportedStyleSets = ControllerType.Handheld | ControllerType.JoyconPair |
+ ControllerType.JoyconLeft | ControllerType.JoyconRight |
+ ControllerType.ProController;
+
+ _supportedPlayers = new bool[MaxControllers];
+ _supportedPlayers.AsSpan().Fill(true);
+
+ _styleSetUpdateEvents = new KEvent[MaxControllers];
+ for (int i = 0; i < _styleSetUpdateEvents.Length; ++i)
+ {
+ _styleSetUpdateEvents[i] = new KEvent(_device.System.KernelContext);
+ }
+
+ _activeCount = 0;
+
+ JoyHold = NpadJoyHoldType.Vertical;
}
- private struct NpadConfig
+ internal ref KEvent GetStyleSetUpdateEvent(PlayerIndex player)
{
- public ControllerType ConfiguredType;
- public FilterState State;
+ return ref _styleSetUpdateEvents[(int)player];
}
- private const int _maxControllers = 9; // Players1-8 and Handheld
- private NpadConfig[] _configuredNpads;
+ internal void ClearSupportedPlayers()
+ {
+ _supportedPlayers.AsSpan().Clear();
+ }
- private ControllerType _supportedStyleSets = ControllerType.ProController |
- ControllerType.JoyconPair |
- ControllerType.JoyconLeft |
- ControllerType.JoyconRight |
- ControllerType.Handheld;
+ internal void SetSupportedPlayer(PlayerIndex player, bool supported = true)
+ {
+ _supportedPlayers[(int)player] = supported;
+ }
- public ControllerType SupportedStyleSets
+ internal IEnumerable<PlayerIndex> GetSupportedPlayers()
{
- get => _supportedStyleSets;
- set
+ for (int i = 0; i < _supportedPlayers.Length; ++i)
{
- if (_supportedStyleSets != value) // Deal with spamming
+ if (_supportedPlayers[i])
{
- _supportedStyleSets = value;
- MatchControllers();
+ yield return (PlayerIndex)i;
}
}
}
- public PlayerIndex PrimaryController { get; set; } = PlayerIndex.Unknown;
+ public bool Validate(int playerMin, int playerMax, ControllerType acceptedTypes, out int configuredCount, out PlayerIndex primaryIndex)
+ {
+ primaryIndex = PlayerIndex.Unknown;
+ configuredCount = 0;
- private KEvent[] _styleSetUpdateEvents;
+ for (int i = 0; i < MaxControllers; ++i)
+ {
+ ControllerType npad = _configuredTypes[i];
- private static readonly Array3<BatteryCharge> _fullBattery;
+ if (npad == ControllerType.Handheld && _device.System.State.DockedMode)
+ {
+ continue;
+ }
- public NpadDevices(Switch device, bool active = true) : base(device, active)
- {
- _configuredNpads = new NpadConfig[_maxControllers];
+ ControllerType currentType = _device.Hid.SharedMemory.Npads[i].Header.Type;
- _styleSetUpdateEvents = new KEvent[_maxControllers];
+ if (currentType != ControllerType.None && (npad & acceptedTypes) != 0 && _supportedPlayers[i])
+ {
+ configuredCount++;
+ if (primaryIndex == PlayerIndex.Unknown)
+ {
+ primaryIndex = (PlayerIndex)i;
+ }
+ }
+ }
- for (int i = 0; i < _styleSetUpdateEvents.Length; ++i)
+ if (configuredCount < playerMin || configuredCount > playerMax || primaryIndex == PlayerIndex.Unknown)
{
- _styleSetUpdateEvents[i] = new KEvent(_device.System.KernelContext);
+ return false;
}
- _fullBattery[0] = _fullBattery[1] = _fullBattery[2] = BatteryCharge.Percent100;
+ return true;
}
- public void AddControllers(params ControllerConfig[] configs)
+ public void Configure(params ControllerConfig[] configs)
{
+ _configuredTypes = new ControllerType[MaxControllers];
+
for (int i = 0; i < configs.Length; ++i)
{
- PlayerIndex player = configs[i].Player;
+ PlayerIndex player = configs[i].Player;
ControllerType controllerType = configs[i].Type;
if (player > PlayerIndex.Handheld)
@@ -81,77 +125,87 @@ namespace Ryujinx.HLE.HOS.Services.Hid
player = PlayerIndex.Handheld;
}
- _configuredNpads[(int)player] = new NpadConfig { ConfiguredType = controllerType, State = FilterState.Configured };
- }
+ _configuredTypes[(int)player] = controllerType;
- MatchControllers();
+ Logger.Info?.Print(LogClass.Hid, $"Configured Controller {controllerType} to {player}");
+ }
}
- private void MatchControllers()
+ public void Update(IList<GamepadInput> states)
{
- PrimaryController = PlayerIndex.Unknown;
+ Remap();
+
+ UpdateAllEntries();
+
+ // Update configured inputs
+ for (int i = 0; i < states.Count; ++i)
+ {
+ UpdateInput(states[i]);
+ }
+ }
- for (int i = 0; i < _configuredNpads.Length; ++i)
+ private void Remap()
+ {
+ // Remap/Init if necessary
+ for (int i = 0; i < MaxControllers; ++i)
{
- ref NpadConfig config = ref _configuredNpads[i];
+ ControllerType config = _configuredTypes[i];
- if (config.State == FilterState.Unconfigured)
+ // Remove Handheld config when Docked
+ if (config == ControllerType.Handheld && _device.System.State.DockedMode)
{
- continue; // Ignore unconfigured
+ config = ControllerType.None;
}
- if ((config.ConfiguredType & _supportedStyleSets) == 0)
+ // Auto-remap ProController and JoyconPair
+ if (config == ControllerType.JoyconPair && (SupportedStyleSets & ControllerType.JoyconPair) == 0 && (SupportedStyleSets & ControllerType.ProController) != 0)
{
- Logger.Warning?.Print(LogClass.Hid, $"ControllerType {config.ConfiguredType} (connected to {(PlayerIndex)i}) not supported by game. Removing...");
-
- config.State = FilterState.Configured;
- _device.Hid.SharedMemory.Npads[i] = new ShMemNpad(); // Zero it
+ config = ControllerType.ProController;
+ }
+ else if (config == ControllerType.ProController && (SupportedStyleSets & ControllerType.ProController) == 0 && (SupportedStyleSets & ControllerType.JoyconPair) != 0)
+ {
+ config = ControllerType.JoyconPair;
+ }
- continue;
+ // Check StyleSet and PlayerSet
+ if ((config & SupportedStyleSets) == 0 || !_supportedPlayers[i])
+ {
+ config = ControllerType.None;
}
- InitController((PlayerIndex)i, config.ConfiguredType);
+ SetupNpad((PlayerIndex)i, config);
}
- // Couldn't find any matching configuration. Reassign to something that works.
- if (PrimaryController == PlayerIndex.Unknown)
+ if (_activeCount == 0 && PerformanceCounter.ElapsedMilliseconds > _lastNotifyTimestamp + NoMatchNotifyFrequencyMs)
{
- ControllerType[] npadsTypeList = (ControllerType[])Enum.GetValues(typeof(ControllerType));
-
- // Skip None Type
- for (int i = 1; i < npadsTypeList.Length; ++i)
- {
- ControllerType controllerType = npadsTypeList[i];
- if ((controllerType & _supportedStyleSets) != 0)
- {
- Logger.Warning?.Print(LogClass.Hid, $"No matching controllers found. Reassigning input as ControllerType {controllerType}...");
-
- InitController(controllerType == ControllerType.Handheld ? PlayerIndex.Handheld : PlayerIndex.Player1, controllerType);
-
- return;
- }
- }
-
- Logger.Error?.Print(LogClass.Hid, "Couldn't find any appropriate controller.");
+ Logger.Warning?.Print(LogClass.Hid, $"No matching controllers found. Application requests '{SupportedStyleSets}' on '{string.Join(", ", GetSupportedPlayers())}'");
+ _lastNotifyTimestamp = PerformanceCounter.ElapsedMilliseconds;
}
}
- internal ref KEvent GetStyleSetUpdateEvent(PlayerIndex player)
+ private void SetupNpad(PlayerIndex player, ControllerType type)
{
- return ref _styleSetUpdateEvents[(int)player];
- }
+ ref ShMemNpad controller = ref _device.Hid.SharedMemory.Npads[(int)player];
- private void InitController(PlayerIndex player, ControllerType type)
- {
- if (type == ControllerType.Handheld)
+ ControllerType oldType = controller.Header.Type;
+
+ if (oldType == type)
{
- player = PlayerIndex.Handheld;
+ return; // Already configured
}
- ref ShMemNpad controller = ref _device.Hid.SharedMemory.Npads[(int)player];
-
controller = new ShMemNpad(); // Zero it
+ if (type == ControllerType.None)
+ {
+ _styleSetUpdateEvents[(int)player].ReadableEvent.Signal(); // Signal disconnect
+ _activeCount--;
+
+ Logger.Info?.Print(LogClass.Hid, $"Disconnected Controller {oldType} from {player}");
+
+ return;
+ }
+
// TODO: Allow customizing colors at config
NpadStateHeader defaultHeader = new NpadStateHeader
{
@@ -168,7 +222,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
NpadSystemProperties.PowerInfo1Connected |
NpadSystemProperties.PowerInfo2Connected;
- controller.BatteryState = _fullBattery;
+ controller.BatteryState.ToSpan().Fill(DefaultBatteryCharge);
switch (type)
{
@@ -217,19 +271,13 @@ namespace Ryujinx.HLE.HOS.Services.Hid
controller.Header = defaultHeader;
- if (PrimaryController == PlayerIndex.Unknown)
- {
- PrimaryController = player;
- }
-
- _configuredNpads[(int)player].State = FilterState.Accepted;
-
_styleSetUpdateEvents[(int)player].ReadableEvent.Signal();
+ _activeCount++;
- Logger.Info?.Print(LogClass.Hid, $"Connected ControllerType {type} to PlayerIndex {player}");
+ Logger.Info?.Print(LogClass.Hid, $"Connected Controller {type} to {player}");
}
- private static NpadLayoutsIndex ControllerTypeToLayout(ControllerType controllerType)
+ private static NpadLayoutsIndex ControllerTypeToNpadLayout(ControllerType controllerType)
=> controllerType switch
{
ControllerType.ProController => NpadLayoutsIndex.ProController,
@@ -241,43 +289,28 @@ namespace Ryujinx.HLE.HOS.Services.Hid
_ => NpadLayoutsIndex.SystemExternal
};
- public void SetGamepadsInput(params GamepadInput[] states)
+ private void UpdateInput(GamepadInput state)
{
- UpdateAllEntries();
-
- for (int i = 0; i < states.Length; ++i)
- {
- SetGamepadState(states[i].PlayerId, states[i].Buttons, states[i].LStick, states[i].RStick);
- }
- }
-
- private void SetGamepadState(PlayerIndex player, ControllerKeys buttons,
- JoystickPosition leftJoystick, JoystickPosition rightJoystick)
- {
- if (player == PlayerIndex.Auto)
- {
- player = PrimaryController;
- }
-
- if (player == PlayerIndex.Unknown)
+ if (state.PlayerId == PlayerIndex.Unknown)
{
return;
}
- if (_configuredNpads[(int)player].State != FilterState.Accepted)
+ ref ShMemNpad currentNpad = ref _device.Hid.SharedMemory.Npads[(int)state.PlayerId];
+
+ if (currentNpad.Header.Type == ControllerType.None)
{
return;
}
- ref ShMemNpad currentNpad = ref _device.Hid.SharedMemory.Npads[(int)player];
- ref NpadLayout currentLayout = ref currentNpad.Layouts[(int)ControllerTypeToLayout(currentNpad.Header.Type)];
+ ref NpadLayout currentLayout = ref currentNpad.Layouts[(int)ControllerTypeToNpadLayout(currentNpad.Header.Type)];
ref NpadState currentEntry = ref currentLayout.Entries[(int)currentLayout.Header.LatestEntry];
- currentEntry.Buttons = buttons;
- currentEntry.LStickX = leftJoystick.Dx;
- currentEntry.LStickY = leftJoystick.Dy;
- currentEntry.RStickX = rightJoystick.Dx;
- currentEntry.RStickY = rightJoystick.Dy;
+ currentEntry.Buttons = state.Buttons;
+ currentEntry.LStickX = state.LStick.Dx;
+ currentEntry.LStickY = state.LStick.Dy;
+ currentEntry.RStickX = state.RStick.Dx;
+ currentEntry.RStickY = state.RStick.Dy;
// Mirror data to Default layout just in case
ref NpadLayout mainLayout = ref currentNpad.Layouts[(int)NpadLayoutsIndex.SystemExternal];
diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs b/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs
index c2cd8432..9db5b518 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs
@@ -35,5 +35,19 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer
PlayerIndex.Unknown => NpadIdType.Unknown,
_ => throw new ArgumentOutOfRangeException(nameof(index))
};
+
+ public static long GetLedPatternFromNpadId(NpadIdType npadIdType)
+ => npadIdType switch
+ {
+ NpadIdType.Player1 => 0b0001,
+ NpadIdType.Player2 => 0b0011,
+ NpadIdType.Player3 => 0b0111,
+ NpadIdType.Player4 => 0b1111,
+ NpadIdType.Player5 => 0b1001,
+ NpadIdType.Player6 => 0b0101,
+ NpadIdType.Player7 => 0b1101,
+ NpadIdType.Player8 => 0b0110,
+ _ => 0b0000
+ };
}
} \ 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 3059d947..ec4c0980 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
@@ -594,9 +594,18 @@ namespace Ryujinx.HLE.HOS.Services.Hid
NpadIdType[] supportedPlayerIds = new NpadIdType[arraySize];
+ context.Device.Hid.Npads.ClearSupportedPlayers();
+
for (int i = 0; i < arraySize; ++i)
{
- supportedPlayerIds[i] = context.Memory.Read<NpadIdType>((ulong)(context.Request.PtrBuff[0].Position + i * 4));
+ NpadIdType id = context.Memory.Read<NpadIdType>((ulong)(context.Request.PtrBuff[0].Position + i * 4));
+
+ if (id >= 0)
+ {
+ context.Device.Hid.Npads.SetSupportedPlayer(HidUtils.GetIndexFromNpadIdType(id));
+ }
+
+ supportedPlayerIds[i] = id;
}
Logger.Stub?.PrintStub(LogClass.ServiceHid, $"{arraySize} " + string.Join(",", supportedPlayerIds));
@@ -665,9 +674,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// GetPlayerLedPattern(uint NpadId) -> ulong LedPattern
public ResultCode GetPlayerLedPattern(ServiceCtx context)
{
- int npadId = context.RequestData.ReadInt32();
+ NpadIdType npadId = (NpadIdType)context.RequestData.ReadInt32();
- long ledPattern = 0;
+ long ledPattern = HidUtils.GetLedPatternFromNpadId(npadId);
context.ResponseData.Write(ledPattern);
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPad.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPad.cs
index e68924da..3fbaa304 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPad.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/DebugPad/DebugPad.cs
@@ -1,3 +1,5 @@
+using Ryujinx.Common.Memory;
+
namespace Ryujinx.HLE.HOS.Services.Hid
{
unsafe struct ShMemDebugPad
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/HidSharedMemory.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/HidSharedMemory.cs
index d2bd8a23..d950425d 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/HidSharedMemory.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/HidSharedMemory.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Runtime.InteropServices;
+using Ryujinx.Common.Memory;
namespace Ryujinx.HLE.HOS.Services.Hid
{
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/Keyboard.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/Keyboard.cs
index dcfa5aa1..e2c1844f 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/Keyboard.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Keyboard/Keyboard.cs
@@ -1,3 +1,5 @@
+using Ryujinx.Common.Memory;
+
namespace Ryujinx.HLE.HOS.Services.Hid
{
unsafe struct ShMemKeyboard
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/Mouse.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/Mouse.cs
index c1f45c5c..6b99e04a 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/Mouse.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Mouse/Mouse.cs
@@ -1,4 +1,6 @@
+using Ryujinx.Common.Memory;
+
namespace Ryujinx.HLE.HOS.Services.Hid
{
unsafe struct ShMemMouse
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/Npad.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/Npad.cs
index 0bb2628f..4ef83f3d 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/Npad.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/Npad.cs
@@ -1,3 +1,5 @@
+using Ryujinx.Common.Memory;
+
namespace Ryujinx.HLE.HOS.Services.Hid
{
// TODO: Add missing structs
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayout.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayout.cs
index 9851a6b1..24c4f4d4 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayout.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayout.cs
@@ -1,3 +1,5 @@
+using Ryujinx.Common.Memory;
+
namespace Ryujinx.HLE.HOS.Services.Hid
{
struct NpadLayout
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSixAxis.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSixAxis.cs
index 5f65db39..a0a39fdc 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSixAxis.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadSixAxis.cs
@@ -1,3 +1,5 @@
+using Ryujinx.Common.Memory;
+
namespace Ryujinx.HLE.HOS.Services.Hid
{
struct NpadSixAxis
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/StructArrayHelpers.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/StructArrayHelpers.cs
deleted file mode 100644
index f40d16a0..00000000
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/StructArrayHelpers.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.HLE.HOS.Services.Hid
-{
-#pragma warning disable CS0169
- struct Array2<T> where T : unmanaged
- {
- T e0, e1;
- public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref e0, 2)[index];
- public int Length => 2;
- }
-
- struct Array3<T> where T : unmanaged
- {
- T e0, e1, e2;
- public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref e0, 3)[index];
- public int Length => 3;
- }
-
- struct Array6<T> where T : unmanaged
- {
- T e0, e1, e2, e3, e4, e5;
- public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref e0, 6)[index];
- public int Length => 6;
- }
-
- struct Array7<T> where T : unmanaged
- {
- T e0, e1, e2, e3, e4, e5, e6;
- public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref e0, 7)[index];
- public int Length => 7;
- }
-
- struct Array10<T> where T : unmanaged
- {
- T e0, e1, e2, e3, e4, e5, e6, e7, e8, e9;
- public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref e0, 10)[index];
- public int Length => 10;
- }
-
- struct Array16<T> where T : unmanaged
- {
- T e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15;
- public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref e0, 16)[index];
- public int Length => 16;
- }
-
- struct Array17<T> where T : unmanaged
- {
- T e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16;
- public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref e0, 17)[index];
- public int Length => 17;
- }
-#pragma warning restore CS0169
-} \ 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
index 618ddd98..5f12295c 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreen.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreen.cs
@@ -1,3 +1,5 @@
+using Ryujinx.Common.Memory;
+
namespace Ryujinx.HLE.HOS.Services.Hid
{
unsafe struct ShMemTouchScreen
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenState.cs
index a0a9cf23..1c85e291 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenState.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenState.cs
@@ -1,3 +1,5 @@
+using Ryujinx.Common.Memory;
+
namespace Ryujinx.HLE.HOS.Services.Hid
{
struct TouchScreenState
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenStateData.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenStateData.cs
index 872064b3..4d4c48d1 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenStateData.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Touchscreen/TouchScreenStateData.cs
@@ -3,13 +3,17 @@ 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