2018-11-20 00:01:36 +00:00
|
|
|
|
using Ryujinx.Common;
|
2019-12-21 19:52:31 +00:00
|
|
|
|
using Ryujinx.Configuration.Hid;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
using Ryujinx.HLE.HOS;
|
2019-12-21 19:52:31 +00:00
|
|
|
|
using System;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
|
|
|
|
namespace Ryujinx.HLE.Input
|
|
|
|
|
{
|
|
|
|
|
public partial class Hid
|
|
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
|
private Switch _device;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
private long _touchScreenOffset;
|
|
|
|
|
private long _touchEntriesOffset;
|
|
|
|
|
private long _keyboardOffset;
|
|
|
|
|
|
|
|
|
|
private TouchHeader _currentTouchHeader;
|
|
|
|
|
private KeyboardHeader _currentKeyboardHeader;
|
|
|
|
|
private KeyboardEntry _currentKeyboardEntry;
|
|
|
|
|
|
|
|
|
|
public BaseController PrimaryController { get; private set; }
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
|
|
|
|
internal long HidPosition;
|
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
public Hid(Switch device, long hidPosition)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
|
_device = device;
|
|
|
|
|
HidPosition = hidPosition;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
device.Memory.FillWithZeros(hidPosition, Horizon.HidSize);
|
2019-07-22 18:15:46 +01:00
|
|
|
|
|
|
|
|
|
_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;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-12-21 19:52:31 +00:00
|
|
|
|
private static ControllerStatus ConvertControllerTypeToState(ControllerType controllerType)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-12-21 19:52:31 +00:00
|
|
|
|
switch (controllerType)
|
|
|
|
|
{
|
|
|
|
|
case ControllerType.Handheld: return ControllerStatus.Handheld;
|
|
|
|
|
case ControllerType.NpadLeft: return ControllerStatus.NpadLeft;
|
|
|
|
|
case ControllerType.NpadRight: return ControllerStatus.NpadRight;
|
|
|
|
|
case ControllerType.NpadPair: return ControllerStatus.NpadPair;
|
|
|
|
|
case ControllerType.ProController: return ControllerStatus.ProController;
|
|
|
|
|
default: throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void InitializePrimaryController(ControllerType controllerType)
|
|
|
|
|
{
|
|
|
|
|
ControllerId controllerId = controllerType == ControllerType.Handheld ?
|
2019-07-22 18:15:46 +01:00
|
|
|
|
ControllerId.ControllerHandheld : ControllerId.ControllerPlayer1;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
2019-12-21 19:52:31 +00:00
|
|
|
|
if (controllerType == ControllerType.ProController)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
PrimaryController = new ProController(_device, NpadColor.Black, NpadColor.Black);
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-12-21 19:52:31 +00:00
|
|
|
|
PrimaryController = new NpadController(ConvertControllerTypeToState(controllerType),
|
2018-12-06 11:16:24 +00:00
|
|
|
|
_device,
|
2019-07-22 18:15:46 +01:00
|
|
|
|
(NpadColor.BodyNeonRed, NpadColor.BodyNeonRed),
|
2018-12-06 11:16:24 +00:00
|
|
|
|
(NpadColor.ButtonsNeonBlue, NpadColor.ButtonsNeonBlue));
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
PrimaryController.Connect(controllerId);
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
public ControllerButtons UpdateStickButtons(
|
|
|
|
|
JoystickPosition leftStick,
|
|
|
|
|
JoystickPosition rightStick)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
ControllerButtons result = 0;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
if (rightStick.Dx < 0)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
result |= ControllerButtons.RStickLeft;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
if (rightStick.Dx > 0)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
result |= ControllerButtons.RStickRight;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
if (rightStick.Dy < 0)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
result |= ControllerButtons.RStickDown;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
if (rightStick.Dy > 0)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
result |= ControllerButtons.RStickUp;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
if (leftStick.Dx < 0)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
result |= ControllerButtons.LStickLeft;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
if (leftStick.Dx > 0)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
result |= ControllerButtons.LStickRight;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
if (leftStick.Dy < 0)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
result |= ControllerButtons.LStickDown;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
if (leftStick.Dy > 0)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
result |= ControllerButtons.LStickUp;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
|
return result;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
2019-07-22 18:15:46 +01:00
|
|
|
|
public void SetTouchPoints(params TouchPoint[] points)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
long timestamp = GetTimestamp();
|
|
|
|
|
long sampleCounter = _currentTouchHeader.SamplesTimestamp + 1;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
var newTouchHeader = new TouchHeader
|
|
|
|
|
{
|
|
|
|
|
CurrentEntryIndex = (_currentTouchHeader.CurrentEntryIndex + 1) % HidEntryCount,
|
|
|
|
|
EntryCount = HidEntryCount,
|
|
|
|
|
MaxEntries = HidEntryCount - 1,
|
|
|
|
|
SamplesTimestamp = sampleCounter,
|
|
|
|
|
Timestamp = timestamp,
|
|
|
|
|
};
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
long currentTouchEntryOffset = _touchEntriesOffset + newTouchHeader.CurrentEntryIndex * HidTouchEntrySize;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
TouchEntry touchEntry = new TouchEntry()
|
|
|
|
|
{
|
|
|
|
|
SamplesTimestamp = sampleCounter,
|
|
|
|
|
TouchCount = points.Length
|
|
|
|
|
};
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
_device.Memory.WriteStruct(currentTouchEntryOffset, touchEntry);
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
currentTouchEntryOffset += HidTouchEntryHeaderSize;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
for (int i = 0; i < points.Length; i++)
|
2018-11-20 00:01:36 +00:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
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;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
2019-07-22 18:15:46 +01:00
|
|
|
|
|
|
|
|
|
_device.Memory.WriteStruct(_touchScreenOffset, newTouchHeader);
|
|
|
|
|
|
|
|
|
|
_currentTouchHeader = newTouchHeader;
|
2018-11-20 00:01:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
public unsafe void WriteKeyboard(Keyboard keyboard)
|
2019-05-03 00:29:01 +01:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
long timestamp = GetTimestamp();
|
2019-05-03 00:29:01 +01:00
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
var newKeyboardHeader = new KeyboardHeader()
|
|
|
|
|
{
|
|
|
|
|
CurrentEntryIndex = (_currentKeyboardHeader.CurrentEntryIndex + 1) % HidEntryCount,
|
|
|
|
|
EntryCount = HidEntryCount,
|
|
|
|
|
MaxEntries = HidEntryCount - 1,
|
|
|
|
|
Timestamp = timestamp,
|
|
|
|
|
};
|
2019-05-03 00:29:01 +01:00
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
_device.Memory.WriteStruct(_keyboardOffset, newKeyboardHeader);
|
2019-05-03 00:29:01 +01:00
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
long keyboardEntryOffset = _keyboardOffset + HidKeyboardHeaderSize;
|
|
|
|
|
keyboardEntryOffset += newKeyboardHeader.CurrentEntryIndex * HidKeyboardEntrySize;
|
2019-05-03 00:29:01 +01:00
|
|
|
|
|
2019-07-22 18:15:46 +01:00
|
|
|
|
var newkeyboardEntry = new KeyboardEntry()
|
2019-05-03 00:29:01 +01:00
|
|
|
|
{
|
2019-07-22 18:15:46 +01:00
|
|
|
|
SamplesTimestamp = _currentKeyboardEntry.SamplesTimestamp + 1,
|
|
|
|
|
SamplesTimestamp2 = _currentKeyboardEntry.SamplesTimestamp2 + 1,
|
|
|
|
|
Keys = keyboard.Keys,
|
|
|
|
|
Modifier = keyboard.Modifier,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
_device.Memory.WriteStruct(keyboardEntryOffset, newkeyboardEntry);
|
|
|
|
|
|
|
|
|
|
_currentKeyboardEntry = newkeyboardEntry;
|
|
|
|
|
_currentKeyboardHeader = newKeyboardHeader;
|
2019-05-03 00:29:01 +01:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-20 00:01:36 +00:00
|
|
|
|
internal static long GetTimestamp()
|
|
|
|
|
{
|
|
|
|
|
return PerformanceCounter.ElapsedMilliseconds * 19200;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|