Use a struct for HID shared memory (based on libnx struct)

This commit is contained in:
gdkchan 2020-01-03 00:31:13 -03:00
commit 77293d77ce
22 changed files with 410 additions and 424 deletions

View file

@ -113,7 +113,7 @@ namespace Ryujinx.HLE.HOS
public int GlobalAccessLogMode { get; set; } public int GlobalAccessLogMode { get; set; }
internal long HidBaseAddress { get; private set; } internal ulong HidBaseAddress { get; private set; }
internal FileSystemServer FsServer { get; private set; } internal FileSystemServer FsServer { get; private set; }
internal EmulatedGameCard GameCard { get; private set; } internal EmulatedGameCard GameCard { get; private set; }
@ -172,7 +172,7 @@ namespace Ryujinx.HLE.HOS
ulong iirsPa = region.Address + HidSize + FontSize; ulong iirsPa = region.Address + HidSize + FontSize;
ulong timePa = region.Address + HidSize + FontSize + IirsSize; ulong timePa = region.Address + HidSize + FontSize + IirsSize;
HidBaseAddress = (long)(hidPa - DramMemoryMap.DramBase); HidBaseAddress = hidPa - DramMemoryMap.DramBase;
KPageList hidPageList = new KPageList(); KPageList hidPageList = new KPageList();
KPageList fontPageList = new KPageList(); KPageList fontPageList = new KPageList();

View file

