using Ryujinx.Common; using Ryujinx.Configuration.Hid; using Ryujinx.HLE.HOS; using System; namespace Ryujinx.HLE.Input { public partial class Hid { private Switch _device; 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; public Hid(Switch device, long hidPosition) { _device = device; HidPosition = hidPosition; 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; } private static ControllerStatus ConvertControllerTypeToState(ControllerType controllerType) { 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 ? ControllerId.ControllerHandheld : ControllerId.ControllerPlayer1; if (controllerType == ControllerType.ProController) { PrimaryController = new ProController(_device, NpadColor.Black, NpadColor.Black); } else { PrimaryController = new NpadController(ConvertControllerTypeToState(controllerType), _device, (NpadColor.BodyNeonRed, NpadColor.BodyNeonRed), (NpadColor.ButtonsNeonBlue, NpadColor.ButtonsNeonBlue)); } PrimaryController.Connect(controllerId); } public ControllerButtons UpdateStickButtons( JoystickPosition leftStick, JoystickPosition rightStick) { ControllerButtons result = 0; if (rightStick.Dx < 0) { result |= ControllerButtons.RStickLeft; } if (rightStick.Dx > 0) { result |= ControllerButtons.RStickRight; } if (rightStick.Dy < 0) { result |= ControllerButtons.RStickDown; } if (rightStick.Dy > 0) { result |= ControllerButtons.RStickUp; } if (leftStick.Dx < 0) { result |= ControllerButtons.LStickLeft; } if (leftStick.Dx > 0) { result |= ControllerButtons.LStickRight; } if (leftStick.Dy < 0) { result |= ControllerButtons.LStickDown; } if (leftStick.Dy > 0) { result |= ControllerButtons.LStickUp; } return result; } public void SetTouchPoints(params TouchPoint[] points) { long timestamp = GetTimestamp(); long sampleCounter = _currentTouchHeader.SamplesTimestamp + 1; var newTouchHeader = new TouchHeader { CurrentEntryIndex = (_currentTouchHeader.CurrentEntryIndex + 1) % HidEntryCount, EntryCount = HidEntryCount, MaxEntries = HidEntryCount - 1, SamplesTimestamp = sampleCounter, Timestamp = timestamp, }; 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 unsafe void WriteKeyboard(Keyboard keyboard) { long timestamp = GetTimestamp(); var newKeyboardHeader = new KeyboardHeader() { 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() { return PerformanceCounter.ElapsedMilliseconds * 19200; } } }