diff --git a/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs b/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs index fd89e8f64..0597cf9b4 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 18a7ba11d..1e85dbf75 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(_hidMemoryAddress); + internal ref SharedMemory SharedMemory => ref _device.Memory.GetRef(_hidMemoryAddress); internal const int SharedMemEntryCount = 17; @@ -22,32 +30,22 @@ namespace Ryujinx.HLE.HOS.Services.Hid public KeyboardDevice Keyboard; public NpadDevices Npads; + private static void CheckTypeSizeOrThrow(int expectedSize) + { + if (Unsafe.SizeOf() != expectedSize) + { + throw new InvalidStructLayoutException(expectedSize); + } + } + static Hid() { - if (Unsafe.SizeOf() != 0x400) - { - throw new InvalidStructLayoutException(0x400); - } - if (Unsafe.SizeOf() != 0x3000) - { - throw new InvalidStructLayoutException(0x3000); - } - if (Unsafe.SizeOf() != 0x400) - { - throw new InvalidStructLayoutException(0x400); - } - if (Unsafe.SizeOf() != 0x400) - { - throw new InvalidStructLayoutException(0x400); - } - if (Unsafe.SizeOf() != 0x5000) - { - throw new InvalidStructLayoutException(0x5000); - } - if (Unsafe.SizeOf() != Horizon.HidSize) - { - throw new InvalidStructLayoutException(Horizon.HidSize); - } + CheckTypeSizeOrThrow>(0x2c8); + CheckTypeSizeOrThrow>(0x2C38); + CheckTypeSizeOrThrow>(0x350); + CheckTypeSizeOrThrow>(0x3D8); + CheckTypeSizeOrThrow>(0x32000); + CheckTypeSizeOrThrow(Horizon.HidSize); } public Hid(in Switch device, ulong sharedHidMemoryAddress) @@ -55,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid _device = device; _hidMemoryAddress = sharedHidMemoryAddress; - device.Memory.ZeroFill(sharedHidMemoryAddress, Horizon.HidSize); + SharedMemory = SharedMemory.Create(); } public void InitDevices() diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/BaseDevice.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/BaseDevice.cs index 59d6dfa3e..e8bf628a2 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 7e708e32c..e3b95390b 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 lifo = ref _device.Hid.SharedMemory.DebugPad; - int currentIndex = UpdateEntriesHeader(ref debugPad.Header, out int previousIndex); + ref DebugPadState previousEntry = ref lifo.GetCurrentEntryRef(); - if (!Active) + DebugPadState newState = new DebugPadState(); + + if (Active) { - return; + // TODO: This is a debug device only present in dev environment, do we want to support it? } - ref DebugPadEntry currentEntry = ref debugPad.Entries[currentIndex]; - DebugPadEntry previousEntry = debugPad.Entries[previousIndex]; + newState.SamplingNumber = previousEntry.SamplingNumber + 1; - currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1; - currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1; + lifo.Write(ref newState); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/KeyboardDevice.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/KeyboardDevice.cs index e8ed6a3e6..99dc078da 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 lifo = ref _device.Hid.SharedMemory.Keyboard; if (!Active) { + lifo.Clear(); + return; } - ref KeyboardState currentEntry = ref keyboard.Entries[currentIndex]; - KeyboardState previousEntry = keyboard.Entries[previousIndex]; + ref KeyboardState previousEntry = ref lifo.GetCurrentEntryRef(); - currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1; - currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1; - - for (int i = 0; i < 8; ++i) + KeyboardState newState = new KeyboardState { - currentEntry.Keys[i] = (uint)keyState.Keys[i]; - } + SamplingNumber = previousEntry.SamplingNumber + 1, + }; - currentEntry.Modifier = (ulong)keyState.Modifier; + keyState.Keys.AsSpan().CopyTo(newState.Keys.RawData.ToSpan()); + newState.Modifiers = (KeyboardModifier)keyState.Modifier; + + lifo.Write(ref newState); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/MouseDevice.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/MouseDevice.cs index ee58a563f..e07c1d206 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 lifo = ref _device.Hid.SharedMemory.Mouse; - int currentIndex = UpdateEntriesHeader(ref mouse.Header, out int previousIndex); - - if (!Active) + ref MouseState previousEntry = ref lifo.GetCurrentEntryRef(); + + MouseState newState = new MouseState() { - return; + SamplingNumber = previousEntry.SamplingNumber + 1, + }; + + if (Active) + { + newState.Buttons = (MouseButton)buttons; + newState.X = mouseX; + newState.Y = mouseY; + newState.DeltaX = mouseX - previousEntry.DeltaX; + newState.DeltaY = mouseY - previousEntry.DeltaY; + newState.WheelDeltaX = scrollX; + newState.WheelDeltaY = scrollY; } - ref MouseState currentEntry = ref mouse.Entries[currentIndex]; - MouseState previousEntry = mouse.Entries[previousIndex]; - - currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1; - currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1; - - currentEntry.Buttons = (ulong)buttons; - - currentEntry.Position = new MousePosition - { - X = mouseX, - Y = mouseY, - VelocityX = mouseX - previousEntry.Position.X, - VelocityY = mouseY - previousEntry.Position.Y, - ScrollVelocityX = scrollX, - ScrollVelocityY = scrollY - }; + lifo.Write(ref newState); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs index 2150f278e..3ff7e7338 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 updated = stackalloc bool[10]; // Update configured inputs for (int i = 0; i < states.Count; ++i) { - UpdateInput(states[i]); + GamepadInput state = states[i]; + + updated[(int)state.PlayerId] = true; + + UpdateInput(state); + } + + for (int i = 0; i < updated.Length; i++) + { + if (!updated[i]) + { + UpdateDisconnectedInput((PlayerIndex)i); + } } } @@ -185,16 +198,16 @@ namespace Ryujinx.HLE.HOS.Services.Hid private void SetupNpad(PlayerIndex player, ControllerType type) { - ref ShMemNpad controller = ref _device.Hid.SharedMemory.Npads[(int)player]; + ref NpadInternalState controller = ref _device.Hid.SharedMemory.Npads[(int)player].InternalState; - ControllerType oldType = controller.Header.Type; + ControllerType oldType = (ControllerType)controller.StyleSet; if (oldType == type) { return; // Already configured } - controller = new ShMemNpad(); // Zero it + controller = NpadInternalState.Create(); // Reset it if (type == ControllerType.None) { @@ -207,87 +220,151 @@ namespace Ryujinx.HLE.HOS.Services.Hid } // TODO: Allow customizing colors at config - NpadStateHeader defaultHeader = new NpadStateHeader - { - IsHalf = false, - SingleColorBody = NpadColor.BodyGray, - SingleColorButtons = NpadColor.ButtonGray, - LeftColorBody = NpadColor.BodyNeonBlue, - LeftColorButtons = NpadColor.ButtonGray, - RightColorBody = NpadColor.BodyNeonRed, - RightColorButtons = NpadColor.ButtonGray - }; + controller.JoyAssignmentMode = NpadJoyAssignmentMode.Dual; + controller.FullKeyColor.FullKeyBody = (uint)NpadColor.BodyGray; + controller.FullKeyColor.FullKeyButtons = (uint)NpadColor.ButtonGray; + controller.JoyColor.LeftBody = (uint)NpadColor.BodyNeonBlue; + controller.JoyColor.LeftButtons = (uint)NpadColor.ButtonGray; + controller.JoyColor.RightBody = (uint)NpadColor.BodyNeonRed; + controller.JoyColor.RightButtons = (uint)NpadColor.ButtonGray; - controller.SystemProperties = NpadSystemProperties.PowerInfo0Connected | - NpadSystemProperties.PowerInfo1Connected | - NpadSystemProperties.PowerInfo2Connected; + controller.SystemProperties = NpadSystemProperties.IsPoweredJoyDual | + NpadSystemProperties.IsPoweredJoyLeft | + NpadSystemProperties.IsPoweredJoyRight; - controller.BatteryState.ToSpan().Fill(DefaultBatteryCharge); + controller.BatteryLevelJoyDual = NpadBatteryLevel.Percent100; + controller.BatteryLevelJoyLeft = NpadBatteryLevel.Percent100; + controller.BatteryLevelJoyRight = NpadBatteryLevel.Percent100; switch (type) { case ControllerType.ProController: - defaultHeader.Type = ControllerType.ProController; + controller.StyleSet = NpadStyleTag.FullKey; controller.DeviceType = DeviceType.FullKey; - controller.SystemProperties |= NpadSystemProperties.AbxyButtonOriented | - NpadSystemProperties.PlusButtonCapability | - NpadSystemProperties.MinusButtonCapability; + controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented | + NpadSystemProperties.IsPlusAvailable | + NpadSystemProperties.IsMinusAvailable; break; case ControllerType.Handheld: - defaultHeader.Type = ControllerType.Handheld; + controller.StyleSet = NpadStyleTag.Handheld; controller.DeviceType = DeviceType.HandheldLeft | DeviceType.HandheldRight; - controller.SystemProperties |= NpadSystemProperties.AbxyButtonOriented | - NpadSystemProperties.PlusButtonCapability | - NpadSystemProperties.MinusButtonCapability; + controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented | + NpadSystemProperties.IsPlusAvailable | + NpadSystemProperties.IsMinusAvailable; break; case ControllerType.JoyconPair: - defaultHeader.Type = ControllerType.JoyconPair; + controller.StyleSet = NpadStyleTag.JoyDual; controller.DeviceType = DeviceType.JoyLeft | DeviceType.JoyRight; - controller.SystemProperties |= NpadSystemProperties.AbxyButtonOriented | - NpadSystemProperties.PlusButtonCapability | - NpadSystemProperties.MinusButtonCapability; + controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented | + NpadSystemProperties.IsPlusAvailable | + NpadSystemProperties.IsMinusAvailable; break; case ControllerType.JoyconLeft: - defaultHeader.Type = ControllerType.JoyconLeft; - defaultHeader.IsHalf = true; + controller.StyleSet = NpadStyleTag.JoyLeft; + controller.JoyAssignmentMode = NpadJoyAssignmentMode.Single; controller.DeviceType = DeviceType.JoyLeft; - controller.SystemProperties |= NpadSystemProperties.SlSrButtonOriented | - NpadSystemProperties.MinusButtonCapability; + controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented | + NpadSystemProperties.IsMinusAvailable; break; case ControllerType.JoyconRight: - defaultHeader.Type = ControllerType.JoyconRight; - defaultHeader.IsHalf = true; + controller.StyleSet = NpadStyleTag.JoyRight; + controller.JoyAssignmentMode = NpadJoyAssignmentMode.Single; controller.DeviceType = DeviceType.JoyRight; - controller.SystemProperties |= NpadSystemProperties.SlSrButtonOriented | - NpadSystemProperties.PlusButtonCapability; + controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented | + NpadSystemProperties.IsPlusAvailable; break; case ControllerType.Pokeball: - defaultHeader.Type = ControllerType.Pokeball; + controller.StyleSet = NpadStyleTag.Palma; controller.DeviceType = DeviceType.Palma; break; } - controller.Header = defaultHeader; - _styleSetUpdateEvents[(int)player].ReadableEvent.Signal(); _activeCount++; Logger.Info?.Print(LogClass.Hid, $"Connected Controller {type} to {player}"); } - private static NpadLayoutsIndex ControllerTypeToNpadLayout(ControllerType controllerType) - => controllerType switch + private ref RingLifo GetCommonStateLifo(ref NpadInternalState npad) { - ControllerType.ProController => NpadLayoutsIndex.ProController, - ControllerType.Handheld => NpadLayoutsIndex.Handheld, - ControllerType.JoyconPair => NpadLayoutsIndex.JoyDual, - ControllerType.JoyconLeft => NpadLayoutsIndex.JoyLeft, - ControllerType.JoyconRight => NpadLayoutsIndex.JoyRight, - ControllerType.Pokeball => NpadLayoutsIndex.Pokeball, - _ => NpadLayoutsIndex.SystemExternal - }; + switch (npad.StyleSet) + { + case NpadStyleTag.FullKey: + return ref npad.FullKey; + case NpadStyleTag.Handheld: + return ref npad.Handheld; + case NpadStyleTag.JoyDual: + return ref npad.JoyDual; + case NpadStyleTag.JoyLeft: + return ref npad.JoyLeft; + case NpadStyleTag.JoyRight: + return ref npad.JoyRight; + case NpadStyleTag.Palma: + return ref npad.Palma; + default: + return ref npad.SystemExt; + } + } + + private void UpdateUnusedInputIfNotEqual(ref RingLifo currentlyUsed, ref RingLifo 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 lifo, ref NpadCommonState state) + { + ref NpadCommonState previousEntry = ref lifo.GetCurrentEntryRef(); + + state.SamplingNumber = previousEntry.SamplingNumber + 1; + + lifo.Write(ref state); + } + + private void UpdateUnusedSixInputIfNotEqual(ref RingLifo currentlyUsed, ref RingLifo possiblyUnused) + { + bool isEquals; + + unsafe + { + var aPointer = Unsafe.AsPointer(ref currentlyUsed); + var bPointer = Unsafe.AsPointer(ref possiblyUnused); + + isEquals = aPointer == bPointer; + } + + if (!isEquals) + { + SixAxisSensorState newState = new SixAxisSensorState(); + + WriteNewSixInputEntry(ref possiblyUnused, ref newState); + } + } + + private void WriteNewSixInputEntry(ref RingLifo 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 lifo = ref GetCommonStateLifo(ref currentNpad); - currentEntry.Buttons = state.Buttons; - currentEntry.LStickX = state.LStick.Dx; - currentEntry.LStickY = state.LStick.Dy; - currentEntry.RStickX = state.RStick.Dx; - currentEntry.RStickY = state.RStick.Dy; + NpadCommonState newState = new NpadCommonState + { + Buttons = (NpadButton)state.Buttons, + AnalogStickL = new AnalogStickState + { + X = state.LStick.Dx, + Y = state.LStick.Dy, + }, + AnalogStickR = new AnalogStickState + { + X = state.RStick.Dx, + Y = state.RStick.Dy, + } + }; + + newState.Attributes = NpadAttribute.IsConnected; + + switch (currentNpad.StyleSet) + { + case NpadStyleTag.Handheld: + case NpadStyleTag.FullKey: + newState.Attributes |= NpadAttribute.IsWired; + break; + case NpadStyleTag.JoyDual: + newState.Attributes |= NpadAttribute.IsLeftConnected | + NpadAttribute.IsRightConnected; + break; + case NpadStyleTag.JoyLeft: + newState.Attributes |= NpadAttribute.IsLeftConnected; + break; + case NpadStyleTag.JoyRight: + newState.Attributes |= NpadAttribute.IsRightConnected; + break; + } + + WriteNewInputEntry(ref lifo, ref newState); // Mirror data to Default layout just in case - ref NpadLayout mainLayout = ref currentNpad.Layouts[(int)NpadLayoutsIndex.SystemExternal]; - mainLayout.Entries[(int)mainLayout.Header.LatestEntry] = currentEntry; + if (!currentNpad.StyleSet.HasFlag(NpadStyleTag.SystemExt)) + { + WriteNewInputEntry(ref currentNpad.SystemExt, ref newState); + } + + UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.FullKey); + UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.Handheld); + UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.JoyDual); + UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.JoyLeft); + UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.JoyRight); + UpdateUnusedInputIfNotEqual(ref lifo, ref currentNpad.Palma); } - private static SixAxixLayoutsIndex ControllerTypeToSixAxisLayout(ControllerType controllerType) - => controllerType switch + private void UpdateDisconnectedInput(PlayerIndex index) { - ControllerType.ProController => SixAxixLayoutsIndex.ProController, - ControllerType.Handheld => SixAxixLayoutsIndex.Handheld, - ControllerType.JoyconPair => SixAxixLayoutsIndex.JoyDualLeft, - ControllerType.JoyconLeft => SixAxixLayoutsIndex.JoyLeft, - ControllerType.JoyconRight => SixAxixLayoutsIndex.JoyRight, - ControllerType.Pokeball => SixAxixLayoutsIndex.Pokeball, - _ => SixAxixLayoutsIndex.SystemExternal - }; + ref NpadInternalState currentNpad = ref _device.Hid.SharedMemory.Npads[(int)index].InternalState; + + NpadCommonState newState = new NpadCommonState(); + + WriteNewInputEntry(ref currentNpad.FullKey, ref newState); + WriteNewInputEntry(ref currentNpad.Handheld, ref newState); + WriteNewInputEntry(ref currentNpad.JoyDual, ref newState); + WriteNewInputEntry(ref currentNpad.JoyLeft, ref newState); + WriteNewInputEntry(ref currentNpad.JoyRight, ref newState); + WriteNewInputEntry(ref currentNpad.Palma, ref newState); + } public void UpdateSixAxis(IList states) { + Span 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 GetSixAxisSensorLifo(ref NpadInternalState npad, bool isRightPair) + { + switch (npad.StyleSet) + { + case NpadStyleTag.FullKey: + return ref npad.FullKeySixAxisSensor; + case NpadStyleTag.Handheld: + return ref npad.HandheldSixAxisSensor; + case NpadStyleTag.JoyDual: + if (isRightPair) + { + return ref npad.JoyDualRightSixAxisSensor; + } + else + { + return ref npad.JoyDualSixAxisSensor; + } + case NpadStyleTag.JoyLeft: + return ref npad.JoyLeftSixAxisSensor; + case NpadStyleTag.JoyRight: + return ref npad.JoyRightSixAxisSensor; + default: + throw new NotImplementedException($"{npad.StyleSet}"); + } } private bool SetSixAxisState(SixAxisInput state, bool isRightPair = false) @@ -354,9 +510,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid return false; } - ref ShMemNpad currentNpad = ref _device.Hid.SharedMemory.Npads[(int)state.PlayerId]; + ref NpadInternalState currentNpad = ref _device.Hid.SharedMemory.Npads[(int)state.PlayerId].InternalState; - if (currentNpad.Header.Type == ControllerType.None) + if (currentNpad.StyleSet == NpadStyleTag.None) { return false; } @@ -382,87 +538,57 @@ namespace Ryujinx.HLE.HOS.Services.Hid Z = state.Rotation.Z }; - ref NpadSixAxis currentLayout = ref currentNpad.Sixaxis[(int)ControllerTypeToSixAxisLayout(currentNpad.Header.Type) + (isRightPair ? 1 : 0)]; - ref SixAxisState currentEntry = ref currentLayout.Entries[(int)currentLayout.Header.LatestEntry]; - - int previousEntryIndex = (int)(currentLayout.Header.LatestEntry == 0 ? - currentLayout.Header.MaxEntryIndex : currentLayout.Header.LatestEntry - 1); - - ref SixAxisState previousEntry = ref currentLayout.Entries[previousEntryIndex]; - - currentEntry.Accelerometer = accel; - currentEntry.Gyroscope = gyro; - currentEntry.Rotations = rotation; - - unsafe + SixAxisSensorState newState = new SixAxisSensorState { - for (int i = 0; i < 9; i++) - { - currentEntry.Orientation[i] = state.Orientation[i]; - } + Acceleration = accel, + AngularVelocity = gyro, + Angle = rotation, + Attributes = SixAxisSensorAttribute.IsConnected + }; + + state.Orientation.AsSpan().CopyTo(newState.Direction.ToSpan()); + + ref RingLifo lifo = ref GetSixAxisSensorLifo(ref currentNpad, isRightPair); + + WriteNewSixInputEntry(ref lifo, ref newState); + + bool needUpdateRight = currentNpad.StyleSet == NpadStyleTag.JoyDual && !isRightPair; + + if (!isRightPair) + { + UpdateUnusedSixInputIfNotEqual(ref lifo, ref currentNpad.FullKeySixAxisSensor); + UpdateUnusedSixInputIfNotEqual(ref lifo, ref currentNpad.HandheldSixAxisSensor); + UpdateUnusedSixInputIfNotEqual(ref lifo, ref currentNpad.JoyDualSixAxisSensor); + UpdateUnusedSixInputIfNotEqual(ref lifo, ref currentNpad.JoyLeftSixAxisSensor); + UpdateUnusedSixInputIfNotEqual(ref lifo, ref currentNpad.JoyRightSixAxisSensor); } - return currentNpad.Header.Type == ControllerType.JoyconPair && !isRightPair; + if (!needUpdateRight) + { + SixAxisSensorState emptyState = new SixAxisSensorState(); + + emptyState.Attributes = SixAxisSensorAttribute.IsConnected; + + WriteNewSixInputEntry(ref currentNpad.JoyDualRightSixAxisSensor, ref emptyState); + } + + return needUpdateRight; } - private void UpdateAllEntries() + private void UpdateDisconnectedInputSixAxis(PlayerIndex index) { - ref Array10 controllers = ref _device.Hid.SharedMemory.Npads; - for (int i = 0; i < controllers.Length; ++i) - { - ref Array7 layouts = ref controllers[i].Layouts; - for (int l = 0; l < layouts.Length; ++l) - { - ref NpadLayout currentLayout = ref layouts[l]; - int currentIndex = UpdateEntriesHeader(ref currentLayout.Header, out int previousIndex); + ref NpadInternalState currentNpad = ref _device.Hid.SharedMemory.Npads[(int)index].InternalState; - ref NpadState currentEntry = ref currentLayout.Entries[currentIndex]; - NpadState previousEntry = currentLayout.Entries[previousIndex]; + SixAxisSensorState newState = new SixAxisSensorState(); - currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1; - currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1; + newState.Attributes = SixAxisSensorAttribute.IsConnected; - if (controllers[i].Header.Type == ControllerType.None) - { - continue; - } - - currentEntry.ConnectionState = NpadConnectionState.ControllerStateConnected; - - switch (controllers[i].Header.Type) - { - case ControllerType.Handheld: - case ControllerType.ProController: - currentEntry.ConnectionState |= NpadConnectionState.ControllerStateWired; - break; - case ControllerType.JoyconPair: - currentEntry.ConnectionState |= NpadConnectionState.JoyLeftConnected | - NpadConnectionState.JoyRightConnected; - break; - case ControllerType.JoyconLeft: - currentEntry.ConnectionState |= NpadConnectionState.JoyLeftConnected; - break; - case ControllerType.JoyconRight: - currentEntry.ConnectionState |= NpadConnectionState.JoyRightConnected; - break; - } - } - - ref Array6 sixaxis = ref controllers[i].Sixaxis; - for (int l = 0; l < sixaxis.Length; ++l) - { - ref NpadSixAxis currentLayout = ref sixaxis[l]; - int currentIndex = UpdateEntriesHeader(ref currentLayout.Header, out int previousIndex); - - ref SixAxisState currentEntry = ref currentLayout.Entries[currentIndex]; - SixAxisState previousEntry = currentLayout.Entries[previousIndex]; - - currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1; - currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1; - - currentEntry._unknown2 = 1; - } - } + WriteNewSixInputEntry(ref currentNpad.FullKeySixAxisSensor, ref newState); + WriteNewSixInputEntry(ref currentNpad.HandheldSixAxisSensor, ref newState); + WriteNewSixInputEntry(ref currentNpad.JoyDualSixAxisSensor, ref newState); + WriteNewSixInputEntry(ref currentNpad.JoyDualRightSixAxisSensor, ref newState); + WriteNewSixInputEntry(ref currentNpad.JoyLeftSixAxisSensor, ref newState); + WriteNewSixInputEntry(ref currentNpad.JoyRightSixAxisSensor, ref newState); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/TouchDevice.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/TouchDevice.cs index 10c344530..432a37e33 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 lifo = ref _device.Hid.SharedMemory.TouchScreen; - int currentIndex = UpdateEntriesHeader(ref touchscreen.Header, out int previousIndex); + ref TouchScreenState previousEntry = ref lifo.GetCurrentEntryRef(); - if (!Active) + TouchScreenState newState = new TouchScreenState { - return; - } + SamplingNumber = previousEntry.SamplingNumber + 1 + }; - ref TouchScreenState currentEntry = ref touchscreen.Entries[currentIndex]; - TouchScreenState previousEntry = touchscreen.Entries[previousIndex]; - - currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1; - currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1; - - currentEntry.NumTouches = (ulong)points.Length; - - int pointsLength = Math.Min(points.Length, currentEntry.Touches.Length); - - for (int i = 0; i < pointsLength; ++i) + if (Active) { - TouchPoint pi = points[i]; - currentEntry.Touches[i] = new TouchScreenStateData + newState.TouchesCount = points.Length; + + int pointsLength = Math.Min(points.Length, newState.Touches.Length); + + for (int i = 0; i < pointsLength; ++i) { - SampleTimestamp = currentEntry.SampleTimestamp, - X = pi.X, - Y = pi.Y, - TouchIndex = (uint)i, - DiameterX = pi.DiameterX, - DiameterY = pi.DiameterY, - Angle = pi.Angle - }; + TouchPoint pi = points[i]; + newState.Touches[i] = new TouchState + { + DeltaTime = newState.SamplingNumber, + X = pi.X, + Y = pi.Y, + FingerId = (uint)i, + DiameterX = pi.DiameterX, + DiameterY = pi.DiameterY, + RotationAngle = pi.Angle + }; + } } + + lifo.Write(ref newState); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/KeyboardInput.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/KeyboardInput.cs index 266812709..be6857fb3 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 2ab305ac6..e3c22edf6 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 5a8d51c6e..000000000 --- a/Ryujinx.HLE/HOS/Services/Hid/Types/Boolean32.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.HLE.HOS.Services.Hid -{ - struct Boolean32 - { - private uint _value; - public static implicit operator bool(Boolean32 value) => (value._value & 1) != 0; - public static implicit operator Boolean32(bool value) => new Boolean32() { _value = value ? 1u : 0u }; - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/HidVector.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/HidVector.cs similarity index 70% rename from Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/HidVector.cs rename to Ryujinx.HLE/HOS/Services/Hid/Types/HidVector.cs index b41bcb2e8..18d9fd9c9 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 57b4b3666..3c311e218 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/NpadColor.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/NpadColor.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.HOS.Services.Hid { - public enum NpadColor : int + public enum NpadColor : uint { BodyGray = 0x828282, BodyNeonRed = 0xFF3C28, diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadJoyHoldType.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/NpadJoyHoldType.cs similarity index 60% rename from Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadJoyHoldType.cs rename to Ryujinx.HLE/HOS/Services/Hid/Types/NpadJoyHoldType.cs index a6f297606..d3b51a24c 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 f83fdcdf5..000000000 --- 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 3fbaa304c..000000000 --- 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 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 3089fc5b1..000000000 --- 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 d950425d9..000000000 --- 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 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 e2c1844f4..000000000 --- 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 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 1f54a4fd5..000000000 --- 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 6b99e04a8..000000000 --- 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 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 e94c9e0cd..000000000 --- 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 7856b09d2..000000000 --- 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 b94ab172c..000000000 --- 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 f6d7b783c..000000000 --- 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 4ef83f3d1..000000000 --- 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 Layouts; // One for each NpadLayoutsIndex - public Array6 Sixaxis; - public DeviceType DeviceType; - uint _padding1; - public NpadSystemProperties SystemProperties; - public uint NpadSystemButtonProperties; - public Array3 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 ccc7cb8df..000000000 --- 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 60f64fd37..000000000 --- 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 24c4f4d44..000000000 --- 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 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 c44193369..000000000 --- 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 a0a39fdca..000000000 --- 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 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 60a5f9d36..000000000 --- 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 006d4357f..000000000 --- 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 708f7da9c..000000000 --- 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 a8795fc05..000000000 --- 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 12974e7e3..000000000 --- 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 5f12295cf..000000000 --- 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 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 1c85e2914..000000000 --- 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 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 4d4c48d1a..000000000 --- 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 000000000..bf4b58885 --- /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 000000000..45b92ba98 --- /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 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 000000000..08f76747e --- /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 000000000..615e38930 --- /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 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> _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 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 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> ReadEntries(uint maxCount) + { + ulong countAvailaible = Math.Min(Math.Max(0, ReadCurrentCount()), maxCount); + + if (countAvailaible == 0) + { + return ReadOnlySpan>.Empty; + } + + ulong index = ReadCurrentIndex(); + + AtomicStorage[] result = new AtomicStorage[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 Create() + { + return new RingLifo + { + _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 000000000..ec5bd3c88 --- /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 000000000..e8f283170 --- /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 000000000..3e1e1ad8e --- /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 000000000..22df7c791 --- /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 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 000000000..01c2bb304 --- /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 000000000..72d1603aa --- /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 000000000..376085066 --- /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 000000000..5ffba0d7b --- /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 000000000..7e35140c6 --- /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 000000000..67ad6bf1a --- /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 000000000..b02018353 --- /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 000000000..0960b7bf3 --- /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 000000000..477dfd10f --- /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 000000000..5b3e13a72 --- /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 000000000..1e547cc8f --- /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 000000000..eaccef802 --- /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 000000000..990eafb26 --- /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 000000000..52668f85e --- /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 000000000..f225ff677 --- /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 FullKey; + public RingLifo Handheld; + public RingLifo JoyDual; + public RingLifo JoyLeft; + public RingLifo JoyRight; + public RingLifo Palma; + public RingLifo SystemExt; + public RingLifo FullKeySixAxisSensor; + public RingLifo HandheldSixAxisSensor; + public RingLifo JoyDualSixAxisSensor; + public RingLifo JoyDualRightSixAxisSensor; + public RingLifo JoyLeftSixAxisSensor; + public RingLifo 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 GcTrigger; + public NpadLarkType LarkTypeLeftAndMain; + public NpadLarkType LarkTypeRight; + public NpadLuciaType LuciaType; + public uint Unknown43EC; + + public static NpadInternalState Create() + { + return new NpadInternalState + { + FullKey = RingLifo.Create(), + Handheld = RingLifo.Create(), + JoyDual = RingLifo.Create(), + JoyLeft = RingLifo.Create(), + JoyRight = RingLifo.Create(), + Palma = RingLifo.Create(), + SystemExt = RingLifo.Create(), + FullKeySixAxisSensor = RingLifo.Create(), + HandheldSixAxisSensor = RingLifo.Create(), + JoyDualSixAxisSensor = RingLifo.Create(), + JoyDualRightSixAxisSensor = RingLifo.Create(), + JoyLeftSixAxisSensor = RingLifo.Create(), + JoyRightSixAxisSensor = RingLifo.Create(), + GcTrigger = RingLifo.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 000000000..871c4c5a4 --- /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 000000000..3986dd5e0 --- /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 000000000..a487a911a --- /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 000000000..951484857 --- /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 000000000..ed9e7c0df --- /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 000000000..f31978e24 --- /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 +{ + /// + /// Nintendo pad style + /// + [Flags] + enum NpadStyleTag : uint + { + /// + /// No type. + /// + None = 0, + + /// + /// Pro controller. + /// + FullKey = 1 << 0, + + /// + /// Joy-Con controller in handheld mode. + /// + Handheld = 1 << 1, + + /// + /// Joy-Con controller in dual mode. + /// + JoyDual = 1 << 2, + + /// + /// Joy-Con left controller in single mode. + /// + JoyLeft = 1 << 3, + + /// + /// Joy-Con right controller in single mode. + /// + JoyRight = 1 << 4, + + /// + /// GameCube controller. + /// + Gc = 1 << 5, + + /// + /// Poké Ball Plus controller. + /// + Palma = 1 << 6, + + /// + /// NES and Famicom controller. + /// + Lark = 1 << 7, + + /// + /// NES and Famicom controller in handheld mode. + /// + HandheldLark = 1 << 8, + + /// + /// SNES controller. + /// + Lucia = 1 << 9, + + /// + /// Generic external controller. + /// + SystemExt = 1 << 29, + + /// + /// Generic controller. + /// + 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 000000000..686032714 --- /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 000000000..13444555e --- /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 000000000..7ed46d981 --- /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 000000000..d024b0b0e --- /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 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 000000000..48acfc3f3 --- /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 +{ + /// + /// Represent the shared memory shared between applications for input. + /// + [StructLayout(LayoutKind.Explicit, Size = 0x40000)] + struct SharedMemory + { + /// + /// Debug controller. + /// + [FieldOffset(0)] + public RingLifo DebugPad; + + /// + /// Touchscreen. + /// + [FieldOffset(0x400)] + public RingLifo TouchScreen; + + /// + /// Mouse. + /// + [FieldOffset(0x3400)] + public RingLifo Mouse; + + /// + /// Keyboard. + /// + [FieldOffset(0x3800)] + public RingLifo Keyboard; + + /// + /// Nintendo Pads. + /// + [FieldOffset(0x9A00)] + public Array10 Npads; + + public static SharedMemory Create() + { + SharedMemory result = new SharedMemory + { + DebugPad = RingLifo.Create(), + TouchScreen = RingLifo.Create(), + Mouse = RingLifo.Create(), + Keyboard = RingLifo.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 000000000..8a8f9cc1e --- /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 000000000..8203e49b5 --- /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 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 000000000..ba621a2b0 --- /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 d3553d646..e1a8e2d75 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)