@ -2,141 +2,100 @@
namespace Ryujinx.HLE.Input namespace Ryujinx.HLE.Input
{ {
public abstract class BaseController : IHidDevice public class BaseController
{ {
protected ControllerStatus HidControllerType;
protected ControllerId ControllerId;
private long _currentLayoutOffset;
private long _mainLayoutOffset;
protected long DeviceStateOffset => Offset + 0x4188;
protected Switch Device { get; } protected Switch Device { get; }
public long Offset { get; private set; } protected ControllerStatus ControllerType;
public bool Connected { get; protected set; }
public ControllerHeader Header { get; private set; } private ControllerId _controllerId;
public ControllerStateHeader CurrentStateHeader { get; private set; } private ControllerLayouts _currentLayout;
public ControllerDeviceState DeviceState { get; private set; }
public ControllerLayouts CurrentLayout { get; private set; } private HidControllerHeader _header;
public ControllerState LastInputState { get; set; } private HidControllerMisc _misc;
public ControllerConnectionState ConnectionState { get; protected set; }
protected ControllerConnectionState ConnectionState;
public BaseController(Switch device, ControllerStatus controllerType) public BaseController(Switch device, ControllerStatus controllerType)
{ {
Device = device; Device = device;
HidControllerType = controllerType; ControllerType = controllerType;
} }
protected void Initialize( protected void Initialize(
bool isHalf, bool isHalf,
(NpadColor left, NpadColor right) bodyColors, (NpadColor Left, NpadColor Right) bodyColors,
(NpadColor left, NpadColor right) buttonColors, (NpadColor Left, NpadColor Right) buttonColors,
ControllerColorDescription singleColorDesc = 0, ControllerColorDescription singleColorDesc = 0,
ControllerColorDescription splitColorDesc = 0, ControllerColorDescription splitColorDesc = 0,
NpadColor singleBodyColor = 0, NpadColor singleBodyColor = 0,
NpadColor singleButtonColor = 0 NpadColor singleButtonColor = 0)
)
{ {
Header = new ControllerHeader() _header = new HidControllerHeader()
{ {
IsJoyConHalf = isHalf ? 1 : 0, Type = ControllerType,
LeftBodyColor = bodyColors.left, IsHalf = isHalf,
LeftButtonColor = buttonColors.left, LeftColorBody = bodyColors.Left,
RightBodyColor = bodyColors.right, LeftColorButtons = buttonColors.Left,
RightButtonColor = buttonColors.right, RightColorBody = bodyColors.Right,
Status = HidControllerType, RightColorButtons = buttonColors.Right,
SingleBodyColor = singleBodyColor, SingleColorBody = singleBodyColor,
SingleButtonColor = singleButtonColor, SingleColorButtons = singleButtonColor,
SplitColorDescription = splitColorDesc, SplitColorsDescriptor = splitColorDesc,
SingleColorDescription = singleColorDesc, SingleColorsDescriptor = singleColorDesc
}; };
CurrentStateHeader = new ControllerStateHeader _misc = new HidControllerMisc()
{
EntryCount = HidEntryCount,
MaxEntryCount = HidEntryCount - 1,
CurrentEntryIndex = -1
};
DeviceState = new ControllerDeviceState()
{ {
PowerInfo0BatteryState = BatteryState.Percent100, PowerInfo0BatteryState = BatteryState.Percent100,
PowerInfo1BatteryState = BatteryState.Percent100, PowerInfo1BatteryState = BatteryState.Percent100,
PowerInfo2BatteryState = BatteryState.Percent100, PowerInfo2BatteryState = BatteryState.Percent100,
DeviceType = ControllerDeviceType.NPadLeftController | ControllerDeviceType.NPadRightController, DeviceType = ControllerDeviceType.NPadLeftController | ControllerDeviceType.NPadRightController,
DeviceFlags = DeviceFlags.PowerInfo0Connected DeviceFlags = DeviceFlags.PowerInfo0Connected |
| DeviceFlags.PowerInfo1Connected DeviceFlags.PowerInfo1Connected |
| DeviceFlags.PowerInfo2Connected DeviceFlags.PowerInfo2Connected
};
LastInputState = new ControllerState()
{
SamplesTimestamp = -1,
SamplesTimestamp2 = -1
}; };
} }
public virtual void Connect(ControllerId controllerId) public virtual void Connect(ControllerId controllerId)
{ {
ControllerId = controllerId; _controllerId = controllerId;
Offset = Device.Hid.HidPosition + HidControllersOffset + (int)controllerId * HidControllerSize; ref HidSharedMemory sharedMemory = ref Device.Hid.SharedMemory;
_mainLayoutOffset = Offset + HidControllerHeaderSize ref HidController controller = ref sharedMemory.Controllers[(int)controllerId];
+ ((int)ControllerLayouts.Main * HidControllerLayoutsSize);
Device.Memory.ZeroFill((ulong)Offset, 0x5000); controller.Header = _header;
Device.Memory.Write((ulong)Offset, Header); controller.Misc = _misc;
Device.Memory.Write((ulong)DeviceStateOffset, DeviceState);
Connected = true;
} }
public void SetLayout(ControllerLayouts controllerLayout) public void SetLayout(ControllerLayouts controllerLayout)
{ {
CurrentLayout = controllerLayout; _currentLayout = controllerLayout;
_currentLayoutOffset = Offset + HidControllerHeaderSize
+ ((int)controllerLayout * HidControllerLayoutsSize);
} }
public void SendInput( public void SendInput(ControllerButtons buttons, JoystickPosition leftStick, JoystickPosition rightStick)
ControllerButtons buttons,
JoystickPosition leftStick,
JoystickPosition rightStick)
{ {
ControllerState currentInput = new ControllerState() ref HidSharedMemory sharedMemory = ref Device.Hid.SharedMemory;
{
SamplesTimestamp = (long)LastInputState.SamplesTimestamp + 1,
SamplesTimestamp2 = (long)LastInputState.SamplesTimestamp + 1,
ButtonState = buttons,
ConnectionState = ConnectionState,
LeftStick = leftStick,
RightStick = rightStick
};
ControllerStateHeader newInputStateHeader = new ControllerStateHeader ref HidControllerLayout layout = ref sharedMemory.Controllers[(int)_controllerId].Layouts[(int)_currentLayout];
{
EntryCount = HidEntryCount,
MaxEntryCount = HidEntryCount - 1,
CurrentEntryIndex = (CurrentStateHeader.CurrentEntryIndex + 1) % HidEntryCount,
Timestamp = GetTimestamp(),
};
Device.Memory.Write((ulong)_currentLayoutOffset, newInputStateHeader); layout.Header.NumEntries = 17;
Device.Memory.Write((ulong)_mainLayoutOffset, newInputStateHeader); layout.Header.MaxEntryIndex = 16;
long currentInputStateOffset = HidControllersLayoutHeaderSize layout.Header.LatestEntry = (layout.Header.LatestEntry + 1) % 17;
+ newInputStateHeader.CurrentEntryIndex * HidControllersInputEntrySize;
Device.Memory.Write((ulong)(_currentLayoutOffset + currentInputStateOffset), currentInput); layout.Header.TimestampTicks = GetTimestamp();
Device.Memory.Write((ulong)(_mainLayoutOffset + currentInputStateOffset), currentInput);
LastInputState = currentInput; ref HidControllerInputEntry entry = ref layout.Entries[(int)layout.Header.LatestEntry];
CurrentStateHeader = newInputStateHeader;
entry.Timestamp++;
entry.Timestamp2++;
entry.Buttons = buttons;
entry.ConnectionState = ConnectionState;
entry.Joysticks[0] = leftStick;
entry.Joysticks[1] = rightStick;
} }
} }
} }

