Little rewrite of HID input (#723)

* change hid sharedmem writing to use structures
This commit is contained in:
emmauss 2019-07-22 20:15:46 +03:00 committed by GitHub
parent 1f3a34dd7a
commit d254548548
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 682 additions and 409 deletions

View file

@ -1,5 +1,6 @@
using ChocolArm64.Memory; using ChocolArm64.Memory;
using System; using System;
using System.Runtime.InteropServices;
namespace Ryujinx.HLE namespace Ryujinx.HLE
{ {
@ -98,6 +99,11 @@ namespace Ryujinx.HLE
*((ulong*)(_ramPtr + position)) = value; *((ulong*)(_ramPtr + position)) = value;
} }
public unsafe void WriteStruct<T>(long position, T value)
{
Marshal.StructureToPtr(value, (IntPtr)(_ramPtr + position), false);
}
public void FillWithZeros(long position, int size) public void FillWithZeros(long position, int size)
{ {
int size8 = size & ~(8 - 1); int size8 = size & ~(8 - 1);
@ -180,4 +186,4 @@ namespace Ryujinx.HLE
MemoryManagement.Free(RamPointer); MemoryManagement.Free(RamPointer);
} }
} }
} }

View file

@ -5,39 +5,39 @@ namespace Ryujinx.HLE.HOS.Services.Hid
{ {
static class HidUtils static class HidUtils
{ {
public static HidControllerId GetIndexFromNpadIdType(NpadIdType npadIdType) public static ControllerId GetIndexFromNpadIdType(NpadIdType npadIdType)
{ {
switch (npadIdType) switch (npadIdType)
{ {
case NpadIdType.Player1: return HidControllerId.ControllerPlayer1; case NpadIdType.Player1: return ControllerId.ControllerPlayer1;
case NpadIdType.Player2: return HidControllerId.ControllerPlayer2; case NpadIdType.Player2: return ControllerId.ControllerPlayer2;
case NpadIdType.Player3: return HidControllerId.ControllerPlayer3; case NpadIdType.Player3: return ControllerId.ControllerPlayer3;
case NpadIdType.Player4: return HidControllerId.ControllerPlayer4; case NpadIdType.Player4: return ControllerId.ControllerPlayer4;
case NpadIdType.Player5: return HidControllerId.ControllerPlayer5; case NpadIdType.Player5: return ControllerId.ControllerPlayer5;
case NpadIdType.Player6: return HidControllerId.ControllerPlayer6; case NpadIdType.Player6: return ControllerId.ControllerPlayer6;
case NpadIdType.Player7: return HidControllerId.ControllerPlayer7; case NpadIdType.Player7: return ControllerId.ControllerPlayer7;
case NpadIdType.Player8: return HidControllerId.ControllerPlayer8; case NpadIdType.Player8: return ControllerId.ControllerPlayer8;
case NpadIdType.Handheld: return HidControllerId.ControllerHandheld; case NpadIdType.Handheld: return ControllerId.ControllerHandheld;
case NpadIdType.Unknown: return HidControllerId.ControllerUnknown; case NpadIdType.Unknown: return ControllerId.ControllerUnknown;
default: throw new ArgumentOutOfRangeException(nameof(npadIdType)); default: throw new ArgumentOutOfRangeException(nameof(npadIdType));
} }
} }
public static NpadIdType GetNpadIdTypeFromIndex(HidControllerId index) public static NpadIdType GetNpadIdTypeFromIndex(ControllerId index)
{ {
switch (index) switch (index)
{ {
case HidControllerId.ControllerPlayer1: return NpadIdType.Player1; case ControllerId.ControllerPlayer1: return NpadIdType.Player1;
case HidControllerId.ControllerPlayer2: return NpadIdType.Player2; case ControllerId.ControllerPlayer2: return NpadIdType.Player2;
case HidControllerId.ControllerPlayer3: return NpadIdType.Player3; case ControllerId.ControllerPlayer3: return NpadIdType.Player3;
case HidControllerId.ControllerPlayer4: return NpadIdType.Player4; case ControllerId.ControllerPlayer4: return NpadIdType.Player4;
case HidControllerId.ControllerPlayer5: return NpadIdType.Player5; case ControllerId.ControllerPlayer5: return NpadIdType.Player5;
case HidControllerId.ControllerPlayer6: return NpadIdType.Player6; case ControllerId.ControllerPlayer6: return NpadIdType.Player6;
case HidControllerId.ControllerPlayer7: return NpadIdType.Player7; case ControllerId.ControllerPlayer7: return NpadIdType.Player7;
case HidControllerId.ControllerPlayer8: return NpadIdType.Player8; case ControllerId.ControllerPlayer8: return NpadIdType.Player8;
case HidControllerId.ControllerHandheld: return NpadIdType.Handheld; case ControllerId.ControllerHandheld: return NpadIdType.Handheld;
case HidControllerId.ControllerUnknown: return NpadIdType.Unknown; case ControllerId.ControllerUnknown: return NpadIdType.Unknown;
default: throw new ArgumentOutOfRangeException(nameof(index)); default: throw new ArgumentOutOfRangeException(nameof(index));
} }

View file

@ -569,8 +569,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// SetSupportedNpadIdType(nn::applet::AppletResourceUserId, array<NpadIdType, 9>) // SetSupportedNpadIdType(nn::applet::AppletResourceUserId, array<NpadIdType, 9>)
public ResultCode SetSupportedNpadIdType(ServiceCtx context) public ResultCode SetSupportedNpadIdType(ServiceCtx context)
{ {
long appletResourceUserId = context.RequestData.ReadInt64(); long appletResourceUserId = context.RequestData.ReadInt64();
HidControllerId npadIdType = (HidControllerId)context.RequestData.ReadInt64(); ControllerId npadIdType = (ControllerId)context.RequestData.ReadInt64();
Logger.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, npadIdType }); Logger.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, npadIdType });
@ -687,8 +687,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// SetNpadJoyAssignmentModeSingleByDefault(uint HidControllerId, nn::applet::AppletResourceUserId) // SetNpadJoyAssignmentModeSingleByDefault(uint HidControllerId, nn::applet::AppletResourceUserId)
public ResultCode SetNpadJoyAssignmentModeSingleByDefault(ServiceCtx context) public ResultCode SetNpadJoyAssignmentModeSingleByDefault(ServiceCtx context)
{ {
HidControllerId hidControllerId = (HidControllerId)context.RequestData.ReadInt32(); ControllerId hidControllerId = (ControllerId)context.RequestData.ReadInt32();
long appletResourceUserId = context.RequestData.ReadInt64(); long appletResourceUserId = context.RequestData.ReadInt64();
_npadJoyAssignmentMode = HidNpadJoyAssignmentMode.Single; _npadJoyAssignmentMode = HidNpadJoyAssignmentMode.Single;
@ -701,7 +701,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// SetNpadJoyAssignmentModeSingle(uint HidControllerId, nn::applet::AppletResourceUserId, long HidNpadJoyDeviceType) // SetNpadJoyAssignmentModeSingle(uint HidControllerId, nn::applet::AppletResourceUserId, long HidNpadJoyDeviceType)
public ResultCode SetNpadJoyAssignmentModeSingle(ServiceCtx context) public ResultCode SetNpadJoyAssignmentModeSingle(ServiceCtx context)
{ {
HidControllerId hidControllerId = (HidControllerId)context.RequestData.ReadInt32(); ControllerId hidControllerId = (ControllerId)context.RequestData.ReadInt32();
long appletResourceUserId = context.RequestData.ReadInt64(); long appletResourceUserId = context.RequestData.ReadInt64();
HidNpadJoyDeviceType hidNpadJoyDeviceType = (HidNpadJoyDeviceType)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) // SetNpadJoyAssignmentModeDual(uint HidControllerId, nn::applet::AppletResourceUserId)
public ResultCode SetNpadJoyAssignmentModeDual(ServiceCtx context) public ResultCode SetNpadJoyAssignmentModeDual(ServiceCtx context)
{ {
HidControllerId hidControllerId = (HidControllerId)context.RequestData.ReadInt32(); ControllerId hidControllerId = (ControllerId)context.RequestData.ReadInt32();
long appletResourceUserId = context.RequestData.ReadInt64(); long appletResourceUserId = context.RequestData.ReadInt64();
_npadJoyAssignmentMode = HidNpadJoyAssignmentMode.Dual; _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 // SetNpadJoyAssignmentModeSingleWithDestination(uint HidControllerId, long HidNpadJoyDeviceType, nn::applet::AppletResourceUserId) -> bool Unknown0, uint Unknown1
public ResultCode SetNpadJoyAssignmentModeSingleWithDestination(ServiceCtx context) public ResultCode SetNpadJoyAssignmentModeSingleWithDestination(ServiceCtx context)
{ {
HidControllerId hidControllerId = (HidControllerId)context.RequestData.ReadInt32(); ControllerId hidControllerId = (ControllerId)context.RequestData.ReadInt32();
HidNpadJoyDeviceType hidNpadJoyDeviceType = (HidNpadJoyDeviceType)context.RequestData.ReadInt64(); HidNpadJoyDeviceType hidNpadJoyDeviceType = (HidNpadJoyDeviceType)context.RequestData.ReadInt64();
long appletResourceUserId = context.RequestData.ReadInt64(); long appletResourceUserId = context.RequestData.ReadInt64();

View file

@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Irs
return ResultCode.NpadIdOutOfRange; return ResultCode.NpadIdOutOfRange;
} }
HidControllerId irCameraHandle = HidUtils.GetIndexFromNpadIdType(npadIdType); ControllerId irCameraHandle = HidUtils.GetIndexFromNpadIdType(npadIdType);
context.ResponseData.Write((int)irCameraHandle); context.ResponseData.Write((int)irCameraHandle);

View file

@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
public DeviceState State = DeviceState.Unavailable; public DeviceState State = DeviceState.Unavailable;
public HidControllerId Handle; public ControllerId Handle;
public NpadIdType NpadIdType; public NpadIdType NpadIdType;
} }
} }

View file

@ -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;
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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
}
}

View file

@ -3,7 +3,7 @@ using System;
namespace Ryujinx.HLE.Input namespace Ryujinx.HLE.Input
{ {
[Flags] [Flags]
public enum HidControllerButtons public enum ControllerButtons : long
{ {
A = 1 << 0, A = 1 << 0,
B = 1 << 1, B = 1 << 1,

View file

@ -0,0 +1,10 @@
using System;
namespace Ryujinx.HLE.Input
{
[Flags]
public enum ControllerColorDescription : int
{
ColorDescriptionColorsNonexistent = (1 << 1)
}
}

View file

@ -3,7 +3,7 @@ using System;
namespace Ryujinx.HLE.Input namespace Ryujinx.HLE.Input
{ {
[Flags] [Flags]
public enum HidControllerConnState public enum ControllerConnectionState : long
{ {
ControllerStateConnected = (1 << 0), ControllerStateConnected = (1 << 0),
ControllerStateWired = (1 << 1) ControllerStateWired = (1 << 1)

View file

@ -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];
}
}

View file

@ -0,0 +1,12 @@
using System;
namespace Ryujinx.HLE.Input
{
[Flags]
public enum ControllerDeviceType : int
{
ProController = 1 << 0,
NPadLeftController = 1 << 4,
NPadRightController = 1 << 5,
}
}

View file

@ -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;
}
}

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.Input namespace Ryujinx.HLE.Input
{ {
public enum HidControllerId public enum ControllerId
{ {
ControllerPlayer1 = 0, ControllerPlayer1 = 0,
ControllerPlayer2 = 1, ControllerPlayer2 = 1,

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.Input namespace Ryujinx.HLE.Input
{ {
public enum HidControllerLayouts public enum ControllerLayouts
{ {
ProController = 0, ProController = 0,
HandheldJoined = 1, HandheldJoined = 1,

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -3,7 +3,7 @@ using System;
namespace Ryujinx.HLE.Input namespace Ryujinx.HLE.Input
{ {
[Flags] [Flags]
public enum HidControllerType public enum ControllerStatus : int
{ {
ProController = 1 << 0, ProController = 1 << 0,
Handheld = 1 << 1, Handheld = 1 << 1,

View file

@ -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
}
}

View file

@ -3,7 +3,7 @@
namespace Ryujinx.HLE.Input namespace Ryujinx.HLE.Input
{ {
[Flags] [Flags]
public enum HidHotkeyButtons public enum HotkeyButtons
{ {
ToggleVSync = 1 << 0, ToggleVSync = 1 << 0,
} }

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.Input namespace Ryujinx.HLE.Input
{ {
public struct HidJoystickPosition public struct JoystickPosition
{ {
public int Dx; public int Dx;
public int Dy; public int Dy;

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.Input namespace Ryujinx.HLE.Input
{ {
public enum NpadColor //Thanks to CTCaer public enum NpadColor : int //Thanks to CTCaer
{ {
Black = 0, Black = 0,

View file

@ -7,7 +7,15 @@ namespace Ryujinx.HLE.Input
{ {
private Switch _device; 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; internal long HidPosition;
@ -17,22 +25,42 @@ namespace Ryujinx.HLE.Input
HidPosition = hidPosition; HidPosition = hidPosition;
device.Memory.FillWithZeros(hidPosition, Horizon.HidSize); 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 ? ControllerId controllerId = controllerType == ControllerStatus.Handheld ?
HidControllerId.ControllerHandheld : HidControllerId.ControllerPlayer1; 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 else
{ {
PrimaryController = new HidNpadController(controllerType, PrimaryController = new NpadController(controllerType,
_device, _device,
(NpadColor.BodyNeonRed, NpadColor.BodyNeonRed), (NpadColor.BodyNeonRed, NpadColor.BodyNeonRed),
(NpadColor.ButtonsNeonBlue, NpadColor.ButtonsNeonBlue)); (NpadColor.ButtonsNeonBlue, NpadColor.ButtonsNeonBlue));
} }
@ -44,124 +72,132 @@ namespace Ryujinx.HLE.Input
_device.Memory.FillWithZeros(HidPosition + HidKeyboardOffset, HidKeyboardSize); _device.Memory.FillWithZeros(HidPosition + HidKeyboardOffset, HidKeyboardSize);
} }
public HidControllerButtons UpdateStickButtons( public ControllerButtons UpdateStickButtons(
HidJoystickPosition leftStick, JoystickPosition leftStick,
HidJoystickPosition rightStick) JoystickPosition rightStick)
{ {
HidControllerButtons result = 0; ControllerButtons result = 0;
if (rightStick.Dx < 0) if (rightStick.Dx < 0)
{ {
result |= HidControllerButtons.RStickLeft; result |= ControllerButtons.RStickLeft;
} }
if (rightStick.Dx > 0) if (rightStick.Dx > 0)
{ {
result |= HidControllerButtons.RStickRight; result |= ControllerButtons.RStickRight;
} }
if (rightStick.Dy < 0) if (rightStick.Dy < 0)
{ {
result |= HidControllerButtons.RStickDown; result |= ControllerButtons.RStickDown;
} }
if (rightStick.Dy > 0) if (rightStick.Dy > 0)
{ {
result |= HidControllerButtons.RStickUp; result |= ControllerButtons.RStickUp;
} }
if (leftStick.Dx < 0) if (leftStick.Dx < 0)
{ {
result |= HidControllerButtons.LStickLeft; result |= ControllerButtons.LStickLeft;
} }
if (leftStick.Dx > 0) if (leftStick.Dx > 0)
{ {
result |= HidControllerButtons.LStickRight; result |= ControllerButtons.LStickRight;
} }
if (leftStick.Dy < 0) if (leftStick.Dy < 0)
{ {
result |= HidControllerButtons.LStickDown; result |= ControllerButtons.LStickDown;
} }
if (leftStick.Dy > 0) if (leftStick.Dy > 0)
{ {
result |= HidControllerButtons.LStickUp; result |= ControllerButtons.LStickUp;
} }
return result; return result;
} }
public void SetTouchPoints(params TouchPoint[] points)
public void SetTouchPoints(params HidTouchPoint[] points)
{ {
long touchScreenOffset = HidPosition + HidTouchScreenOffset; long timestamp = GetTimestamp();
long lastEntry = _device.Memory.ReadInt64(touchScreenOffset + 0x10); long sampleCounter = _currentTouchHeader.SamplesTimestamp + 1;
long currEntry = (lastEntry + 1) % HidEntryCount;
long timestamp = GetTimestamp();
_device.Memory.WriteInt64(touchScreenOffset + 0x00, timestamp); var newTouchHeader = new TouchHeader
_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)
{ {
_device.Memory.WriteInt64(touchEntryOffset + 0x00, sampleCounter); CurrentEntryIndex = (_currentTouchHeader.CurrentEntryIndex + 1) % HidEntryCount,
_device.Memory.WriteInt32(touchEntryOffset + 0x08, padding); EntryCount = HidEntryCount,
_device.Memory.WriteInt32(touchEntryOffset + 0x0c, index++); MaxEntries = HidEntryCount - 1,
_device.Memory.WriteInt32(touchEntryOffset + 0x10, point.X); SamplesTimestamp = sampleCounter,
_device.Memory.WriteInt32(touchEntryOffset + 0x14, point.Y); Timestamp = timestamp,
_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);
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 timestamp = GetTimestamp();
long lastEntry = _device.Memory.ReadInt64(keyboardOffset + 0x10);
long currEntry = (lastEntry + 1) % HidEntryCount;
long timestamp = GetTimestamp();
_device.Memory.WriteInt64(keyboardOffset + 0x00, timestamp); var newKeyboardHeader = new KeyboardHeader()
_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++)
{ {
_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() internal static long GetTimestamp()

View file

@ -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;
}
}
}

View file

@ -1,10 +0,0 @@
using System;
namespace Ryujinx.HLE.Input
{
[Flags]
public enum HidControllerColorDesc
{
ColorDescColorsNonexistent = (1 << 1)
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.Input namespace Ryujinx.HLE.Input
{ {
public struct HidKeyboard public struct Keyboard
{ {
public int Modifier; public int Modifier;
public int[] Keys; public int[] Keys;

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.Input namespace Ryujinx.HLE.Input
{ {
public struct HidTouchPoint public struct TouchPoint
{ {
public int X; public int X;
public int Y; public int Y;

View file

@ -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 GPU
{ {
public static class Engine2d public static class Engine2d

View file

@ -64,7 +64,7 @@
"controller_type": "Handheld", "controller_type": "Handheld",
// Enable or disable "direct keyboard access (HID) support" (Provides games access to your keyboard as a text entry device). // 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 // Keyboard Controls
// https://github.com/opentk/opentk/blob/master/src/OpenTK/Input/Key.cs // https://github.com/opentk/opentk/blob/master/src/OpenTK/Input/Key.cs

View file

@ -120,7 +120,7 @@ namespace Ryujinx
/// <summary> /// <summary>
/// The primary controller's type /// The primary controller's type
/// </summary> /// </summary>
public HidControllerType ControllerType { get; private set; } public ControllerStatus ControllerType { get; private set; }
/// <summary> /// <summary>
/// Enable or disable keyboard support (Independent from controllers binding) /// Enable or disable keyboard support (Independent from controllers binding)
@ -135,7 +135,7 @@ namespace Ryujinx
/// <summary> /// <summary>
/// Controller control bindings /// Controller control bindings
/// </summary> /// </summary>
public NpadController GamepadControls { get; private set; } public UI.Input.NpadController GamepadControls { get; private set; }
/// <summary> /// <summary>
/// Loads a configuration file from disk /// Loads a configuration file from disk

View file

@ -23,7 +23,7 @@ namespace Ryujinx
private IGalRenderer _renderer; private IGalRenderer _renderer;
private HidHotkeyButtons _prevHotkeyButtons = 0; private HotkeyButtons _prevHotkeyButtons = 0;
private KeyboardState? _keyboard = null; private KeyboardState? _keyboard = null;
@ -140,11 +140,11 @@ namespace Ryujinx
private new void UpdateFrame() private new void UpdateFrame()
{ {
HidHotkeyButtons currentHotkeyButtons = 0; HotkeyButtons currentHotkeyButtons = 0;
HidControllerButtons currentButton = 0; ControllerButtons currentButton = 0;
HidJoystickPosition leftJoystick; JoystickPosition leftJoystick;
HidJoystickPosition rightJoystick; JoystickPosition rightJoystick;
HidKeyboard? hidKeyboard = null; HLE.Input.Keyboard? hidKeyboard = null;
int leftJoystickDx = 0; int leftJoystickDx = 0;
int leftJoystickDy = 0; int leftJoystickDy = 0;
@ -176,7 +176,7 @@ namespace Ryujinx
if (!hidKeyboard.HasValue) if (!hidKeyboard.HasValue)
{ {
hidKeyboard = new HidKeyboard hidKeyboard = new HLE.Input.Keyboard
{ {
Modifier = 0, Modifier = 0,
Keys = new int[0x8] Keys = new int[0x8]
@ -196,13 +196,13 @@ namespace Ryujinx
(rightJoystickDx, rightJoystickDy) = Configuration.Instance.GamepadControls.GetRightStick(); (rightJoystickDx, rightJoystickDy) = Configuration.Instance.GamepadControls.GetRightStick();
} }
leftJoystick = new HidJoystickPosition leftJoystick = new JoystickPosition
{ {
Dx = leftJoystickDx, Dx = leftJoystickDx,
Dy = leftJoystickDy Dy = leftJoystickDy
}; };
rightJoystick = new HidJoystickPosition rightJoystick = new JoystickPosition
{ {
Dx = rightJoystickDx, Dx = rightJoystickDx,
Dy = rightJoystickDy Dy = rightJoystickDy
@ -247,7 +247,7 @@ namespace Ryujinx
int mX = (scrnMouseX * TouchScreenWidth) / scrnWidth; int mX = (scrnMouseX * TouchScreenWidth) / scrnWidth;
int mY = (scrnMouseY * TouchScreenHeight) / scrnHeight; int mY = (scrnMouseY * TouchScreenHeight) / scrnHeight;
HidTouchPoint currentPoint = new HidTouchPoint TouchPoint currentPoint = new TouchPoint
{ {
X = mX, X = mX,
Y = mY, Y = mY,
@ -274,13 +274,13 @@ namespace Ryujinx
_device.Hid.WriteKeyboard(hidKeyboard.Value); _device.Hid.WriteKeyboard(hidKeyboard.Value);
} }
HidControllerBase controller = _device.Hid.PrimaryController; BaseController controller = _device.Hid.PrimaryController;
controller.SendInput(currentButton, leftJoystick, rightJoystick); controller.SendInput(currentButton, leftJoystick, rightJoystick);
// Toggle vsync // Toggle vsync
if (currentHotkeyButtons.HasFlag(HidHotkeyButtons.ToggleVSync) && if (currentHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync) &&
!_prevHotkeyButtons.HasFlag(HidHotkeyButtons.ToggleVSync)) !_prevHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync))
{ {
_device.EnableDeviceVsync = !_device.EnableDeviceVsync; _device.EnableDeviceVsync = !_device.EnableDeviceVsync;
} }

View file

@ -107,7 +107,7 @@ namespace Ryujinx.UI.Input
Enabled = enabled; Enabled = enabled;
} }
public HidControllerButtons GetButtons() public ControllerButtons GetButtons()
{ {
if (!Enabled) if (!Enabled)
{ {
@ -116,25 +116,25 @@ namespace Ryujinx.UI.Input
GamePadState gpState = GamePad.GetState(Index); GamePadState gpState = GamePad.GetState(Index);
HidControllerButtons buttons = 0; ControllerButtons buttons = 0;
if (IsPressed(gpState, LeftJoycon.DPadUp)) buttons |= HidControllerButtons.DpadUp; if (IsPressed(gpState, LeftJoycon.DPadUp)) buttons |= ControllerButtons.DpadUp;
if (IsPressed(gpState, LeftJoycon.DPadDown)) buttons |= HidControllerButtons.DpadDown; if (IsPressed(gpState, LeftJoycon.DPadDown)) buttons |= ControllerButtons.DpadDown;
if (IsPressed(gpState, LeftJoycon.DPadLeft)) buttons |= HidControllerButtons.DpadLeft; if (IsPressed(gpState, LeftJoycon.DPadLeft)) buttons |= ControllerButtons.DpadLeft;
if (IsPressed(gpState, LeftJoycon.DPadRight)) buttons |= HidControllerButtons.DPadRight; if (IsPressed(gpState, LeftJoycon.DPadRight)) buttons |= ControllerButtons.DPadRight;
if (IsPressed(gpState, LeftJoycon.StickButton)) buttons |= HidControllerButtons.StickLeft; if (IsPressed(gpState, LeftJoycon.StickButton)) buttons |= ControllerButtons.StickLeft;
if (IsPressed(gpState, LeftJoycon.ButtonMinus)) buttons |= HidControllerButtons.Minus; if (IsPressed(gpState, LeftJoycon.ButtonMinus)) buttons |= ControllerButtons.Minus;
if (IsPressed(gpState, LeftJoycon.ButtonL)) buttons |= HidControllerButtons.L; if (IsPressed(gpState, LeftJoycon.ButtonL)) buttons |= ControllerButtons.L;
if (IsPressed(gpState, LeftJoycon.ButtonZl)) buttons |= HidControllerButtons.Zl; if (IsPressed(gpState, LeftJoycon.ButtonZl)) buttons |= ControllerButtons.Zl;
if (IsPressed(gpState, RightJoycon.ButtonA)) buttons |= HidControllerButtons.A; if (IsPressed(gpState, RightJoycon.ButtonA)) buttons |= ControllerButtons.A;
if (IsPressed(gpState, RightJoycon.ButtonB)) buttons |= HidControllerButtons.B; if (IsPressed(gpState, RightJoycon.ButtonB)) buttons |= ControllerButtons.B;
if (IsPressed(gpState, RightJoycon.ButtonX)) buttons |= HidControllerButtons.X; if (IsPressed(gpState, RightJoycon.ButtonX)) buttons |= ControllerButtons.X;
if (IsPressed(gpState, RightJoycon.ButtonY)) buttons |= HidControllerButtons.Y; if (IsPressed(gpState, RightJoycon.ButtonY)) buttons |= ControllerButtons.Y;
if (IsPressed(gpState, RightJoycon.StickButton)) buttons |= HidControllerButtons.StickRight; if (IsPressed(gpState, RightJoycon.StickButton)) buttons |= ControllerButtons.StickRight;
if (IsPressed(gpState, RightJoycon.ButtonPlus)) buttons |= HidControllerButtons.Plus; if (IsPressed(gpState, RightJoycon.ButtonPlus)) buttons |= ControllerButtons.Plus;
if (IsPressed(gpState, RightJoycon.ButtonR)) buttons |= HidControllerButtons.R; if (IsPressed(gpState, RightJoycon.ButtonR)) buttons |= ControllerButtons.R;
if (IsPressed(gpState, RightJoycon.ButtonZr)) buttons |= HidControllerButtons.Zr; if (IsPressed(gpState, RightJoycon.ButtonZr)) buttons |= ControllerButtons.Zr;
return buttons; return buttons;
} }

View file

@ -57,27 +57,27 @@ namespace Ryujinx.UI.Input
/// </summary> /// </summary>
public KeyboardHotkeys Hotkeys { get; private set; } 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.StickButton]) buttons |= ControllerButtons.StickLeft;
if (keyboard[(Key)LeftJoycon.DPadUp]) buttons |= HidControllerButtons.DpadUp; if (keyboard[(Key)LeftJoycon.DPadUp]) buttons |= ControllerButtons.DpadUp;
if (keyboard[(Key)LeftJoycon.DPadDown]) buttons |= HidControllerButtons.DpadDown; if (keyboard[(Key)LeftJoycon.DPadDown]) buttons |= ControllerButtons.DpadDown;
if (keyboard[(Key)LeftJoycon.DPadLeft]) buttons |= HidControllerButtons.DpadLeft; if (keyboard[(Key)LeftJoycon.DPadLeft]) buttons |= ControllerButtons.DpadLeft;
if (keyboard[(Key)LeftJoycon.DPadRight]) buttons |= HidControllerButtons.DPadRight; if (keyboard[(Key)LeftJoycon.DPadRight]) buttons |= ControllerButtons.DPadRight;
if (keyboard[(Key)LeftJoycon.ButtonMinus]) buttons |= HidControllerButtons.Minus; if (keyboard[(Key)LeftJoycon.ButtonMinus]) buttons |= ControllerButtons.Minus;
if (keyboard[(Key)LeftJoycon.ButtonL]) buttons |= HidControllerButtons.L; if (keyboard[(Key)LeftJoycon.ButtonL]) buttons |= ControllerButtons.L;
if (keyboard[(Key)LeftJoycon.ButtonZl]) buttons |= HidControllerButtons.Zl; if (keyboard[(Key)LeftJoycon.ButtonZl]) buttons |= ControllerButtons.Zl;
if (keyboard[(Key)RightJoycon.StickButton]) buttons |= HidControllerButtons.StickRight; if (keyboard[(Key)RightJoycon.StickButton]) buttons |= ControllerButtons.StickRight;
if (keyboard[(Key)RightJoycon.ButtonA]) buttons |= HidControllerButtons.A; if (keyboard[(Key)RightJoycon.ButtonA]) buttons |= ControllerButtons.A;
if (keyboard[(Key)RightJoycon.ButtonB]) buttons |= HidControllerButtons.B; if (keyboard[(Key)RightJoycon.ButtonB]) buttons |= ControllerButtons.B;
if (keyboard[(Key)RightJoycon.ButtonX]) buttons |= HidControllerButtons.X; if (keyboard[(Key)RightJoycon.ButtonX]) buttons |= ControllerButtons.X;
if (keyboard[(Key)RightJoycon.ButtonY]) buttons |= HidControllerButtons.Y; if (keyboard[(Key)RightJoycon.ButtonY]) buttons |= ControllerButtons.Y;
if (keyboard[(Key)RightJoycon.ButtonPlus]) buttons |= HidControllerButtons.Plus; if (keyboard[(Key)RightJoycon.ButtonPlus]) buttons |= ControllerButtons.Plus;
if (keyboard[(Key)RightJoycon.ButtonR]) buttons |= HidControllerButtons.R; if (keyboard[(Key)RightJoycon.ButtonR]) buttons |= ControllerButtons.R;
if (keyboard[(Key)RightJoycon.ButtonZr]) buttons |= HidControllerButtons.Zr; if (keyboard[(Key)RightJoycon.ButtonZr]) buttons |= ControllerButtons.Zr;
return buttons; return buttons;
} }
@ -108,11 +108,11 @@ namespace Ryujinx.UI.Input
return (dx, dy); 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; return buttons;
} }
@ -267,9 +267,9 @@ namespace Ryujinx.UI.Input
new KeyMappingEntry { TargetKey = Key.NumLock, Target = 10 }, 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, Modifier = 0,
Keys = new int[0x8] Keys = new int[0x8]