Little rewrite of HID input (#723)
* change hid sharedmem writing to use structures
This commit is contained in:
parent
1f3a34dd7a
commit
d254548548
42 changed files with 682 additions and 409 deletions
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
142
Ryujinx.HLE/Input/Controller/BaseController.cs
Normal file
142
Ryujinx.HLE/Input/Controller/BaseController.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
Ryujinx.HLE/Input/Controller/NpadController.cs
Normal file
68
Ryujinx.HLE/Input/Controller/NpadController.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
Ryujinx.HLE/Input/Controller/ProController.cs
Normal file
42
Ryujinx.HLE/Input/Controller/ProController.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
Ryujinx.HLE/Input/Controller/Types/BatteryState.cs
Normal file
12
Ryujinx.HLE/Input/Controller/Types/BatteryState.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.Input
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum ControllerColorDescription : int
|
||||||
|
{
|
||||||
|
ColorDescriptionColorsNonexistent = (1 << 1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
18
Ryujinx.HLE/Input/Controller/Types/ControllerDeviceState.cs
Normal file
18
Ryujinx.HLE/Input/Controller/Types/ControllerDeviceState.cs
Normal 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];
|
||||||
|
}
|
||||||
|
}
|
12
Ryujinx.HLE/Input/Controller/Types/ControllerDeviceType.cs
Normal file
12
Ryujinx.HLE/Input/Controller/Types/ControllerDeviceType.cs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
19
Ryujinx.HLE/Input/Controller/Types/ControllerHeader.cs
Normal file
19
Ryujinx.HLE/Input/Controller/Types/ControllerHeader.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,
|
|
@ -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,
|
15
Ryujinx.HLE/Input/Controller/Types/ControllerState.cs
Normal file
15
Ryujinx.HLE/Input/Controller/Types/ControllerState.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
13
Ryujinx.HLE/Input/Controller/Types/ControllerStateHeader.cs
Normal file
13
Ryujinx.HLE/Input/Controller/Types/ControllerStateHeader.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,
|
22
Ryujinx.HLE/Input/Controller/Types/DeviceFlags.cs
Normal file
22
Ryujinx.HLE/Input/Controller/Types/DeviceFlags.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,
|
||||||
}
|
}
|
|
@ -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;
|
|
@ -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,
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.HLE.Input
|
|
||||||
{
|
|
||||||
[Flags]
|
|
||||||
public enum HidControllerColorDesc
|
|
||||||
{
|
|
||||||
ColorDescColorsNonexistent = (1 << 1)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
15
Ryujinx.HLE/Input/Keyboard/KeyboardEntry.cs
Normal file
15
Ryujinx.HLE/Input/Keyboard/KeyboardEntry.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
13
Ryujinx.HLE/Input/Keyboard/KeyboardHeader.cs
Normal file
13
Ryujinx.HLE/Input/Keyboard/KeyboardHeader.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
18
Ryujinx.HLE/Input/Touch/TouchData.cs
Normal file
18
Ryujinx.HLE/Input/Touch/TouchData.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
11
Ryujinx.HLE/Input/Touch/TouchEntry.cs
Normal file
11
Ryujinx.HLE/Input/Touch/TouchEntry.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
14
Ryujinx.HLE/Input/Touch/TouchHeader.cs
Normal file
14
Ryujinx.HLE/Input/Touch/TouchHeader.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]
|
||||||
|
|
Loading…
Reference in a new issue