View file

@ -19,7 +19,7 @@
public override void Connect(ControllerId controllerId) public override void Connect(ControllerId controllerId)
{ {
if (HidControllerType != ControllerStatus.NpadLeft && HidControllerType != ControllerStatus.NpadRight) if (ControllerType != ControllerStatus.NpadLeft && ControllerType != ControllerStatus.NpadRight)
{ {
_isHalf = false; _isHalf = false;
} }
@ -27,7 +27,9 @@
ConnectionState = ControllerConnectionState.ControllerStateConnected; ConnectionState = ControllerConnectionState.ControllerStateConnected;
if (controllerId == ControllerId.ControllerHandheld) if (controllerId == ControllerId.ControllerHandheld)
{
ConnectionState |= ControllerConnectionState.ControllerStateWired; ConnectionState |= ControllerConnectionState.ControllerStateWired;
}
ControllerColorDescription singleColorDesc = ControllerColorDescription singleColorDesc =
ControllerColorDescription.ColorDescriptionColorsNonexistent; ControllerColorDescription.ColorDescriptionColorsNonexistent;
@ -37,32 +39,33 @@
NpadColor singleBodyColor = NpadColor.Black; NpadColor singleBodyColor = NpadColor.Black;
NpadColor singleButtonColor = NpadColor.Black; NpadColor singleButtonColor = NpadColor.Black;
Initialize(_isHalf, Initialize(
_isHalf,
(_npadBodyColors.Left, _npadBodyColors.Right), (_npadBodyColors.Left, _npadBodyColors.Right),
(_npadButtonColors.Left, _npadButtonColors.Right), (_npadButtonColors.Left, _npadButtonColors.Right),
singleColorDesc, singleColorDesc,
splitColorDesc, splitColorDesc,
singleBodyColor, singleBodyColor,
singleButtonColor ); singleButtonColor);
base.Connect(controllerId); base.Connect(controllerId);
var _currentLayout = ControllerLayouts.HandheldJoined; var currentLayout = ControllerLayouts.HandheldJoined;
switch (HidControllerType) switch (ControllerType)
{ {
case ControllerStatus.NpadLeft: case ControllerStatus.NpadLeft:
_currentLayout = ControllerLayouts.Left; currentLayout = ControllerLayouts.Left;
break; break;
case ControllerStatus.NpadRight: case ControllerStatus.NpadRight:
_currentLayout = ControllerLayouts.Right; currentLayout = ControllerLayouts.Right;
break; break;
case ControllerStatus.NpadPair: case ControllerStatus.NpadPair:
_currentLayout = ControllerLayouts.Joined; currentLayout = ControllerLayouts.Joined;
break; break;
} }
SetLayout(_currentLayout); SetLayout(currentLayout);
} }
} }
} }

View file

@ -2,17 +2,11 @@
{ {
public class ProController : BaseController public class ProController : BaseController
{ {
private bool _wired = false; private readonly NpadColor _bodyColor;
private readonly NpadColor _buttonColor;
private NpadColor _bodyColor; public ProController(Switch device, NpadColor bodyColor, NpadColor buttonColor) : base(device, ControllerStatus.ProController)
private NpadColor _buttonColor;
public ProController(Switch device,
NpadColor bodyColor,
NpadColor buttonColor) : base(device, ControllerStatus.ProController)
{ {
_wired = true;
_bodyColor = bodyColor; _bodyColor = bodyColor;
_buttonColor = buttonColor; _buttonColor = buttonColor;
} }
@ -26,7 +20,8 @@
ConnectionState = ControllerConnectionState.ControllerStateConnected | ControllerConnectionState.ControllerStateWired; ConnectionState = ControllerConnectionState.ControllerStateConnected | ControllerConnectionState.ControllerStateWired;
Initialize(false, Initialize(
false,
(0, 0), (0, 0),
(0, 0), (0, 0),
singleColorDesc, singleColorDesc,

View file

@ -2,7 +2,7 @@
{ {
public enum BatteryState : int public enum BatteryState : int
{ {
// TODO : Check if these are the correct states // TODO: Check if these are the correct states
Percent0 = 0, Percent0 = 0,
Percent25 = 1, Percent25 = 1,
Percent50 = 2, Percent50 = 2,

View file

@ -1,18 +0,0 @@
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

@ -7,6 +7,6 @@ namespace Ryujinx.HLE.Input
{ {
ProController = 1 << 0, ProController = 1 << 0,
NPadLeftController = 1 << 4, NPadLeftController = 1 << 4,
NPadRightController = 1 << 5, NPadRightController = 1 << 5
} }
} }

View file

@ -1,19 +0,0 @@
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,15 +0,0 @@
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

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

View file

@ -7,59 +7,33 @@ namespace Ryujinx.HLE.Input
{ {
public partial class Hid public partial class Hid
{ {
private Switch _device; private readonly Switch _device;
private long _touchScreenOffset; private ulong _sharedMemoryAddress;
private long _touchEntriesOffset;
private long _keyboardOffset;
private TouchHeader _currentTouchHeader; internal ref HidSharedMemory SharedMemory => ref _device.Memory.GetRef<HidSharedMemory>(_sharedMemoryAddress);
private KeyboardHeader _currentKeyboardHeader;
private KeyboardEntry _currentKeyboardEntry;
public BaseController PrimaryController { get; private set; } public BaseController PrimaryController { get; private set; }
internal long HidPosition; public Hid(Switch device, ulong sharedMemoryAddress)
public Hid(Switch device, long hidPosition)
{ {
_device = device; _device = device;
HidPosition = hidPosition; _sharedMemoryAddress = sharedMemoryAddress;
device.Memory.ZeroFill((ulong)hidPosition, Horizon.HidSize); device.Memory.ZeroFill(sharedMemoryAddress, 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;
} }
private static ControllerStatus ConvertControllerTypeToState(ControllerType controllerType) private static ControllerStatus ConvertControllerTypeToState(ControllerType controllerType)
{ {
switch (controllerType) return controllerType switch
{ {
case ControllerType.Handheld: return ControllerStatus.Handheld; ControllerType.Handheld => ControllerStatus.Handheld,
case ControllerType.NpadLeft: return ControllerStatus.NpadLeft; ControllerType.NpadLeft => ControllerStatus.NpadLeft,
case ControllerType.NpadRight: return ControllerStatus.NpadRight; ControllerType.NpadRight => ControllerStatus.NpadRight,
case ControllerType.NpadPair: return ControllerStatus.NpadPair; ControllerType.NpadPair => ControllerStatus.NpadPair,
case ControllerType.ProController: return ControllerStatus.ProController; ControllerType.ProController => ControllerStatus.ProController,
default: throw new NotImplementedException(); _ => throw new NotImplementedException(),
} };
} }
public void InitializePrimaryController(ControllerType controllerType) public void InitializePrimaryController(ControllerType controllerType)
@ -73,7 +47,8 @@ namespace Ryujinx.HLE.Input
} }
else else
{ {
PrimaryController = new NpadController(ConvertControllerTypeToState(controllerType), PrimaryController = new NpadController(
ConvertControllerTypeToState(controllerType),
_device, _device,
(NpadColor.BodyNeonRed, NpadColor.BodyNeonRed), (NpadColor.BodyNeonRed, NpadColor.BodyNeonRed),
(NpadColor.ButtonsNeonBlue, NpadColor.ButtonsNeonBlue)); (NpadColor.ButtonsNeonBlue, NpadColor.ButtonsNeonBlue));
@ -82,9 +57,7 @@ namespace Ryujinx.HLE.Input
PrimaryController.Connect(controllerId); PrimaryController.Connect(controllerId);
} }
public ControllerButtons UpdateStickButtons( public static ControllerButtons UpdateStickButtons(JoystickPosition leftStick, JoystickPosition rightStick)
JoystickPosition leftStick,
JoystickPosition rightStick)
{ {
ControllerButtons result = 0; ControllerButtons result = 0;
@ -130,93 +103,71 @@ namespace Ryujinx.HLE.Input
return result; return result;
} }
public void SetTouchPoints(params TouchPoint[] points) public void SetTouchPoints(params TouchPoint[] points)
{ {
long timestamp = GetTimestamp(); ref HidSharedMemory sharedMemory = ref SharedMemory;
long sampleCounter = _currentTouchHeader.SamplesTimestamp + 1;
var newTouchHeader = new TouchHeader ref HidTouchScreen touchScreen = ref sharedMemory.Touchscreen;
touchScreen.Header.NumEntries = 17;
touchScreen.Header.MaxEntryIndex = 16;
touchScreen.Header.LatestEntry = (touchScreen.Header.LatestEntry + 1) % 17;
touchScreen.Header.TimestampTicks = GetTimestamp();
ulong timestamp = touchScreen.Header.Timestamp + 1;
touchScreen.Header.Timestamp = timestamp;
ref HidTouchScreenEntry entry = ref touchScreen.Entries[(int)touchScreen.Header.LatestEntry];
entry.Header.Timestamp = timestamp;
entry.Header.NumTouches = (ulong)points.Length;
for (int index = 0; index < points.Length; index++)
{
entry.Touches[index] = new HidTouchScreenEntryTouch()
{ {
CurrentEntryIndex = (_currentTouchHeader.CurrentEntryIndex + 1) % HidEntryCount,
EntryCount = HidEntryCount,
MaxEntries = HidEntryCount - 1,
SamplesTimestamp = sampleCounter,
Timestamp = timestamp, Timestamp = timestamp,
TouchIndex = (uint)index,
X = points[index].X,
Y = points[index].Y,
DiameterX = points[index].DiameterX,
DiameterY = points[index].DiameterY,
Angle = points[index].Angle
}; };
long currentTouchEntryOffset = _touchEntriesOffset + newTouchHeader.CurrentEntryIndex * HidTouchEntrySize;
TouchEntry touchEntry = new TouchEntry()
{
SamplesTimestamp = sampleCounter,
TouchCount = points.Length
};
_device.Memory.Write((ulong)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.Write((ulong)currentTouchEntryOffset, touch);
currentTouchEntryOffset += HidTouchEntryTouchSize;
} }
_device.Memory.Write((ulong)_touchScreenOffset, newTouchHeader);
_currentTouchHeader = newTouchHeader;
} }
public unsafe void WriteKeyboard(Keyboard keyboard) public unsafe void WriteKeyboard(Keyboard keyboard)
{ {
long timestamp = GetTimestamp(); ref HidSharedMemory sharedMemory = ref SharedMemory;
var newKeyboardHeader = new KeyboardHeader() ref HidKeyboard kbd = ref sharedMemory.Keyboard;
{
CurrentEntryIndex = (_currentKeyboardHeader.CurrentEntryIndex + 1) % HidEntryCount,
EntryCount = HidEntryCount,
MaxEntries = HidEntryCount - 1,
Timestamp = timestamp,
};
_device.Memory.Write((ulong)_keyboardOffset, newKeyboardHeader); kbd.Header.NumEntries = 17;
kbd.Header.MaxEntryIndex = 16;
long keyboardEntryOffset = _keyboardOffset + HidKeyboardHeaderSize; kbd.Header.LatestEntry = (kbd.Header.LatestEntry + 1) % 17;
keyboardEntryOffset += newKeyboardHeader.CurrentEntryIndex * HidKeyboardEntrySize;
var newkeyboardEntry = new KeyboardEntry() kbd.Header.TimestampTicks = GetTimestamp();
{
SamplesTimestamp = _currentKeyboardEntry.SamplesTimestamp + 1, kbd.Entries[(int)kbd.Header.LatestEntry].Timestamp++;
SamplesTimestamp2 = _currentKeyboardEntry.SamplesTimestamp2 + 1, kbd.Entries[(int)kbd.Header.LatestEntry].Timestamp2++;
Modifier = keyboard.Modifier,
};
for (int index = 0; index < keyboard.Keys.Length; index++) for (int index = 0; index < keyboard.Keys.Length; index++)
{ {
newkeyboardEntry.Keys[index] = keyboard.Keys[index]; kbd.Entries[(int)kbd.Header.LatestEntry].Keys[index] = keyboard.Keys[index];
} }
_device.Memory.Write((ulong)keyboardEntryOffset, newkeyboardEntry); kbd.Entries[(int)kbd.Header.LatestEntry].Modifier = keyboard.Modifier;
_currentKeyboardEntry = newkeyboardEntry;
_currentKeyboardHeader = newKeyboardHeader;
} }
internal static long GetTimestamp() internal static ulong GetTimestamp()
{ {
return PerformanceCounter.ElapsedMilliseconds * 19200; return (ulong)PerformanceCounter.ElapsedMilliseconds * 19200;
} }
} }
} }

View file

@ -0,0 +1,259 @@
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.Input
{
struct Array2<T> where T : unmanaged { T _e0; T _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 2)[index]; }
struct Array3<T> where T : unmanaged { T _e0; Array2<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 3)[index]; }
struct Array4<T> where T : unmanaged { T _e0; Array3<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 4)[index]; }
struct Array5<T> where T : unmanaged { T _e0; Array4<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 5)[index]; }
struct Array6<T> where T : unmanaged { T _e0; Array5<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 6)[index]; }
struct Array7<T> where T : unmanaged { T _e0; Array6<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 7)[index]; }
struct Array8<T> where T : unmanaged { T _e0; Array7<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 8)[index]; }
struct Array9<T> where T : unmanaged { T _e0; Array8<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 9)[index]; }
struct Array10<T> where T : unmanaged { T _e0; Array9<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 10)[index]; }
struct Array11<T> where T : unmanaged { T _e0; Array10<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 11)[index]; }
struct Array12<T> where T : unmanaged { T _e0; Array11<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 12)[index]; }
struct Array13<T> where T : unmanaged { T _e0; Array12<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 13)[index]; }
struct Array14<T> where T : unmanaged { T _e0; Array13<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 14)[index]; }
struct Array15<T> where T : unmanaged { T _e0; Array14<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 15)[index]; }
struct Array16<T> where T : unmanaged { T _e0; Array15<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 16)[index]; }
struct Array17<T> where T : unmanaged { T _e0; Array16<T> _e1; public ref T this[int index] => ref MemoryMarshal.CreateSpan(ref _e0, 17)[index]; }
struct HidBool
{
private uint _value;
public static implicit operator bool(HidBool value)
{
return (value._value & 1) != 0;
}
public static implicit operator HidBool(bool value)
{
return new HidBool() { _value = value ? 1u : 0u };
}
}
struct MousePosition
{
public int X;
public int Y;
public int VelocityX;
public int VelocityY;
public int ScrollVelocityX;
public int ScrollVelocityY;
}
struct HidVector
{
public float X;
public float Y;
public float Z;
}
struct SixAxisSensorValues
{
public HidVector Accelerometer;
public HidVector Gyroscope;
public HidVector Unk;
public Array3<HidVector> Orientation;
}
struct HidTouchScreenHeader
{
public ulong TimestampTicks;
public ulong NumEntries;
public ulong LatestEntry;
public ulong MaxEntryIndex;
public ulong Timestamp;
}
struct HidTouchScreenEntryHeader
{
public ulong Timestamp;
public ulong NumTouches;
}
struct HidTouchScreenEntryTouch
{
public ulong Timestamp;
public uint Padding;
public uint TouchIndex;
public uint X;
public uint Y;
public uint DiameterX;
public uint DiameterY;
public uint Angle;
public uint Padding2;
}
struct HidTouchScreenEntry
{
public HidTouchScreenEntryHeader Header;
public Array16<HidTouchScreenEntryTouch> Touches;
public ulong Unk;
}
unsafe struct HidTouchScreen
{
public HidTouchScreenHeader Header;
public Array17<HidTouchScreenEntry> Entries;
public fixed byte Padding[0x3c0];
}
struct HidMouseHeader
{
public ulong TimestampTicks;
public ulong NumEntries;
public ulong LatestEntry;
public ulong MaxEntryIndex;
}
struct HidMouseEntry
{
public ulong Timestamp;
public ulong Timestamp_2;
public MousePosition Position;
public ulong Buttons;
}
unsafe struct HidMouse
{
public HidMouseHeader Header;
public Array17<HidMouseEntry> Entries;
public fixed byte Padding[0xB0];
}
struct HidKeyboardHeader
{
public ulong TimestampTicks;
public ulong NumEntries;
public ulong LatestEntry;
public ulong MaxEntryIndex;
}
unsafe struct HidKeyboardEntry
{
public ulong Timestamp;
public ulong Timestamp2;
public ulong Modifier;
public fixed uint Keys[8];
}
unsafe struct HidKeyboard
{
public HidKeyboardHeader Header;
public Array17<HidKeyboardEntry> Entries;
public fixed byte Padding[0x28];
}
unsafe struct HidControllerMAC
{
public ulong Timestamp;
public fixed byte Mac[0x8];
public ulong Unk;
public ulong Timestamp2;
}
struct HidControllerHeader
{
public ControllerStatus Type;
public HidBool IsHalf;
public ControllerColorDescription SingleColorsDescriptor;
public NpadColor SingleColorBody;
public NpadColor SingleColorButtons;
public ControllerColorDescription SplitColorsDescriptor;
public NpadColor LeftColorBody;
public NpadColor LeftColorButtons;
public NpadColor RightColorBody;
public NpadColor RightColorButtons;
}
struct HidControllerLayoutHeader
{
public ulong TimestampTicks;
public ulong NumEntries;
public ulong LatestEntry;
public ulong MaxEntryIndex;
}
struct HidControllerInputEntry
{
public ulong Timestamp;
public ulong Timestamp2;
public ControllerButtons Buttons;
public Array2<JoystickPosition> Joysticks;
public ControllerConnectionState ConnectionState;
}
struct HidControllerLayout
{
public HidControllerLayoutHeader Header;
public Array17<HidControllerInputEntry> Entries;
}
struct HidControllerSixAxisHeader
{
public ulong Timestamp;
public ulong NumEntries;
public ulong LatestEntry;
public ulong MaxEntryIndex;
}
struct HidControllerSixAxisEntry
{
public ulong Timestamp;
public ulong Unk1;
public ulong Timestamp2;
public SixAxisSensorValues Values;
public ulong Unk3;
}
struct HidControllerSixAxisLayout
{
public HidControllerSixAxisHeader Header;
public Array17<HidControllerSixAxisEntry> Entries;
}
unsafe struct HidControllerMisc
{
public ControllerDeviceType DeviceType;
public uint Padding;
public DeviceFlags DeviceFlags;
public uint UnintendedHomeButtonInputProtectionEnabled;
public BatteryState PowerInfo0BatteryState;
public BatteryState PowerInfo1BatteryState;
public BatteryState PowerInfo2BatteryState;
public fixed byte Unk1[0x20];
HidControllerMAC MacLeft;
HidControllerMAC MacRight;
}
unsafe struct HidController
{
public HidControllerHeader Header;
public Array7<HidControllerLayout> Layouts;
public Array6<HidControllerSixAxisLayout> Sixaxis;
public HidControllerMisc Misc;
public fixed byte Unk2[0xDF8];
}
unsafe struct HidSharedMemory
{
public fixed byte Header[0x400];
public HidTouchScreen Touchscreen;
public HidMouse Mouse;
public HidKeyboard Keyboard;
public fixed byte UnkSection1[0x400];
public fixed byte UnkSection2[0x400];
public fixed byte UnkSection3[0x400];
public fixed byte UnkSection4[0x400];
public fixed byte UnkSection5[0x200];
public fixed byte UnkSection6[0x200];
public fixed byte UnkSection7[0x200];
public fixed byte UnkSection8[0x800];
public fixed byte ControllerSerials[0x4000];
public Array10<HidController> Controllers;
public fixed byte UnkSection9[0x4600];
}
}

