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
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
|
||||
}
|
||||
}
|
35
Ryujinx.HLE/Input/Controller/Types/ControllerButtons.cs
Normal file
35
Ryujinx.HLE/Input/Controller/Types/ControllerButtons.cs
Normal file
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.Input
|
||||
{
|
||||
[Flags]
|
||||
public enum ControllerButtons : long
|
||||
{
|
||||
A = 1 << 0,
|
||||
B = 1 << 1,
|
||||
X = 1 << 2,
|
||||
Y = 1 << 3,
|
||||
StickLeft = 1 << 4,
|
||||
StickRight = 1 << 5,
|
||||
L = 1 << 6,
|
||||
R = 1 << 7,
|
||||
Zl = 1 << 8,
|
||||
Zr = 1 << 9,
|
||||
Plus = 1 << 10,
|
||||
Minus = 1 << 11,
|
||||
DpadLeft = 1 << 12,
|
||||
DpadUp = 1 << 13,
|
||||
DPadRight = 1 << 14,
|
||||
DpadDown = 1 << 15,
|
||||
LStickLeft = 1 << 16,
|
||||
LStickUp = 1 << 17,
|
||||
LStickRight = 1 << 18,
|
||||
LStickDown = 1 << 19,
|
||||
RStickLeft = 1 << 20,
|
||||
RStickUp = 1 << 21,
|
||||
RStickRight = 1 << 22,
|
||||
RStickDown = 1 << 23,
|
||||
Sl = 1 << 24,
|
||||
Sr = 1 << 25
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.Input
|
||||
{
|
||||
[Flags]
|
||||
public enum ControllerColorDescription : int
|
||||
{
|
||||
ColorDescriptionColorsNonexistent = (1 << 1)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.Input
|
||||
{
|
||||
[Flags]
|
||||
public enum ControllerConnectionState : long
|
||||
{
|
||||
ControllerStateConnected = (1 << 0),
|
||||
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;
|
||||
}
|
||||
}
|
16
Ryujinx.HLE/Input/Controller/Types/ControllerId.cs
Normal file
16
Ryujinx.HLE/Input/Controller/Types/ControllerId.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
namespace Ryujinx.HLE.Input
|
||||
{
|
||||
public enum ControllerId
|
||||
{
|
||||
ControllerPlayer1 = 0,
|
||||
ControllerPlayer2 = 1,
|
||||
ControllerPlayer3 = 2,
|
||||
ControllerPlayer4 = 3,
|
||||
ControllerPlayer5 = 4,
|
||||
ControllerPlayer6 = 5,
|
||||
ControllerPlayer7 = 6,
|
||||
ControllerPlayer8 = 7,
|
||||
ControllerHandheld = 8,
|
||||
ControllerUnknown = 9
|
||||
}
|
||||
}
|
13
Ryujinx.HLE/Input/Controller/Types/ControllerLayouts.cs
Normal file
13
Ryujinx.HLE/Input/Controller/Types/ControllerLayouts.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
namespace Ryujinx.HLE.Input
|
||||
{
|
||||
public enum ControllerLayouts
|
||||
{
|
||||
ProController = 0,
|
||||
HandheldJoined = 1,
|
||||
Joined = 2,
|
||||
Left = 3,
|
||||
Right = 4,
|
||||
MainNoAnalog = 5,
|
||||
Main = 6
|
||||
}
|
||||
}
|
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;
|
||||
}
|
||||
}
|
14
Ryujinx.HLE/Input/Controller/Types/ControllerStatus.cs
Normal file
14
Ryujinx.HLE/Input/Controller/Types/ControllerStatus.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.Input
|
||||
{
|
||||
[Flags]
|
||||
public enum ControllerStatus : int
|
||||
{
|
||||
ProController = 1 << 0,
|
||||
Handheld = 1 << 1,
|
||||
NpadPair = 1 << 2,
|
||||
NpadLeft = 1 << 3,
|
||||
NpadRight = 1 << 4
|
||||
}
|
||||
}
|
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
|
||||
}
|
||||
}
|
10
Ryujinx.HLE/Input/Controller/Types/HotkeyButtons.cs
Normal file
10
Ryujinx.HLE/Input/Controller/Types/HotkeyButtons.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.Input
|
||||
{
|
||||
[Flags]
|
||||
public enum HotkeyButtons
|
||||
{
|
||||
ToggleVSync = 1 << 0,
|
||||
}
|
||||
}
|
8
Ryujinx.HLE/Input/Controller/Types/JoystickPosition.cs
Normal file
8
Ryujinx.HLE/Input/Controller/Types/JoystickPosition.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Ryujinx.HLE.Input
|
||||
{
|
||||
public struct JoystickPosition
|
||||
{
|
||||
public int Dx;
|
||||
public int Dy;
|
||||
}
|
||||
}
|
23
Ryujinx.HLE/Input/Controller/Types/NpadColor.cs
Normal file
23
Ryujinx.HLE/Input/Controller/Types/NpadColor.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
namespace Ryujinx.HLE.Input
|
||||
{
|
||||
public enum NpadColor : int //Thanks to CTCaer
|
||||
{
|
||||
Black = 0,
|
||||
|
||||
BodyGrey = 0x828282,
|
||||
BodyNeonBlue = 0x0AB9E6,
|
||||
BodyNeonRed = 0xFF3C28,
|
||||
BodyNeonYellow = 0xE6FF00,
|
||||
BodyNeonPink = 0xFF3278,
|
||||
BodyNeonGreen = 0x1EDC00,
|
||||
BodyRed = 0xE10F00,
|
||||
|
||||
ButtonsGrey = 0x0F0F0F,
|
||||
ButtonsNeonBlue = 0x001E1E,
|
||||
ButtonsNeonRed = 0x1E0A0A,
|
||||
ButtonsNeonYellow = 0x142800,
|
||||
ButtonsNeonPink = 0x28001E,
|
||||
ButtonsNeonGreen = 0x002800,
|
||||
ButtonsRed = 0x280A0A
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue