diff --git a/Ryujinx.HLE/DeviceMemory.cs b/Ryujinx.HLE/DeviceMemory.cs index 524adb846..3553a6e71 100644 --- a/Ryujinx.HLE/DeviceMemory.cs +++ b/Ryujinx.HLE/DeviceMemory.cs @@ -1,5 +1,6 @@ using ChocolArm64.Memory; using System; +using System.Runtime.InteropServices; namespace Ryujinx.HLE { @@ -98,6 +99,11 @@ namespace Ryujinx.HLE *((ulong*)(_ramPtr + position)) = value; } + public unsafe void WriteStruct(long position, T value) + { + Marshal.StructureToPtr(value, (IntPtr)(_ramPtr + position), false); + } + public void FillWithZeros(long position, int size) { int size8 = size & ~(8 - 1); @@ -180,4 +186,4 @@ namespace Ryujinx.HLE MemoryManagement.Free(RamPointer); } } -} \ No newline at end of file +} diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidUtils.cs b/Ryujinx.HLE/HOS/Services/Hid/HidUtils.cs index 051be7a88..fd540c7c8 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/HidUtils.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/HidUtils.cs @@ -5,39 +5,39 @@ namespace Ryujinx.HLE.HOS.Services.Hid { static class HidUtils { - public static HidControllerId GetIndexFromNpadIdType(NpadIdType npadIdType) + public static ControllerId GetIndexFromNpadIdType(NpadIdType npadIdType) { switch (npadIdType) { - case NpadIdType.Player1: return HidControllerId.ControllerPlayer1; - case NpadIdType.Player2: return HidControllerId.ControllerPlayer2; - case NpadIdType.Player3: return HidControllerId.ControllerPlayer3; - case NpadIdType.Player4: return HidControllerId.ControllerPlayer4; - case NpadIdType.Player5: return HidControllerId.ControllerPlayer5; - case NpadIdType.Player6: return HidControllerId.ControllerPlayer6; - case NpadIdType.Player7: return HidControllerId.ControllerPlayer7; - case NpadIdType.Player8: return HidControllerId.ControllerPlayer8; - case NpadIdType.Handheld: return HidControllerId.ControllerHandheld; - case NpadIdType.Unknown: return HidControllerId.ControllerUnknown; + case NpadIdType.Player1: return ControllerId.ControllerPlayer1; + case NpadIdType.Player2: return ControllerId.ControllerPlayer2; + case NpadIdType.Player3: return ControllerId.ControllerPlayer3; + case NpadIdType.Player4: return ControllerId.ControllerPlayer4; + case NpadIdType.Player5: return ControllerId.ControllerPlayer5; + case NpadIdType.Player6: return ControllerId.ControllerPlayer6; + case NpadIdType.Player7: return ControllerId.ControllerPlayer7; + case NpadIdType.Player8: return ControllerId.ControllerPlayer8; + case NpadIdType.Handheld: return ControllerId.ControllerHandheld; + case NpadIdType.Unknown: return ControllerId.ControllerUnknown; default: throw new ArgumentOutOfRangeException(nameof(npadIdType)); } } - public static NpadIdType GetNpadIdTypeFromIndex(HidControllerId index) + public static NpadIdType GetNpadIdTypeFromIndex(ControllerId index) { switch (index) { - case HidControllerId.ControllerPlayer1: return NpadIdType.Player1; - case HidControllerId.ControllerPlayer2: return NpadIdType.Player2; - case HidControllerId.ControllerPlayer3: return NpadIdType.Player3; - case HidControllerId.ControllerPlayer4: return NpadIdType.Player4; - case HidControllerId.ControllerPlayer5: return NpadIdType.Player5; - case HidControllerId.ControllerPlayer6: return NpadIdType.Player6; - case HidControllerId.ControllerPlayer7: return NpadIdType.Player7; - case HidControllerId.ControllerPlayer8: return NpadIdType.Player8; - case HidControllerId.ControllerHandheld: return NpadIdType.Handheld; - case HidControllerId.ControllerUnknown: return NpadIdType.Unknown; + case ControllerId.ControllerPlayer1: return NpadIdType.Player1; + case ControllerId.ControllerPlayer2: return NpadIdType.Player2; + case ControllerId.ControllerPlayer3: return NpadIdType.Player3; + case ControllerId.ControllerPlayer4: return NpadIdType.Player4; + case ControllerId.ControllerPlayer5: return NpadIdType.Player5; + case ControllerId.ControllerPlayer6: return NpadIdType.Player6; + case ControllerId.ControllerPlayer7: return NpadIdType.Player7; + case ControllerId.ControllerPlayer8: return NpadIdType.Player8; + case ControllerId.ControllerHandheld: return NpadIdType.Handheld; + case ControllerId.ControllerUnknown: return NpadIdType.Unknown; default: throw new ArgumentOutOfRangeException(nameof(index)); } diff --git a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs index 22bd28f30..7d77ff32b 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs @@ -569,8 +569,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid // SetSupportedNpadIdType(nn::applet::AppletResourceUserId, array) public ResultCode SetSupportedNpadIdType(ServiceCtx context) { - long appletResourceUserId = context.RequestData.ReadInt64(); - HidControllerId npadIdType = (HidControllerId)context.RequestData.ReadInt64(); + long appletResourceUserId = context.RequestData.ReadInt64(); + ControllerId npadIdType = (ControllerId)context.RequestData.ReadInt64(); Logger.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, npadIdType }); @@ -687,8 +687,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid // SetNpadJoyAssignmentModeSingleByDefault(uint HidControllerId, nn::applet::AppletResourceUserId) public ResultCode SetNpadJoyAssignmentModeSingleByDefault(ServiceCtx context) { - HidControllerId hidControllerId = (HidControllerId)context.RequestData.ReadInt32(); - long appletResourceUserId = context.RequestData.ReadInt64(); + ControllerId hidControllerId = (ControllerId)context.RequestData.ReadInt32(); + long appletResourceUserId = context.RequestData.ReadInt64(); _npadJoyAssignmentMode = HidNpadJoyAssignmentMode.Single; @@ -701,7 +701,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid // SetNpadJoyAssignmentModeSingle(uint HidControllerId, nn::applet::AppletResourceUserId, long HidNpadJoyDeviceType) public ResultCode SetNpadJoyAssignmentModeSingle(ServiceCtx context) { - HidControllerId hidControllerId = (HidControllerId)context.RequestData.ReadInt32(); + ControllerId hidControllerId = (ControllerId)context.RequestData.ReadInt32(); long appletResourceUserId = context.RequestData.ReadInt64(); HidNpadJoyDeviceType hidNpadJoyDeviceType = (HidNpadJoyDeviceType)context.RequestData.ReadInt64(); @@ -716,8 +716,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid // SetNpadJoyAssignmentModeDual(uint HidControllerId, nn::applet::AppletResourceUserId) public ResultCode SetNpadJoyAssignmentModeDual(ServiceCtx context) { - HidControllerId hidControllerId = (HidControllerId)context.RequestData.ReadInt32(); - long appletResourceUserId = context.RequestData.ReadInt64(); + ControllerId hidControllerId = (ControllerId)context.RequestData.ReadInt32(); + long appletResourceUserId = context.RequestData.ReadInt64(); _npadJoyAssignmentMode = HidNpadJoyAssignmentMode.Dual; @@ -830,7 +830,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid // SetNpadJoyAssignmentModeSingleWithDestination(uint HidControllerId, long HidNpadJoyDeviceType, nn::applet::AppletResourceUserId) -> bool Unknown0, uint Unknown1 public ResultCode SetNpadJoyAssignmentModeSingleWithDestination(ServiceCtx context) { - HidControllerId hidControllerId = (HidControllerId)context.RequestData.ReadInt32(); + ControllerId hidControllerId = (ControllerId)context.RequestData.ReadInt32(); HidNpadJoyDeviceType hidNpadJoyDeviceType = (HidNpadJoyDeviceType)context.RequestData.ReadInt64(); long appletResourceUserId = context.RequestData.ReadInt64(); diff --git a/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs b/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs index d6659fd8a..d2991d0fd 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs @@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Irs return ResultCode.NpadIdOutOfRange; } - HidControllerId irCameraHandle = HidUtils.GetIndexFromNpadIdType(npadIdType); + ControllerId irCameraHandle = HidUtils.GetIndexFromNpadIdType(npadIdType); context.ResponseData.Write((int)irCameraHandle); diff --git a/Ryujinx.HLE/HOS/Services/Nfc/Nfp/Device.cs b/Ryujinx.HLE/HOS/Services/Nfc/Nfp/Device.cs index a1f58dae1..3c49ee510 100644 --- a/Ryujinx.HLE/HOS/Services/Nfc/Nfp/Device.cs +++ b/Ryujinx.HLE/HOS/Services/Nfc/Nfp/Device.cs @@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp public DeviceState State = DeviceState.Unavailable; - public HidControllerId Handle; - public NpadIdType NpadIdType; + public ControllerId Handle; + public NpadIdType NpadIdType; } } \ No newline at end of file diff --git a/Ryujinx.HLE/Input/Controller/BaseController.cs b/Ryujinx.HLE/Input/Controller/BaseController.cs new file mode 100644 index 000000000..dfd54a832 --- /dev/null +++ b/Ryujinx.HLE/Input/Controller/BaseController.cs @@ -0,0 +1,142 @@ +using static Ryujinx.HLE.Input.Hid; + +namespace Ryujinx.HLE.Input +{ + public abstract class BaseController : IHidDevice + { + protected ControllerStatus HidControllerType; + protected ControllerId ControllerId; + + private long _currentLayoutOffset; + private long _mainLayoutOffset; + + protected long DeviceStateOffset => Offset + 0x4188; + + protected Switch Device { get; } + + public long Offset { get; private set; } + public bool Connected { get; protected set; } + + public ControllerHeader Header { get; private set; } + public ControllerStateHeader CurrentStateHeader { get; private set; } + public ControllerDeviceState DeviceState { get; private set; } + public ControllerLayouts CurrentLayout { get; private set; } + public ControllerState LastInputState { get; set; } + public ControllerConnectionState ConnectionState { get; protected set; } + + public BaseController(Switch device, ControllerStatus controllerType) + { + Device = device; + HidControllerType = controllerType; + } + + protected void Initialize( + bool isHalf, + (NpadColor left, NpadColor right) bodyColors, + (NpadColor left, NpadColor right) buttonColors, + ControllerColorDescription singleColorDesc = 0, + ControllerColorDescription splitColorDesc = 0, + NpadColor singleBodyColor = 0, + NpadColor singleButtonColor = 0 + ) + { + Header = new ControllerHeader() + { + IsJoyConHalf = isHalf ? 1 : 0, + LeftBodyColor = bodyColors.left, + LeftButtonColor = buttonColors.left, + RightBodyColor = bodyColors.right, + RightButtonColor = buttonColors.right, + Status = HidControllerType, + SingleBodyColor = singleBodyColor, + SingleButtonColor = singleButtonColor, + SplitColorDescription = splitColorDesc, + SingleColorDescription = singleColorDesc, + }; + + CurrentStateHeader = new ControllerStateHeader + { + EntryCount = HidEntryCount, + MaxEntryCount = HidEntryCount - 1, + CurrentEntryIndex = -1 + }; + + DeviceState = new ControllerDeviceState() + { + PowerInfo0BatteryState = BatteryState.Percent100, + PowerInfo1BatteryState = BatteryState.Percent100, + PowerInfo2BatteryState = BatteryState.Percent100, + DeviceType = ControllerDeviceType.NPadLeftController | ControllerDeviceType.NPadRightController, + DeviceFlags = DeviceFlags.PowerInfo0Connected + | DeviceFlags.PowerInfo1Connected + | DeviceFlags.PowerInfo2Connected + }; + + LastInputState = new ControllerState() + { + SamplesTimestamp = -1, + SamplesTimestamp2 = -1 + }; + } + + public virtual void Connect(ControllerId controllerId) + { + ControllerId = controllerId; + + Offset = Device.Hid.HidPosition + HidControllersOffset + (int)controllerId * HidControllerSize; + + _mainLayoutOffset = Offset + HidControllerHeaderSize + + ((int)ControllerLayouts.Main * HidControllerLayoutsSize); + + Device.Memory.FillWithZeros(Offset, 0x5000); + Device.Memory.WriteStruct(Offset, Header); + Device.Memory.WriteStruct(DeviceStateOffset, DeviceState); + + Connected = true; + } + + public void SetLayout(ControllerLayouts controllerLayout) + { + CurrentLayout = controllerLayout; + + _currentLayoutOffset = Offset + HidControllerHeaderSize + + ((int)controllerLayout * HidControllerLayoutsSize); + } + + public void SendInput( + ControllerButtons buttons, + JoystickPosition leftStick, + JoystickPosition rightStick) + { + ControllerState currentInput = new ControllerState() + { + SamplesTimestamp = (long)LastInputState.SamplesTimestamp + 1, + SamplesTimestamp2 = (long)LastInputState.SamplesTimestamp + 1, + ButtonState = buttons, + ConnectionState = ConnectionState, + LeftStick = leftStick, + RightStick = rightStick + }; + + ControllerStateHeader newInputStateHeader = new ControllerStateHeader + { + EntryCount = HidEntryCount, + MaxEntryCount = HidEntryCount - 1, + CurrentEntryIndex = (CurrentStateHeader.CurrentEntryIndex + 1) % HidEntryCount, + Timestamp = GetTimestamp(), + }; + + Device.Memory.WriteStruct(_currentLayoutOffset, newInputStateHeader); + Device.Memory.WriteStruct(_mainLayoutOffset, newInputStateHeader); + + long currentInputStateOffset = HidControllersLayoutHeaderSize + + newInputStateHeader.CurrentEntryIndex * HidControllersInputEntrySize; + + Device.Memory.WriteStruct(_currentLayoutOffset + currentInputStateOffset, currentInput); + Device.Memory.WriteStruct(_mainLayoutOffset + currentInputStateOffset, currentInput); + + LastInputState = currentInput; + CurrentStateHeader = newInputStateHeader; + } + } +} diff --git a/Ryujinx.HLE/Input/Controller/NpadController.cs b/Ryujinx.HLE/Input/Controller/NpadController.cs new file mode 100644 index 000000000..b4304b8f3 --- /dev/null +++ b/Ryujinx.HLE/Input/Controller/NpadController.cs @@ -0,0 +1,68 @@ +namespace Ryujinx.HLE.Input +{ + public class NpadController : BaseController + { + private (NpadColor Left, NpadColor Right) _npadBodyColors; + private (NpadColor Left, NpadColor Right) _npadButtonColors; + + private bool _isHalf; + + public NpadController( + ControllerStatus controllerStatus, + Switch device, + (NpadColor, NpadColor) npadBodyColors, + (NpadColor, NpadColor) npadButtonColors) : base(device, controllerStatus) + { + _npadBodyColors = npadBodyColors; + _npadButtonColors = npadButtonColors; + } + + public override void Connect(ControllerId controllerId) + { + if (HidControllerType != ControllerStatus.NpadLeft && HidControllerType != ControllerStatus.NpadRight) + { + _isHalf = false; + } + + ConnectionState = ControllerConnectionState.ControllerStateConnected; + + if (controllerId == ControllerId.ControllerHandheld) + ConnectionState |= ControllerConnectionState.ControllerStateWired; + + ControllerColorDescription singleColorDesc = + ControllerColorDescription.ColorDescriptionColorsNonexistent; + + ControllerColorDescription splitColorDesc = 0; + + NpadColor singleBodyColor = NpadColor.Black; + NpadColor singleButtonColor = NpadColor.Black; + + Initialize(_isHalf, + (_npadBodyColors.Left, _npadBodyColors.Right), + (_npadButtonColors.Left, _npadButtonColors.Right), + singleColorDesc, + splitColorDesc, + singleBodyColor, + singleButtonColor ); + + base.Connect(controllerId); + + var _currentLayout = ControllerLayouts.HandheldJoined; + + switch (HidControllerType) + { + case ControllerStatus.NpadLeft: + _currentLayout = ControllerLayouts.Left; + break; + case ControllerStatus.NpadRight: + _currentLayout = ControllerLayouts.Right; + break; + case ControllerStatus.NpadPair: + _currentLayout = ControllerLayouts.Joined; + break; + } + + SetLayout(_currentLayout); + } + } +} diff --git a/Ryujinx.HLE/Input/Controller/ProController.cs b/Ryujinx.HLE/Input/Controller/ProController.cs new file mode 100644 index 000000000..ae574260f --- /dev/null +++ b/Ryujinx.HLE/Input/Controller/ProController.cs @@ -0,0 +1,42 @@ +namespace Ryujinx.HLE.Input +{ + public class ProController : BaseController + { + private bool _wired = false; + + private NpadColor _bodyColor; + private NpadColor _buttonColor; + + public ProController(Switch device, + NpadColor bodyColor, + NpadColor buttonColor) : base(device, ControllerStatus.ProController) + { + _wired = true; + + _bodyColor = bodyColor; + _buttonColor = buttonColor; + } + + public override void Connect(ControllerId controllerId) + { + ControllerColorDescription singleColorDesc = + ControllerColorDescription.ColorDescriptionColorsNonexistent; + + ControllerColorDescription splitColorDesc = 0; + + ConnectionState = ControllerConnectionState.ControllerStateConnected | ControllerConnectionState.ControllerStateWired; + + Initialize(false, + (0, 0), + (0, 0), + singleColorDesc, + splitColorDesc, + _bodyColor, + _buttonColor); + + base.Connect(controllerId); + + SetLayout(ControllerLayouts.ProController); + } + } +} diff --git a/Ryujinx.HLE/Input/Controller/Types/BatteryState.cs b/Ryujinx.HLE/Input/Controller/Types/BatteryState.cs new file mode 100644 index 000000000..4279d7a03 --- /dev/null +++ b/Ryujinx.HLE/Input/Controller/Types/BatteryState.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.HLE.Input +{ + public enum BatteryState : int + { + // TODO : Check if these are the correct states + Percent0 = 0, + Percent25 = 1, + Percent50 = 2, + Percent75 = 3, + Percent100 = 4 + } +} diff --git a/Ryujinx.HLE/Input/HidControllerButtons.cs b/Ryujinx.HLE/Input/Controller/Types/ControllerButtons.cs similarity index 95% rename from Ryujinx.HLE/Input/HidControllerButtons.cs rename to Ryujinx.HLE/Input/Controller/Types/ControllerButtons.cs index 07a3a118e..879257f26 100644 --- a/Ryujinx.HLE/Input/HidControllerButtons.cs +++ b/Ryujinx.HLE/Input/Controller/Types/ControllerButtons.cs @@ -3,7 +3,7 @@ using System; namespace Ryujinx.HLE.Input { [Flags] - public enum HidControllerButtons + public enum ControllerButtons : long { A = 1 << 0, B = 1 << 1, diff --git a/Ryujinx.HLE/Input/Controller/Types/ControllerColorDescription.cs b/Ryujinx.HLE/Input/Controller/Types/ControllerColorDescription.cs new file mode 100644 index 000000000..c31f41a3f --- /dev/null +++ b/Ryujinx.HLE/Input/Controller/Types/ControllerColorDescription.cs @@ -0,0 +1,10 @@ +using System; + +namespace Ryujinx.HLE.Input +{ + [Flags] + public enum ControllerColorDescription : int + { + ColorDescriptionColorsNonexistent = (1 << 1) + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/Input/HidControllerConnState.cs b/Ryujinx.HLE/Input/Controller/Types/ControllerConnectionState.cs similarity index 75% rename from Ryujinx.HLE/Input/HidControllerConnState.cs rename to Ryujinx.HLE/Input/Controller/Types/ControllerConnectionState.cs index ef41cbb80..526da1ff1 100644 --- a/Ryujinx.HLE/Input/HidControllerConnState.cs +++ b/Ryujinx.HLE/Input/Controller/Types/ControllerConnectionState.cs @@ -3,7 +3,7 @@ using System; namespace Ryujinx.HLE.Input { [Flags] - public enum HidControllerConnState + public enum ControllerConnectionState : long { ControllerStateConnected = (1 << 0), ControllerStateWired = (1 << 1) diff --git a/Ryujinx.HLE/Input/Controller/Types/ControllerDeviceState.cs b/Ryujinx.HLE/Input/Controller/Types/ControllerDeviceState.cs new file mode 100644 index 000000000..45895a1e9 --- /dev/null +++ b/Ryujinx.HLE/Input/Controller/Types/ControllerDeviceState.cs @@ -0,0 +1,18 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.Input +{ + [StructLayout(LayoutKind.Sequential)] + public unsafe struct ControllerDeviceState + { + public ControllerDeviceType DeviceType; + public int Padding; + public DeviceFlags DeviceFlags; + public int UnintendedHomeButtonInputProtectionEnabled; + public BatteryState PowerInfo0BatteryState; + public BatteryState PowerInfo1BatteryState; + public BatteryState PowerInfo2BatteryState; + public fixed byte ControllerMac[16]; + public fixed byte ControllerMac2[16]; + } +} diff --git a/Ryujinx.HLE/Input/Controller/Types/ControllerDeviceType.cs b/Ryujinx.HLE/Input/Controller/Types/ControllerDeviceType.cs new file mode 100644 index 000000000..8043d8a0f --- /dev/null +++ b/Ryujinx.HLE/Input/Controller/Types/ControllerDeviceType.cs @@ -0,0 +1,12 @@ +using System; + +namespace Ryujinx.HLE.Input +{ + [Flags] + public enum ControllerDeviceType : int + { + ProController = 1 << 0, + NPadLeftController = 1 << 4, + NPadRightController = 1 << 5, + } +} diff --git a/Ryujinx.HLE/Input/Controller/Types/ControllerHeader.cs b/Ryujinx.HLE/Input/Controller/Types/ControllerHeader.cs new file mode 100644 index 000000000..cbb5b6f56 --- /dev/null +++ b/Ryujinx.HLE/Input/Controller/Types/ControllerHeader.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.Input +{ + [StructLayout(LayoutKind.Sequential)] + public struct ControllerHeader + { + public ControllerStatus Status; + public int IsJoyConHalf; + public ControllerColorDescription SingleColorDescription; + public NpadColor SingleBodyColor; + public NpadColor SingleButtonColor; + public ControllerColorDescription SplitColorDescription; + public NpadColor RightBodyColor; + public NpadColor RightButtonColor; + public NpadColor LeftBodyColor; + public NpadColor LeftButtonColor; + } +} diff --git a/Ryujinx.HLE/Input/HidControllerId.cs b/Ryujinx.HLE/Input/Controller/Types/ControllerId.cs similarity index 91% rename from Ryujinx.HLE/Input/HidControllerId.cs rename to Ryujinx.HLE/Input/Controller/Types/ControllerId.cs index 60faf822d..c82056c68 100644 --- a/Ryujinx.HLE/Input/HidControllerId.cs +++ b/Ryujinx.HLE/Input/Controller/Types/ControllerId.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.Input { - public enum HidControllerId + public enum ControllerId { ControllerPlayer1 = 0, ControllerPlayer2 = 1, diff --git a/Ryujinx.HLE/Input/HidControllerLayouts.cs b/Ryujinx.HLE/Input/Controller/Types/ControllerLayouts.cs similarity index 86% rename from Ryujinx.HLE/Input/HidControllerLayouts.cs rename to Ryujinx.HLE/Input/Controller/Types/ControllerLayouts.cs index 3548175f6..fedc0399a 100644 --- a/Ryujinx.HLE/Input/HidControllerLayouts.cs +++ b/Ryujinx.HLE/Input/Controller/Types/ControllerLayouts.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.Input { - public enum HidControllerLayouts + public enum ControllerLayouts { ProController = 0, HandheldJoined = 1, diff --git a/Ryujinx.HLE/Input/Controller/Types/ControllerState.cs b/Ryujinx.HLE/Input/Controller/Types/ControllerState.cs new file mode 100644 index 000000000..4847438dd --- /dev/null +++ b/Ryujinx.HLE/Input/Controller/Types/ControllerState.cs @@ -0,0 +1,15 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.Input +{ + [StructLayout(LayoutKind.Sequential)] + public struct ControllerState + { + public long SamplesTimestamp; + public long SamplesTimestamp2; + public ControllerButtons ButtonState; + public JoystickPosition LeftStick; + public JoystickPosition RightStick; + public ControllerConnectionState ConnectionState; + } +} diff --git a/Ryujinx.HLE/Input/Controller/Types/ControllerStateHeader.cs b/Ryujinx.HLE/Input/Controller/Types/ControllerStateHeader.cs new file mode 100644 index 000000000..f885c00c7 --- /dev/null +++ b/Ryujinx.HLE/Input/Controller/Types/ControllerStateHeader.cs @@ -0,0 +1,13 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.Input +{ + [StructLayout(LayoutKind.Sequential)] + public struct ControllerStateHeader + { + public long Timestamp; + public long EntryCount; + public long CurrentEntryIndex; + public long MaxEntryCount; + } +} diff --git a/Ryujinx.HLE/Input/HidControllerType.cs b/Ryujinx.HLE/Input/Controller/Types/ControllerStatus.cs similarity index 85% rename from Ryujinx.HLE/Input/HidControllerType.cs rename to Ryujinx.HLE/Input/Controller/Types/ControllerStatus.cs index 74bca365c..9444d7b0e 100644 --- a/Ryujinx.HLE/Input/HidControllerType.cs +++ b/Ryujinx.HLE/Input/Controller/Types/ControllerStatus.cs @@ -3,7 +3,7 @@ using System; namespace Ryujinx.HLE.Input { [Flags] - public enum HidControllerType + public enum ControllerStatus : int { ProController = 1 << 0, Handheld = 1 << 1, diff --git a/Ryujinx.HLE/Input/Controller/Types/DeviceFlags.cs b/Ryujinx.HLE/Input/Controller/Types/DeviceFlags.cs new file mode 100644 index 000000000..539131757 --- /dev/null +++ b/Ryujinx.HLE/Input/Controller/Types/DeviceFlags.cs @@ -0,0 +1,22 @@ +using System; + +namespace Ryujinx.HLE.Input +{ + [Flags] + public enum DeviceFlags : 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 + } +} diff --git a/Ryujinx.HLE/Input/HidHotkeyButtons.cs b/Ryujinx.HLE/Input/Controller/Types/HotkeyButtons.cs similarity index 75% rename from Ryujinx.HLE/Input/HidHotkeyButtons.cs rename to Ryujinx.HLE/Input/Controller/Types/HotkeyButtons.cs index 7fa6ed6d0..be76ee1e3 100644 --- a/Ryujinx.HLE/Input/HidHotkeyButtons.cs +++ b/Ryujinx.HLE/Input/Controller/Types/HotkeyButtons.cs @@ -3,7 +3,7 @@ namespace Ryujinx.HLE.Input { [Flags] - public enum HidHotkeyButtons + public enum HotkeyButtons { ToggleVSync = 1 << 0, } diff --git a/Ryujinx.HLE/Input/HidJoystickPosition.cs b/Ryujinx.HLE/Input/Controller/Types/JoystickPosition.cs similarity index 69% rename from Ryujinx.HLE/Input/HidJoystickPosition.cs rename to Ryujinx.HLE/Input/Controller/Types/JoystickPosition.cs index a1fe16087..1442bc60c 100644 --- a/Ryujinx.HLE/Input/HidJoystickPosition.cs +++ b/Ryujinx.HLE/Input/Controller/Types/JoystickPosition.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.Input { - public struct HidJoystickPosition + public struct JoystickPosition { public int Dx; public int Dy; diff --git a/Ryujinx.HLE/Input/NpadColor.cs b/Ryujinx.HLE/Input/Controller/Types/NpadColor.cs similarity index 91% rename from Ryujinx.HLE/Input/NpadColor.cs rename to Ryujinx.HLE/Input/Controller/Types/NpadColor.cs index b15c45d82..a60f94aae 100644 --- a/Ryujinx.HLE/Input/NpadColor.cs +++ b/Ryujinx.HLE/Input/Controller/Types/NpadColor.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.Input { - public enum NpadColor //Thanks to CTCaer + public enum NpadColor : int //Thanks to CTCaer { Black = 0, diff --git a/Ryujinx.HLE/Input/Hid.cs b/Ryujinx.HLE/Input/Hid.cs index c42f3b6cd..27e6a3087 100644 --- a/Ryujinx.HLE/Input/Hid.cs +++ b/Ryujinx.HLE/Input/Hid.cs @@ -7,7 +7,15 @@ namespace Ryujinx.HLE.Input { private Switch _device; - public HidControllerBase PrimaryController { get; private set; } + private long _touchScreenOffset; + private long _touchEntriesOffset; + private long _keyboardOffset; + + private TouchHeader _currentTouchHeader; + private KeyboardHeader _currentKeyboardHeader; + private KeyboardEntry _currentKeyboardEntry; + + public BaseController PrimaryController { get; private set; } internal long HidPosition; @@ -17,22 +25,42 @@ namespace Ryujinx.HLE.Input HidPosition = hidPosition; device.Memory.FillWithZeros(hidPosition, Horizon.HidSize); + + _currentTouchHeader = new TouchHeader() + { + CurrentEntryIndex = -1, + }; + + _currentKeyboardHeader = new KeyboardHeader() + { + CurrentEntryIndex = -1, + }; + + _currentKeyboardEntry = new KeyboardEntry() + { + SamplesTimestamp = -1, + SamplesTimestamp2 = -1 + }; + + _touchScreenOffset = HidPosition + HidTouchScreenOffset; + _touchEntriesOffset = _touchScreenOffset + HidTouchHeaderSize; + _keyboardOffset = HidPosition + HidKeyboardOffset; } - public void InitializePrimaryController(HidControllerType controllerType) + public void InitializePrimaryController(ControllerStatus controllerType) { - HidControllerId controllerId = controllerType == HidControllerType.Handheld ? - HidControllerId.ControllerHandheld : HidControllerId.ControllerPlayer1; + ControllerId controllerId = controllerType == ControllerStatus.Handheld ? + ControllerId.ControllerHandheld : ControllerId.ControllerPlayer1; - if (controllerType == HidControllerType.ProController) + if (controllerType == ControllerStatus.ProController) { - PrimaryController = new HidProController(_device); + PrimaryController = new ProController(_device, NpadColor.Black, NpadColor.Black); } else { - PrimaryController = new HidNpadController(controllerType, + PrimaryController = new NpadController(controllerType, _device, - (NpadColor.BodyNeonRed, NpadColor.BodyNeonRed), + (NpadColor.BodyNeonRed, NpadColor.BodyNeonRed), (NpadColor.ButtonsNeonBlue, NpadColor.ButtonsNeonBlue)); } @@ -44,124 +72,132 @@ namespace Ryujinx.HLE.Input _device.Memory.FillWithZeros(HidPosition + HidKeyboardOffset, HidKeyboardSize); } - public HidControllerButtons UpdateStickButtons( - HidJoystickPosition leftStick, - HidJoystickPosition rightStick) + public ControllerButtons UpdateStickButtons( + JoystickPosition leftStick, + JoystickPosition rightStick) { - HidControllerButtons result = 0; + ControllerButtons result = 0; if (rightStick.Dx < 0) { - result |= HidControllerButtons.RStickLeft; + result |= ControllerButtons.RStickLeft; } if (rightStick.Dx > 0) { - result |= HidControllerButtons.RStickRight; + result |= ControllerButtons.RStickRight; } if (rightStick.Dy < 0) { - result |= HidControllerButtons.RStickDown; + result |= ControllerButtons.RStickDown; } if (rightStick.Dy > 0) { - result |= HidControllerButtons.RStickUp; + result |= ControllerButtons.RStickUp; } if (leftStick.Dx < 0) { - result |= HidControllerButtons.LStickLeft; + result |= ControllerButtons.LStickLeft; } if (leftStick.Dx > 0) { - result |= HidControllerButtons.LStickRight; + result |= ControllerButtons.LStickRight; } if (leftStick.Dy < 0) { - result |= HidControllerButtons.LStickDown; + result |= ControllerButtons.LStickDown; } if (leftStick.Dy > 0) { - result |= HidControllerButtons.LStickUp; + result |= ControllerButtons.LStickUp; } return result; } - - public void SetTouchPoints(params HidTouchPoint[] points) + public void SetTouchPoints(params TouchPoint[] points) { - long touchScreenOffset = HidPosition + HidTouchScreenOffset; - long lastEntry = _device.Memory.ReadInt64(touchScreenOffset + 0x10); - long currEntry = (lastEntry + 1) % HidEntryCount; - long timestamp = GetTimestamp(); + long timestamp = GetTimestamp(); + long sampleCounter = _currentTouchHeader.SamplesTimestamp + 1; - _device.Memory.WriteInt64(touchScreenOffset + 0x00, timestamp); - _device.Memory.WriteInt64(touchScreenOffset + 0x08, HidEntryCount); - _device.Memory.WriteInt64(touchScreenOffset + 0x10, currEntry); - _device.Memory.WriteInt64(touchScreenOffset + 0x18, HidEntryCount - 1); - _device.Memory.WriteInt64(touchScreenOffset + 0x20, timestamp); - - long touchEntryOffset = touchScreenOffset + HidTouchHeaderSize; - long lastEntryOffset = touchEntryOffset + lastEntry * HidTouchEntrySize; - long sampleCounter = _device.Memory.ReadInt64(lastEntryOffset) + 1; - - touchEntryOffset += currEntry * HidTouchEntrySize; - - _device.Memory.WriteInt64(touchEntryOffset + 0x00, sampleCounter); - _device.Memory.WriteInt64(touchEntryOffset + 0x08, points.Length); - - touchEntryOffset += HidTouchEntryHeaderSize; - - const int padding = 0; - - int index = 0; - - foreach (HidTouchPoint point in points) + var newTouchHeader = new TouchHeader { - _device.Memory.WriteInt64(touchEntryOffset + 0x00, sampleCounter); - _device.Memory.WriteInt32(touchEntryOffset + 0x08, padding); - _device.Memory.WriteInt32(touchEntryOffset + 0x0c, index++); - _device.Memory.WriteInt32(touchEntryOffset + 0x10, point.X); - _device.Memory.WriteInt32(touchEntryOffset + 0x14, point.Y); - _device.Memory.WriteInt32(touchEntryOffset + 0x18, point.DiameterX); - _device.Memory.WriteInt32(touchEntryOffset + 0x1c, point.DiameterY); - _device.Memory.WriteInt32(touchEntryOffset + 0x20, point.Angle); - _device.Memory.WriteInt32(touchEntryOffset + 0x24, padding); + CurrentEntryIndex = (_currentTouchHeader.CurrentEntryIndex + 1) % HidEntryCount, + EntryCount = HidEntryCount, + MaxEntries = HidEntryCount - 1, + SamplesTimestamp = sampleCounter, + Timestamp = timestamp, + }; - touchEntryOffset += HidTouchEntryTouchSize; + long currentTouchEntryOffset = _touchEntriesOffset + newTouchHeader.CurrentEntryIndex * HidTouchEntrySize; + + TouchEntry touchEntry = new TouchEntry() + { + SamplesTimestamp = sampleCounter, + TouchCount = points.Length + }; + + _device.Memory.WriteStruct(currentTouchEntryOffset, touchEntry); + + currentTouchEntryOffset += HidTouchEntryHeaderSize; + + for (int i = 0; i < points.Length; i++) + { + TouchData touch = new TouchData() + { + Angle = points[i].Angle, + DiameterX = points[i].DiameterX, + DiameterY = points[i].DiameterY, + Index = i, + SampleTimestamp = sampleCounter, + X = points[i].X, + Y = points[i].Y + }; + + _device.Memory.WriteStruct(currentTouchEntryOffset, touch); + + currentTouchEntryOffset += HidTouchEntryTouchSize; } + + _device.Memory.WriteStruct(_touchScreenOffset, newTouchHeader); + + _currentTouchHeader = newTouchHeader; } - public void WriteKeyboard(HidKeyboard keyboard) + public unsafe void WriteKeyboard(Keyboard keyboard) { - long keyboardOffset = HidPosition + HidKeyboardOffset; - long lastEntry = _device.Memory.ReadInt64(keyboardOffset + 0x10); - long currEntry = (lastEntry + 1) % HidEntryCount; - long timestamp = GetTimestamp(); + long timestamp = GetTimestamp(); - _device.Memory.WriteInt64(keyboardOffset + 0x00, timestamp); - _device.Memory.WriteInt64(keyboardOffset + 0x08, HidEntryCount); - _device.Memory.WriteInt64(keyboardOffset + 0x10, currEntry); - _device.Memory.WriteInt64(keyboardOffset + 0x18, HidEntryCount - 1); - - long keyboardEntryOffset = keyboardOffset + HidKeyboardHeaderSize; - long lastEntryOffset = keyboardEntryOffset + lastEntry * HidKeyboardEntrySize; - long sampleCounter = _device.Memory.ReadInt64(lastEntryOffset); - - keyboardEntryOffset += currEntry * HidKeyboardEntrySize; - _device.Memory.WriteInt64(keyboardEntryOffset + 0x00, sampleCounter + 1); - _device.Memory.WriteInt64(keyboardEntryOffset + 0x08, sampleCounter); - _device.Memory.WriteInt64(keyboardEntryOffset + 0x10, keyboard.Modifier); - - for (int i = 0; i < keyboard.Keys.Length; i++) + var newKeyboardHeader = new KeyboardHeader() { - _device.Memory.WriteInt32(keyboardEntryOffset + 0x18 + (i * 4), keyboard.Keys[i]); - } + CurrentEntryIndex = (_currentKeyboardHeader.CurrentEntryIndex + 1) % HidEntryCount, + EntryCount = HidEntryCount, + MaxEntries = HidEntryCount - 1, + Timestamp = timestamp, + }; + + _device.Memory.WriteStruct(_keyboardOffset, newKeyboardHeader); + + long keyboardEntryOffset = _keyboardOffset + HidKeyboardHeaderSize; + keyboardEntryOffset += newKeyboardHeader.CurrentEntryIndex * HidKeyboardEntrySize; + + var newkeyboardEntry = new KeyboardEntry() + { + SamplesTimestamp = _currentKeyboardEntry.SamplesTimestamp + 1, + SamplesTimestamp2 = _currentKeyboardEntry.SamplesTimestamp2 + 1, + Keys = keyboard.Keys, + Modifier = keyboard.Modifier, + }; + + _device.Memory.WriteStruct(keyboardEntryOffset, newkeyboardEntry); + + _currentKeyboardEntry = newkeyboardEntry; + _currentKeyboardHeader = newKeyboardHeader; } internal static long GetTimestamp() diff --git a/Ryujinx.HLE/Input/HidBaseController.cs b/Ryujinx.HLE/Input/HidBaseController.cs deleted file mode 100644 index 8b29d8918..000000000 --- a/Ryujinx.HLE/Input/HidBaseController.cs +++ /dev/null @@ -1,76 +0,0 @@ -using static Ryujinx.HLE.Input.Hid; - -namespace Ryujinx.HLE.Input -{ - public abstract class HidControllerBase : IHidDevice - { - protected HidControllerType HidControllerType; - protected Switch Device; - protected HidControllerId ControllerId; - - public long Offset { get; private set; } - public bool Connected { get; protected set; } - - public HidControllerBase(HidControllerType controllerType, Switch device) - { - Device = device; - - HidControllerType = controllerType; - } - - public virtual void Connect(HidControllerId controllerId) - { - ControllerId = controllerId; - - Offset = Device.Hid.HidPosition + HidControllersOffset + (int)controllerId * HidControllerSize; - - Device.Memory.FillWithZeros(Offset, 0x5000); - - Device.Memory.WriteInt32(Offset + 0x00, (int)HidControllerType); - } - - public abstract void SendInput( - HidControllerButtons buttons, - HidJoystickPosition leftStick, - HidJoystickPosition rightStick); - - protected long WriteInput( - HidControllerButtons buttons, - HidJoystickPosition leftStick, - HidJoystickPosition rightStick, - HidControllerLayouts controllerLayout) - { - long controllerOffset = Offset + HidControllerHeaderSize; - - controllerOffset += (int)controllerLayout * HidControllerLayoutsSize; - - long lastEntry = Device.Memory.ReadInt64(controllerOffset + 0x10); - long currEntry = (lastEntry + 1) % HidEntryCount; - long timestamp = GetTimestamp(); - - Device.Memory.WriteInt64(controllerOffset + 0x00, timestamp); - Device.Memory.WriteInt64(controllerOffset + 0x08, HidEntryCount); - Device.Memory.WriteInt64(controllerOffset + 0x10, currEntry); - Device.Memory.WriteInt64(controllerOffset + 0x18, HidEntryCount - 1); - - controllerOffset += HidControllersLayoutHeaderSize; - - long lastEntryOffset = controllerOffset + lastEntry * HidControllersInputEntrySize; - - controllerOffset += currEntry * HidControllersInputEntrySize; - - long sampleCounter = Device.Memory.ReadInt64(lastEntryOffset) + 1; - - Device.Memory.WriteInt64(controllerOffset + 0x00, sampleCounter); - Device.Memory.WriteInt64(controllerOffset + 0x08, sampleCounter); - Device.Memory.WriteInt64(controllerOffset + 0x10, (uint)buttons); - - Device.Memory.WriteInt32(controllerOffset + 0x18, leftStick.Dx); - Device.Memory.WriteInt32(controllerOffset + 0x1c, leftStick.Dy); - Device.Memory.WriteInt32(controllerOffset + 0x20, rightStick.Dx); - Device.Memory.WriteInt32(controllerOffset + 0x24, rightStick.Dy); - - return controllerOffset; - } - } -} diff --git a/Ryujinx.HLE/Input/HidControllerColorDesc.cs b/Ryujinx.HLE/Input/HidControllerColorDesc.cs deleted file mode 100644 index 85ece5f11..000000000 --- a/Ryujinx.HLE/Input/HidControllerColorDesc.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Ryujinx.HLE.Input -{ - [Flags] - public enum HidControllerColorDesc - { - ColorDescColorsNonexistent = (1 << 1) - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/Input/HidNpadController.cs b/Ryujinx.HLE/Input/HidNpadController.cs deleted file mode 100644 index 0c773e86b..000000000 --- a/Ryujinx.HLE/Input/HidNpadController.cs +++ /dev/null @@ -1,92 +0,0 @@ -namespace Ryujinx.HLE.Input -{ - public class HidNpadController : HidControllerBase - { - private (NpadColor Left, NpadColor Right) _npadBodyColors; - private (NpadColor Left, NpadColor Right) _npadButtonColors; - - private HidControllerLayouts _currentLayout; - - private bool _isHalf; - - public HidNpadController( - HidControllerType controllerType, - Switch device, - (NpadColor, NpadColor) npadBodyColors, - (NpadColor, NpadColor) npadButtonColors) : base(controllerType, device) - { - _npadBodyColors = npadBodyColors; - _npadButtonColors = npadButtonColors; - - _currentLayout = HidControllerLayouts.HandheldJoined; - - switch (controllerType) - { - case HidControllerType.NpadLeft: - _currentLayout = HidControllerLayouts.Left; - break; - case HidControllerType.NpadRight: - _currentLayout = HidControllerLayouts.Right; - break; - case HidControllerType.NpadPair: - _currentLayout = HidControllerLayouts.Joined; - break; - } - } - - public override void Connect(HidControllerId controllerId) - { - if (HidControllerType != HidControllerType.NpadLeft && HidControllerType != HidControllerType.NpadRight) - { - _isHalf = false; - } - - base.Connect(_currentLayout == HidControllerLayouts.HandheldJoined ? HidControllerId.ControllerHandheld : controllerId); - - HidControllerColorDesc singleColorDesc = - HidControllerColorDesc.ColorDescColorsNonexistent; - - HidControllerColorDesc splitColorDesc = 0; - - NpadColor singleColorBody = NpadColor.Black; - NpadColor singleColorButtons = NpadColor.Black; - - Device.Memory.WriteInt32(Offset + 0x04, _isHalf ? 1 : 0); - - if (_isHalf) - { - Device.Memory.WriteInt32(Offset + 0x08, (int)singleColorDesc); - Device.Memory.WriteInt32(Offset + 0x0c, (int)singleColorBody); - Device.Memory.WriteInt32(Offset + 0x10, (int)singleColorButtons); - Device.Memory.WriteInt32(Offset + 0x14, (int)splitColorDesc); - } - else - { - Device.Memory.WriteInt32(Offset + 0x18, (int)_npadBodyColors.Left); - Device.Memory.WriteInt32(Offset + 0x1c, (int)_npadButtonColors.Left); - Device.Memory.WriteInt32(Offset + 0x20, (int)_npadBodyColors.Right); - Device.Memory.WriteInt32(Offset + 0x24, (int)_npadButtonColors.Right); - } - - Connected = true; - } - - public override void SendInput - (HidControllerButtons buttons, - HidJoystickPosition leftStick, - HidJoystickPosition rightStick) - { - long controllerOffset = WriteInput(buttons, leftStick, rightStick, _currentLayout); - - Device.Memory.WriteInt64(controllerOffset + 0x28, - (Connected ? (uint)HidControllerConnState.ControllerStateConnected : 0) | - (_currentLayout == HidControllerLayouts.HandheldJoined ? (uint)HidControllerConnState.ControllerStateWired : 0)); - - controllerOffset = WriteInput(buttons, leftStick, rightStick, HidControllerLayouts.Main); - - Device.Memory.WriteInt64(controllerOffset + 0x28, - (Connected ? (uint)HidControllerConnState.ControllerStateWired : 0) | - (uint)HidControllerConnState.ControllerStateWired); - } - } -} diff --git a/Ryujinx.HLE/Input/HidProController.cs b/Ryujinx.HLE/Input/HidProController.cs deleted file mode 100644 index e30e91722..000000000 --- a/Ryujinx.HLE/Input/HidProController.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace Ryujinx.HLE.Input -{ - public class HidProController : HidControllerBase - { - bool _wired = false; - - public HidProController(Switch device) : base(HidControllerType.ProController, device) - { - _wired = true; - } - - public override void Connect(HidControllerId controllerId) - { - base.Connect(controllerId); - - HidControllerColorDesc singleColorDesc = - HidControllerColorDesc.ColorDescColorsNonexistent; - - HidControllerColorDesc splitColorDesc = 0; - - NpadColor singleColorBody = NpadColor.Black; - NpadColor singleColorButtons = NpadColor.Black; - - Device.Memory.WriteInt32(Offset + 0x08, (int)singleColorDesc); - Device.Memory.WriteInt32(Offset + 0x0c, (int)singleColorBody); - Device.Memory.WriteInt32(Offset + 0x10, (int)singleColorButtons); - Device.Memory.WriteInt32(Offset + 0x14, (int)splitColorDesc); - - Connected = true; - } - - public override void SendInput( - HidControllerButtons buttons, - HidJoystickPosition leftStick, - HidJoystickPosition rightStick) - { - long controllerOffset = WriteInput(buttons, leftStick, rightStick, HidControllerLayouts.ProController); - - Device.Memory.WriteInt64(controllerOffset + 0x28, - (Connected ? (uint)HidControllerConnState.ControllerStateConnected : 0) | - (_wired ? (uint)HidControllerConnState.ControllerStateWired : 0)); - - controllerOffset = WriteInput(buttons, leftStick, rightStick, HidControllerLayouts.Main); - - Device.Memory.WriteInt64(controllerOffset + 0x28, - (Connected ? (uint)HidControllerConnState.ControllerStateWired : 0) | - (uint)HidControllerConnState.ControllerStateWired); - } - } -} diff --git a/Ryujinx.HLE/Input/HidKeyboard.cs b/Ryujinx.HLE/Input/Keyboard/Keyboard.cs similarity index 76% rename from Ryujinx.HLE/Input/HidKeyboard.cs rename to Ryujinx.HLE/Input/Keyboard/Keyboard.cs index a5b042a52..7220e5187 100644 --- a/Ryujinx.HLE/Input/HidKeyboard.cs +++ b/Ryujinx.HLE/Input/Keyboard/Keyboard.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.Input { - public struct HidKeyboard + public struct Keyboard { public int Modifier; public int[] Keys; diff --git a/Ryujinx.HLE/Input/Keyboard/KeyboardEntry.cs b/Ryujinx.HLE/Input/Keyboard/KeyboardEntry.cs new file mode 100644 index 000000000..be7d9399d --- /dev/null +++ b/Ryujinx.HLE/Input/Keyboard/KeyboardEntry.cs @@ -0,0 +1,15 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.Input +{ + [StructLayout(LayoutKind.Sequential)] + public struct KeyboardEntry + { + public long SamplesTimestamp; + public long SamplesTimestamp2; + public long Modifier; + + [MarshalAs(UnmanagedType.ByValArray , SizeConst = 0x8)] + public int[] Keys; + } +} diff --git a/Ryujinx.HLE/Input/Keyboard/KeyboardHeader.cs b/Ryujinx.HLE/Input/Keyboard/KeyboardHeader.cs new file mode 100644 index 000000000..882ccbabe --- /dev/null +++ b/Ryujinx.HLE/Input/Keyboard/KeyboardHeader.cs @@ -0,0 +1,13 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.Input +{ + [StructLayout(LayoutKind.Sequential)] + public struct KeyboardHeader + { + public long Timestamp; + public long EntryCount; + public long CurrentEntryIndex; + public long MaxEntries; + } +} diff --git a/Ryujinx.HLE/Input/Touch/TouchData.cs b/Ryujinx.HLE/Input/Touch/TouchData.cs new file mode 100644 index 000000000..8489ef709 --- /dev/null +++ b/Ryujinx.HLE/Input/Touch/TouchData.cs @@ -0,0 +1,18 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.Input +{ + [StructLayout(LayoutKind.Sequential)] + public struct TouchData + { + public long SampleTimestamp; + public int Padding; + public int Index; + public int X; + public int Y; + public int DiameterX; + public int DiameterY; + public int Angle; + public int Padding2; + } +} diff --git a/Ryujinx.HLE/Input/Touch/TouchEntry.cs b/Ryujinx.HLE/Input/Touch/TouchEntry.cs new file mode 100644 index 000000000..2ef09d752 --- /dev/null +++ b/Ryujinx.HLE/Input/Touch/TouchEntry.cs @@ -0,0 +1,11 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.Input +{ + [StructLayout(LayoutKind.Sequential)] + public unsafe struct TouchEntry + { + public long SamplesTimestamp; + public long TouchCount; + } +} diff --git a/Ryujinx.HLE/Input/Touch/TouchHeader.cs b/Ryujinx.HLE/Input/Touch/TouchHeader.cs new file mode 100644 index 000000000..dd93137c2 --- /dev/null +++ b/Ryujinx.HLE/Input/Touch/TouchHeader.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.Input +{ + [StructLayout(LayoutKind.Sequential)] + public struct TouchHeader + { + public long Timestamp; + public long EntryCount; + public long CurrentEntryIndex; + public long MaxEntries; + public long SamplesTimestamp; + } +} diff --git a/Ryujinx.HLE/Input/HidTouchPoint.cs b/Ryujinx.HLE/Input/Touch/TouchPoint.cs similarity index 83% rename from Ryujinx.HLE/Input/HidTouchPoint.cs rename to Ryujinx.HLE/Input/Touch/TouchPoint.cs index 25412456b..a9b095de2 100644 --- a/Ryujinx.HLE/Input/HidTouchPoint.cs +++ b/Ryujinx.HLE/Input/Touch/TouchPoint.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.Input { - public struct HidTouchPoint + public struct TouchPoint { public int X; public int Y; diff --git a/Ryujinx.Profiler/ProfileConfig.cs b/Ryujinx.Profiler/ProfileConfig.cs index d70da6023..4271bd2b8 100644 --- a/Ryujinx.Profiler/ProfileConfig.cs +++ b/Ryujinx.Profiler/ProfileConfig.cs @@ -105,6 +105,21 @@ namespace Ryujinx.Profiler }; } + public static class Input + { + public static ProfileConfig ControllerInput = new ProfileConfig + { + Category = "Input", + SessionGroup = "ControllerInput" + }; + + public static ProfileConfig TouchInput = new ProfileConfig + { + Category = "Input", + SessionGroup = "TouchInput" + }; + } + public static class GPU { public static class Engine2d diff --git a/Ryujinx/Config.jsonc b/Ryujinx/Config.jsonc index 4bbdd5a42..fa961d294 100644 --- a/Ryujinx/Config.jsonc +++ b/Ryujinx/Config.jsonc @@ -64,7 +64,7 @@ "controller_type": "Handheld", // Enable or disable "direct keyboard access (HID) support" (Provides games access to your keyboard as a text entry device). - "enable_keyboard": true, + "enable_keyboard": false, // Keyboard Controls // https://github.com/opentk/opentk/blob/master/src/OpenTK/Input/Key.cs diff --git a/Ryujinx/Configuration.cs b/Ryujinx/Configuration.cs index 77895ac85..72f507de1 100644 --- a/Ryujinx/Configuration.cs +++ b/Ryujinx/Configuration.cs @@ -120,7 +120,7 @@ namespace Ryujinx /// /// The primary controller's type /// - public HidControllerType ControllerType { get; private set; } + public ControllerStatus ControllerType { get; private set; } /// /// Enable or disable keyboard support (Independent from controllers binding) @@ -135,7 +135,7 @@ namespace Ryujinx /// /// Controller control bindings /// - public NpadController GamepadControls { get; private set; } + public UI.Input.NpadController GamepadControls { get; private set; } /// /// Loads a configuration file from disk diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index c57727992..33ecc9173 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -23,7 +23,7 @@ namespace Ryujinx private IGalRenderer _renderer; - private HidHotkeyButtons _prevHotkeyButtons = 0; + private HotkeyButtons _prevHotkeyButtons = 0; private KeyboardState? _keyboard = null; @@ -140,11 +140,11 @@ namespace Ryujinx private new void UpdateFrame() { - HidHotkeyButtons currentHotkeyButtons = 0; - HidControllerButtons currentButton = 0; - HidJoystickPosition leftJoystick; - HidJoystickPosition rightJoystick; - HidKeyboard? hidKeyboard = null; + HotkeyButtons currentHotkeyButtons = 0; + ControllerButtons currentButton = 0; + JoystickPosition leftJoystick; + JoystickPosition rightJoystick; + HLE.Input.Keyboard? hidKeyboard = null; int leftJoystickDx = 0; int leftJoystickDy = 0; @@ -176,7 +176,7 @@ namespace Ryujinx if (!hidKeyboard.HasValue) { - hidKeyboard = new HidKeyboard + hidKeyboard = new HLE.Input.Keyboard { Modifier = 0, Keys = new int[0x8] @@ -196,13 +196,13 @@ namespace Ryujinx (rightJoystickDx, rightJoystickDy) = Configuration.Instance.GamepadControls.GetRightStick(); } - leftJoystick = new HidJoystickPosition + leftJoystick = new JoystickPosition { Dx = leftJoystickDx, Dy = leftJoystickDy }; - rightJoystick = new HidJoystickPosition + rightJoystick = new JoystickPosition { Dx = rightJoystickDx, Dy = rightJoystickDy @@ -247,7 +247,7 @@ namespace Ryujinx int mX = (scrnMouseX * TouchScreenWidth) / scrnWidth; int mY = (scrnMouseY * TouchScreenHeight) / scrnHeight; - HidTouchPoint currentPoint = new HidTouchPoint + TouchPoint currentPoint = new TouchPoint { X = mX, Y = mY, @@ -274,13 +274,13 @@ namespace Ryujinx _device.Hid.WriteKeyboard(hidKeyboard.Value); } - HidControllerBase controller = _device.Hid.PrimaryController; + BaseController controller = _device.Hid.PrimaryController; controller.SendInput(currentButton, leftJoystick, rightJoystick); // Toggle vsync - if (currentHotkeyButtons.HasFlag(HidHotkeyButtons.ToggleVSync) && - !_prevHotkeyButtons.HasFlag(HidHotkeyButtons.ToggleVSync)) + if (currentHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync) && + !_prevHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync)) { _device.EnableDeviceVsync = !_device.EnableDeviceVsync; } diff --git a/Ryujinx/Ui/NpadController.cs b/Ryujinx/Ui/NpadController.cs index eddf0aa89..71f97fb8d 100644 --- a/Ryujinx/Ui/NpadController.cs +++ b/Ryujinx/Ui/NpadController.cs @@ -107,7 +107,7 @@ namespace Ryujinx.UI.Input Enabled = enabled; } - public HidControllerButtons GetButtons() + public ControllerButtons GetButtons() { if (!Enabled) { @@ -116,25 +116,25 @@ namespace Ryujinx.UI.Input GamePadState gpState = GamePad.GetState(Index); - HidControllerButtons buttons = 0; + ControllerButtons buttons = 0; - if (IsPressed(gpState, LeftJoycon.DPadUp)) buttons |= HidControllerButtons.DpadUp; - if (IsPressed(gpState, LeftJoycon.DPadDown)) buttons |= HidControllerButtons.DpadDown; - if (IsPressed(gpState, LeftJoycon.DPadLeft)) buttons |= HidControllerButtons.DpadLeft; - if (IsPressed(gpState, LeftJoycon.DPadRight)) buttons |= HidControllerButtons.DPadRight; - if (IsPressed(gpState, LeftJoycon.StickButton)) buttons |= HidControllerButtons.StickLeft; - if (IsPressed(gpState, LeftJoycon.ButtonMinus)) buttons |= HidControllerButtons.Minus; - if (IsPressed(gpState, LeftJoycon.ButtonL)) buttons |= HidControllerButtons.L; - if (IsPressed(gpState, LeftJoycon.ButtonZl)) buttons |= HidControllerButtons.Zl; + if (IsPressed(gpState, LeftJoycon.DPadUp)) buttons |= ControllerButtons.DpadUp; + if (IsPressed(gpState, LeftJoycon.DPadDown)) buttons |= ControllerButtons.DpadDown; + if (IsPressed(gpState, LeftJoycon.DPadLeft)) buttons |= ControllerButtons.DpadLeft; + if (IsPressed(gpState, LeftJoycon.DPadRight)) buttons |= ControllerButtons.DPadRight; + if (IsPressed(gpState, LeftJoycon.StickButton)) buttons |= ControllerButtons.StickLeft; + if (IsPressed(gpState, LeftJoycon.ButtonMinus)) buttons |= ControllerButtons.Minus; + if (IsPressed(gpState, LeftJoycon.ButtonL)) buttons |= ControllerButtons.L; + if (IsPressed(gpState, LeftJoycon.ButtonZl)) buttons |= ControllerButtons.Zl; - if (IsPressed(gpState, RightJoycon.ButtonA)) buttons |= HidControllerButtons.A; - if (IsPressed(gpState, RightJoycon.ButtonB)) buttons |= HidControllerButtons.B; - if (IsPressed(gpState, RightJoycon.ButtonX)) buttons |= HidControllerButtons.X; - if (IsPressed(gpState, RightJoycon.ButtonY)) buttons |= HidControllerButtons.Y; - if (IsPressed(gpState, RightJoycon.StickButton)) buttons |= HidControllerButtons.StickRight; - if (IsPressed(gpState, RightJoycon.ButtonPlus)) buttons |= HidControllerButtons.Plus; - if (IsPressed(gpState, RightJoycon.ButtonR)) buttons |= HidControllerButtons.R; - if (IsPressed(gpState, RightJoycon.ButtonZr)) buttons |= HidControllerButtons.Zr; + if (IsPressed(gpState, RightJoycon.ButtonA)) buttons |= ControllerButtons.A; + if (IsPressed(gpState, RightJoycon.ButtonB)) buttons |= ControllerButtons.B; + if (IsPressed(gpState, RightJoycon.ButtonX)) buttons |= ControllerButtons.X; + if (IsPressed(gpState, RightJoycon.ButtonY)) buttons |= ControllerButtons.Y; + if (IsPressed(gpState, RightJoycon.StickButton)) buttons |= ControllerButtons.StickRight; + if (IsPressed(gpState, RightJoycon.ButtonPlus)) buttons |= ControllerButtons.Plus; + if (IsPressed(gpState, RightJoycon.ButtonR)) buttons |= ControllerButtons.R; + if (IsPressed(gpState, RightJoycon.ButtonZr)) buttons |= ControllerButtons.Zr; return buttons; } diff --git a/Ryujinx/Ui/NpadKeyboard.cs b/Ryujinx/Ui/NpadKeyboard.cs index 1f758024e..79d6330c6 100644 --- a/Ryujinx/Ui/NpadKeyboard.cs +++ b/Ryujinx/Ui/NpadKeyboard.cs @@ -57,27 +57,27 @@ namespace Ryujinx.UI.Input /// public KeyboardHotkeys Hotkeys { get; private set; } - public HidControllerButtons GetButtons(KeyboardState keyboard) + public ControllerButtons GetButtons(KeyboardState keyboard) { - HidControllerButtons buttons = 0; + ControllerButtons buttons = 0; - if (keyboard[(Key)LeftJoycon.StickButton]) buttons |= HidControllerButtons.StickLeft; - if (keyboard[(Key)LeftJoycon.DPadUp]) buttons |= HidControllerButtons.DpadUp; - if (keyboard[(Key)LeftJoycon.DPadDown]) buttons |= HidControllerButtons.DpadDown; - if (keyboard[(Key)LeftJoycon.DPadLeft]) buttons |= HidControllerButtons.DpadLeft; - if (keyboard[(Key)LeftJoycon.DPadRight]) buttons |= HidControllerButtons.DPadRight; - if (keyboard[(Key)LeftJoycon.ButtonMinus]) buttons |= HidControllerButtons.Minus; - if (keyboard[(Key)LeftJoycon.ButtonL]) buttons |= HidControllerButtons.L; - if (keyboard[(Key)LeftJoycon.ButtonZl]) buttons |= HidControllerButtons.Zl; + if (keyboard[(Key)LeftJoycon.StickButton]) buttons |= ControllerButtons.StickLeft; + if (keyboard[(Key)LeftJoycon.DPadUp]) buttons |= ControllerButtons.DpadUp; + if (keyboard[(Key)LeftJoycon.DPadDown]) buttons |= ControllerButtons.DpadDown; + if (keyboard[(Key)LeftJoycon.DPadLeft]) buttons |= ControllerButtons.DpadLeft; + if (keyboard[(Key)LeftJoycon.DPadRight]) buttons |= ControllerButtons.DPadRight; + if (keyboard[(Key)LeftJoycon.ButtonMinus]) buttons |= ControllerButtons.Minus; + if (keyboard[(Key)LeftJoycon.ButtonL]) buttons |= ControllerButtons.L; + if (keyboard[(Key)LeftJoycon.ButtonZl]) buttons |= ControllerButtons.Zl; - if (keyboard[(Key)RightJoycon.StickButton]) buttons |= HidControllerButtons.StickRight; - if (keyboard[(Key)RightJoycon.ButtonA]) buttons |= HidControllerButtons.A; - if (keyboard[(Key)RightJoycon.ButtonB]) buttons |= HidControllerButtons.B; - if (keyboard[(Key)RightJoycon.ButtonX]) buttons |= HidControllerButtons.X; - if (keyboard[(Key)RightJoycon.ButtonY]) buttons |= HidControllerButtons.Y; - if (keyboard[(Key)RightJoycon.ButtonPlus]) buttons |= HidControllerButtons.Plus; - if (keyboard[(Key)RightJoycon.ButtonR]) buttons |= HidControllerButtons.R; - if (keyboard[(Key)RightJoycon.ButtonZr]) buttons |= HidControllerButtons.Zr; + if (keyboard[(Key)RightJoycon.StickButton]) buttons |= ControllerButtons.StickRight; + if (keyboard[(Key)RightJoycon.ButtonA]) buttons |= ControllerButtons.A; + if (keyboard[(Key)RightJoycon.ButtonB]) buttons |= ControllerButtons.B; + if (keyboard[(Key)RightJoycon.ButtonX]) buttons |= ControllerButtons.X; + if (keyboard[(Key)RightJoycon.ButtonY]) buttons |= ControllerButtons.Y; + if (keyboard[(Key)RightJoycon.ButtonPlus]) buttons |= ControllerButtons.Plus; + if (keyboard[(Key)RightJoycon.ButtonR]) buttons |= ControllerButtons.R; + if (keyboard[(Key)RightJoycon.ButtonZr]) buttons |= ControllerButtons.Zr; return buttons; } @@ -108,11 +108,11 @@ namespace Ryujinx.UI.Input return (dx, dy); } - public HidHotkeyButtons GetHotkeyButtons(KeyboardState keyboard) + public HotkeyButtons GetHotkeyButtons(KeyboardState keyboard) { - HidHotkeyButtons buttons = 0; + HotkeyButtons buttons = 0; - if (keyboard[(Key)Hotkeys.ToggleVsync]) buttons |= HidHotkeyButtons.ToggleVSync; + if (keyboard[(Key)Hotkeys.ToggleVsync]) buttons |= HotkeyButtons.ToggleVSync; return buttons; } @@ -267,9 +267,9 @@ namespace Ryujinx.UI.Input new KeyMappingEntry { TargetKey = Key.NumLock, Target = 10 }, }; - public HidKeyboard GetKeysDown(KeyboardState keyboard) + public HLE.Input.Keyboard GetKeysDown(KeyboardState keyboard) { - HidKeyboard hidKeyboard = new HidKeyboard + HLE.Input.Keyboard hidKeyboard = new HLE.Input.Keyboard { Modifier = 0, Keys = new int[0x8]