View file

@ -1,63 +0,0 @@
namespace Ryujinx.HLE.Input
{
public partial class Hid
{
/*
* Reference:
* https://github.com/reswitched/libtransistor/blob/development/lib/hid.c
* https://github.com/reswitched/libtransistor/blob/development/include/libtransistor/hid.h
* https://github.com/switchbrew/libnx/blob/master/nx/source/services/hid.c
* https://github.com/switchbrew/libnx/blob/master/nx/include/switch/services/hid.h
*/
internal const int HidHeaderSize = 0x400;
internal const int HidTouchScreenSize = 0x3000;
internal const int HidMouseSize = 0x400;
internal const int HidKeyboardSize = 0x400;
internal const int HidUnkSection1Size = 0x400;
internal const int HidUnkSection2Size = 0x400;
internal const int HidUnkSection3Size = 0x400;
internal const int HidUnkSection4Size = 0x400;
internal const int HidUnkSection5Size = 0x200;
internal const int HidUnkSection6Size = 0x200;
internal const int HidUnkSection7Size = 0x200;
internal const int HidUnkSection8Size = 0x800;
internal const int HidControllerSerialsSize = 0x4000;
internal const int HidControllersSize = 0x32000;
internal const int HidUnkSection9Size = 0x800;
internal const int HidKeyboardHeaderSize = 0x20;
internal const int HidKeyboardEntrySize = 0x38;
internal const int HidTouchHeaderSize = 0x28;
internal const int HidTouchEntrySize = 0x298;
internal const int HidTouchEntryHeaderSize = 0x10;
internal const int HidTouchEntryTouchSize = 0x28;
internal const int HidControllerSize = 0x5000;
internal const int HidControllerHeaderSize = 0x28;
internal const int HidControllerLayoutsSize = 0x350;
internal const int HidControllersLayoutHeaderSize = 0x20;
internal const int HidControllersInputEntrySize = 0x30;
internal const int HidHeaderOffset = 0;
internal const int HidTouchScreenOffset = HidHeaderOffset + HidHeaderSize;
internal const int HidMouseOffset = HidTouchScreenOffset + HidTouchScreenSize;
internal const int HidKeyboardOffset = HidMouseOffset + HidMouseSize;
internal const int HidUnkSection1Offset = HidKeyboardOffset + HidKeyboardSize;
internal const int HidUnkSection2Offset = HidUnkSection1Offset + HidUnkSection1Size;
internal const int HidUnkSection3Offset = HidUnkSection2Offset + HidUnkSection2Size;
internal const int HidUnkSection4Offset = HidUnkSection3Offset + HidUnkSection3Size;
internal const int HidUnkSection5Offset = HidUnkSection4Offset + HidUnkSection4Size;
internal const int HidUnkSection6Offset = HidUnkSection5Offset + HidUnkSection5Size;
internal const int HidUnkSection7Offset = HidUnkSection6Offset + HidUnkSection6Size;
internal const int HidUnkSection8Offset = HidUnkSection7Offset + HidUnkSection7Size;
internal const int HidControllerSerialsOffset = HidUnkSection8Offset + HidUnkSection8Size;
internal const int HidControllersOffset = HidControllerSerialsOffset + HidControllerSerialsSize;
internal const int HidUnkSection9Offset = HidControllersOffset + HidControllersSize;
internal const int HidEntryCount = 17;
}
}

View file

@ -1,8 +0,0 @@
namespace Ryujinx.HLE.Input
{
interface IHidDevice
{
long Offset { get; }
bool Connected { get; }
}
}

View file

@ -2,7 +2,7 @@ namespace Ryujinx.HLE.Input
{ {
public struct Keyboard public struct Keyboard
{ {
public int Modifier; public uint Modifier;
public int[] Keys; public uint[] Keys;
} }
} }

View file

@ -1,13 +0,0 @@
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.Input
{
[StructLayout(LayoutKind.Sequential)]
public unsafe struct KeyboardEntry
{
public long SamplesTimestamp;
public long SamplesTimestamp2;
public long Modifier;
public fixed int Keys[8];
}
}

View file

@ -1,13 +0,0 @@
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

@ -1,18 +0,0 @@
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

@ -1,14 +0,0 @@
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

@ -2,10 +2,10 @@ namespace Ryujinx.HLE.Input
{ {
public struct TouchPoint public struct TouchPoint
{ {
public int X; public uint X;
public int Y; public uint Y;
public int DiameterX; public uint DiameterX;
public int DiameterY; public uint DiameterY;
public int Angle; public uint Angle;
} }
} }

View file

@ -185,7 +185,7 @@ namespace Ryujinx.Ui
hidKeyboard = new HLE.Input.Keyboard hidKeyboard = new HLE.Input.Keyboard
{ {
Modifier = 0, Modifier = 0,
Keys = new int[0x8] Keys = new uint[0x8]
}; };
} }
@ -214,7 +214,7 @@ namespace Ryujinx.Ui
Dy = rightJoystickDy Dy = rightJoystickDy
}; };
currentButton |= _device.Hid.UpdateStickButtons(leftJoystick, rightJoystick); currentButton |= Hid.UpdateStickButtons(leftJoystick, rightJoystick);
bool hasTouch = false; bool hasTouch = false;
@ -255,8 +255,8 @@ namespace Ryujinx.Ui
TouchPoint currentPoint = new TouchPoint TouchPoint currentPoint = new TouchPoint
{ {
X = mX, X = (uint)mX,
Y = mY, Y = (uint)mY,
// Placeholder values till more data is acquired // Placeholder values till more data is acquired
DiameterX = 10, DiameterX = 10,

View file

@ -221,21 +221,21 @@ namespace Ryujinx.Ui
HLE.Input.Keyboard hidKeyboard = new HLE.Input.Keyboard HLE.Input.Keyboard hidKeyboard = new HLE.Input.Keyboard
{ {
Modifier = 0, Modifier = 0,
Keys = new int[0x8] Keys = new uint[0x8]
}; };
foreach (KeyMappingEntry entry in KeyMapping) foreach (KeyMappingEntry entry in KeyMapping)
{ {
int value = keyboard[entry.TargetKey] ? 1 : 0; int value = keyboard[entry.TargetKey] ? 1 : 0;
hidKeyboard.Keys[entry.Target / 0x20] |= (value << (entry.Target % 0x20)); hidKeyboard.Keys[entry.Target / 0x20] |= (uint)value << (entry.Target % 0x20);
} }
foreach (KeyMappingEntry entry in KeyModifierMapping) foreach (KeyMappingEntry entry in KeyModifierMapping)
{ {
int value = keyboard[entry.TargetKey] ? 1 : 0; int value = keyboard[entry.TargetKey] ? 1 : 0;
hidKeyboard.Modifier |= value << entry.Target; hidKeyboard.Modifier |= (uint)value << entry.Target;
} }
return hidKeyboard; return hidKeyboard;