From dc02ac08caa84456e8b280a3347ac8907b5249ff Mon Sep 17 00:00:00 2001 From: emmauss Date: Tue, 20 Nov 2018 02:01:36 +0200 Subject: Support other switch controller types (#487) * Make controllers modular, support changing controller type * return readable events * signal hid events * fix style --- Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs | 37 +++- Ryujinx.HLE/Hid/Hid.cs | 273 ---------------------------- Ryujinx.HLE/Hid/HidControllerButtons.cs | 35 ---- Ryujinx.HLE/Hid/HidControllerColorDesc.cs | 10 - Ryujinx.HLE/Hid/HidControllerConnState.cs | 11 -- Ryujinx.HLE/Hid/HidControllerId.cs | 16 -- Ryujinx.HLE/Hid/HidControllerLayouts.cs | 13 -- Ryujinx.HLE/Hid/HidControllerType.cs | 14 -- Ryujinx.HLE/Hid/HidJoystickPosition.cs | 8 - Ryujinx.HLE/Hid/HidTouchPoint.cs | 11 -- Ryujinx.HLE/Hid/JoyConColor.cs | 23 --- Ryujinx.HLE/Input/Hid.cs | 140 ++++++++++++++ Ryujinx.HLE/Input/HidBaseController.cs | 76 ++++++++ Ryujinx.HLE/Input/HidControllerButtons.cs | 35 ++++ Ryujinx.HLE/Input/HidControllerColorDesc.cs | 10 + Ryujinx.HLE/Input/HidControllerConnState.cs | 11 ++ Ryujinx.HLE/Input/HidControllerId.cs | 16 ++ Ryujinx.HLE/Input/HidControllerLayouts.cs | 13 ++ Ryujinx.HLE/Input/HidControllerType.cs | 14 ++ Ryujinx.HLE/Input/HidJoystickPosition.cs | 8 + Ryujinx.HLE/Input/HidNpadController.cs | 86 +++++++++ Ryujinx.HLE/Input/HidProController.cs | 44 +++++ Ryujinx.HLE/Input/HidTouchPoint.cs | 11 ++ Ryujinx.HLE/Input/HidValues.cs | 64 +++++++ Ryujinx.HLE/Input/IHidDevice.cs | 12 ++ Ryujinx.HLE/Input/NpadColor.cs | 23 +++ Ryujinx/Config.cs | 23 ++- Ryujinx/Ryujinx.conf | 3 + Ryujinx/Ui/GLScreen.cs | 31 +--- Ryujinx/Ui/JoyConController.cs | 216 ---------------------- Ryujinx/Ui/JoyConKeyboard.cs | 102 ----------- Ryujinx/Ui/NpadController.cs | 216 ++++++++++++++++++++++ Ryujinx/Ui/NpadKeyboard.cs | 102 +++++++++++ 33 files changed, 936 insertions(+), 771 deletions(-) delete mode 100644 Ryujinx.HLE/Hid/Hid.cs delete mode 100644 Ryujinx.HLE/Hid/HidControllerButtons.cs delete mode 100644 Ryujinx.HLE/Hid/HidControllerColorDesc.cs delete mode 100644 Ryujinx.HLE/Hid/HidControllerConnState.cs delete mode 100644 Ryujinx.HLE/Hid/HidControllerId.cs delete mode 100644 Ryujinx.HLE/Hid/HidControllerLayouts.cs delete mode 100644 Ryujinx.HLE/Hid/HidControllerType.cs delete mode 100644 Ryujinx.HLE/Hid/HidJoystickPosition.cs delete mode 100644 Ryujinx.HLE/Hid/HidTouchPoint.cs delete mode 100644 Ryujinx.HLE/Hid/JoyConColor.cs create mode 100644 Ryujinx.HLE/Input/Hid.cs create mode 100644 Ryujinx.HLE/Input/HidBaseController.cs create mode 100644 Ryujinx.HLE/Input/HidControllerButtons.cs create mode 100644 Ryujinx.HLE/Input/HidControllerColorDesc.cs create mode 100644 Ryujinx.HLE/Input/HidControllerConnState.cs create mode 100644 Ryujinx.HLE/Input/HidControllerId.cs create mode 100644 Ryujinx.HLE/Input/HidControllerLayouts.cs create mode 100644 Ryujinx.HLE/Input/HidControllerType.cs create mode 100644 Ryujinx.HLE/Input/HidJoystickPosition.cs create mode 100644 Ryujinx.HLE/Input/HidNpadController.cs create mode 100644 Ryujinx.HLE/Input/HidProController.cs create mode 100644 Ryujinx.HLE/Input/HidTouchPoint.cs create mode 100644 Ryujinx.HLE/Input/HidValues.cs create mode 100644 Ryujinx.HLE/Input/IHidDevice.cs create mode 100644 Ryujinx.HLE/Input/NpadColor.cs delete mode 100644 Ryujinx/Ui/JoyConController.cs delete mode 100644 Ryujinx/Ui/JoyConKeyboard.cs create mode 100644 Ryujinx/Ui/NpadController.cs create mode 100644 Ryujinx/Ui/NpadKeyboard.cs diff --git a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs index e54ca812..1af734ff 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs @@ -23,7 +23,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid private bool UsbFullKeyControllerEnabled; private HidNpadJoyHoldType NpadJoyHoldType; - private HidNpadStyle NpadStyleTag; + private HidNpadStyle NpadStyleSet; private HidNpadJoyAssignmentMode NpadJoyAssignmentMode; private HidNpadHandheldActivationMode NpadHandheldActivationMode; private HidGyroscopeZeroDriftMode GyroscopeZeroDriftMode; @@ -153,7 +153,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid PalmaOperationCompleteEvent = new KEvent(System); NpadJoyHoldType = HidNpadJoyHoldType.Vertical; - NpadStyleTag = HidNpadStyle.FullKey | HidNpadStyle.Dual | HidNpadStyle.Left | HidNpadStyle.Right; + NpadStyleSet = HidNpadStyle.FullKey | HidNpadStyle.Dual | HidNpadStyle.Left | HidNpadStyle.Right | HidNpadStyle.Handheld; NpadJoyAssignmentMode = HidNpadJoyAssignmentMode.Dual; NpadHandheldActivationMode = HidNpadHandheldActivationMode.Dual; GyroscopeZeroDriftMode = HidGyroscopeZeroDriftMode.Standard; @@ -161,6 +161,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid SensorFusionParams = new HidSensorFusionParameters(); AccelerometerParams = new HidAccelerometerParameters(); VibrationValue = new HidVibrationValue(); + + // TODO: signal event at right place + XpadIdEvent.ReadableEvent.Signal(); } // CreateAppletResource(nn::applet::AppletResourceUserId) -> object @@ -218,7 +221,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid { long XpadId = Context.RequestData.ReadInt64(); - if (Context.Process.HandleTable.GenerateHandle(XpadIdEvent, out XpadIdEventHandle) != KernelResult.Success) + if (Context.Process.HandleTable.GenerateHandle(XpadIdEvent.ReadableEvent, out XpadIdEventHandle) != KernelResult.Success) { throw new InvalidOperationException("Out of handles!"); } @@ -652,12 +655,14 @@ namespace Ryujinx.HLE.HOS.Services.Hid // SetSupportedNpadStyleSet(nn::applet::AppletResourceUserId, nn::hid::NpadStyleTag) public long SetSupportedNpadStyleSet(ServiceCtx Context) { - NpadStyleTag = (HidNpadStyle)Context.RequestData.ReadInt32(); + NpadStyleSet = (HidNpadStyle)Context.RequestData.ReadInt32(); long AppletResourceUserId = Context.RequestData.ReadInt64(); Logger.PrintStub(LogClass.ServiceHid, $"Stubbed. AppletResourceUserId: {AppletResourceUserId} - " + - $"NpadStyleTag: {NpadStyleTag}"); + $"NpadStyleSet: {NpadStyleSet}"); + + NpadStyleSetUpdateEvent.ReadableEvent.Signal(); return 0; } @@ -667,10 +672,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid { long AppletResourceUserId = Context.RequestData.ReadInt64(); - Context.ResponseData.Write((int)NpadStyleTag); + Context.ResponseData.Write((int)NpadStyleSet); Logger.PrintStub(LogClass.ServiceHid, $"Stubbed. AppletResourceUserId: {AppletResourceUserId} - " + - $"NpadStyleTag: {NpadStyleTag}"); + $"NpadStyleSet: {NpadStyleSet}"); return 0; } @@ -714,7 +719,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid int NpadId = Context.RequestData.ReadInt32(); long NpadStyleSet = Context.RequestData.ReadInt64(); - if (Context.Process.HandleTable.GenerateHandle(NpadStyleSetUpdateEvent, out int Handle) != KernelResult.Success) + if (Context.Process.HandleTable.GenerateHandle(NpadStyleSetUpdateEvent.ReadableEvent, out int Handle) != KernelResult.Success) { throw new InvalidOperationException("Out of handles!"); } @@ -1348,6 +1353,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid Logger.PrintStub(LogClass.ServiceHid, $"Stubbed. PalmaConnectionHandle: {PalmaConnectionHandle}"); + PalmaOperationCompleteEvent.ReadableEvent.Signal(); + return 0; } @@ -1356,7 +1363,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid { int PalmaConnectionHandle = Context.RequestData.ReadInt32(); - if (Context.Process.HandleTable.GenerateHandle(PalmaOperationCompleteEvent, out int Handle) != KernelResult.Success) + if (Context.Process.HandleTable.GenerateHandle(PalmaOperationCompleteEvent.ReadableEvent, out int Handle) != KernelResult.Success) { throw new InvalidOperationException("Out of handles!"); } @@ -1392,6 +1399,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid Logger.PrintStub(LogClass.ServiceHid, $"Stubbed. PalmaConnectionHandle: {PalmaConnectionHandle} - " + $"Unknown0: {Unknown0}"); + PalmaOperationCompleteEvent.ReadableEvent.Signal(); + return 0; } @@ -1404,6 +1413,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid Logger.PrintStub(LogClass.ServiceHid, $"Stubbed. PalmaConnectionHandle: {PalmaConnectionHandle} - " + $"FrModeType: {FrModeType}"); + PalmaOperationCompleteEvent.ReadableEvent.Signal(); + return 0; } @@ -1426,6 +1437,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid Logger.PrintStub(LogClass.ServiceHid, $"Stubbed. PalmaConnectionHandle: {PalmaConnectionHandle} - " + $"EnabledPalmaStep: {EnabledPalmaStep}"); + PalmaOperationCompleteEvent.ReadableEvent.Signal(); + return 0; } @@ -1436,6 +1449,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid Logger.PrintStub(LogClass.ServiceHid, $"Stubbed. PalmaConnectionHandle: {PalmaConnectionHandle}"); + PalmaOperationCompleteEvent.ReadableEvent.Signal(); + return 0; } @@ -1446,6 +1461,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid Logger.PrintStub(LogClass.ServiceHid, $"Stubbed. PalmaConnectionHandle: {PalmaConnectionHandle}"); + PalmaOperationCompleteEvent.ReadableEvent.Signal(); + return 0; } @@ -1475,6 +1492,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid $"Unknown0: {Unknown0} - " + $"Unknown1: {Unknown1}"); + PalmaOperationCompleteEvent.ReadableEvent.Signal(); + return 0; } diff --git a/Ryujinx.HLE/Hid/Hid.cs b/Ryujinx.HLE/Hid/Hid.cs deleted file mode 100644 index 21580223..00000000 --- a/Ryujinx.HLE/Hid/Hid.cs +++ /dev/null @@ -1,273 +0,0 @@ -using Ryujinx.Common; -using Ryujinx.HLE.HOS; -using System; - -namespace Ryujinx.HLE.Input -{ - public 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 - */ - - private const int HidHeaderSize = 0x400; - private const int HidTouchScreenSize = 0x3000; - private const int HidMouseSize = 0x400; - private const int HidKeyboardSize = 0x400; - private const int HidUnkSection1Size = 0x400; - private const int HidUnkSection2Size = 0x400; - private const int HidUnkSection3Size = 0x400; - private const int HidUnkSection4Size = 0x400; - private const int HidUnkSection5Size = 0x200; - private const int HidUnkSection6Size = 0x200; - private const int HidUnkSection7Size = 0x200; - private const int HidUnkSection8Size = 0x800; - private const int HidControllerSerialsSize = 0x4000; - private const int HidControllersSize = 0x32000; - private const int HidUnkSection9Size = 0x800; - - private const int HidTouchHeaderSize = 0x28; - private const int HidTouchEntrySize = 0x298; - - private const int HidTouchEntryHeaderSize = 0x10; - private const int HidTouchEntryTouchSize = 0x28; - - private const int HidControllerSize = 0x5000; - private const int HidControllerHeaderSize = 0x28; - private const int HidControllerLayoutsSize = 0x350; - - private const int HidControllersLayoutHeaderSize = 0x20; - private const int HidControllersInputEntrySize = 0x30; - - private const int HidHeaderOffset = 0; - private const int HidTouchScreenOffset = HidHeaderOffset + HidHeaderSize; - private const int HidMouseOffset = HidTouchScreenOffset + HidTouchScreenSize; - private const int HidKeyboardOffset = HidMouseOffset + HidMouseSize; - private const int HidUnkSection1Offset = HidKeyboardOffset + HidKeyboardSize; - private const int HidUnkSection2Offset = HidUnkSection1Offset + HidUnkSection1Size; - private const int HidUnkSection3Offset = HidUnkSection2Offset + HidUnkSection2Size; - private const int HidUnkSection4Offset = HidUnkSection3Offset + HidUnkSection3Size; - private const int HidUnkSection5Offset = HidUnkSection4Offset + HidUnkSection4Size; - private const int HidUnkSection6Offset = HidUnkSection5Offset + HidUnkSection5Size; - private const int HidUnkSection7Offset = HidUnkSection6Offset + HidUnkSection6Size; - private const int HidUnkSection8Offset = HidUnkSection7Offset + HidUnkSection7Size; - private const int HidControllerSerialsOffset = HidUnkSection8Offset + HidUnkSection8Size; - private const int HidControllersOffset = HidControllerSerialsOffset + HidControllerSerialsSize; - private const int HidUnkSection9Offset = HidControllersOffset + HidControllersSize; - - private const int HidEntryCount = 17; - - private Switch Device; - - private long HidPosition; - - public Hid(Switch Device, long HidPosition) - { - this.Device = Device; - this.HidPosition = HidPosition; - - Device.Memory.FillWithZeros(HidPosition, Horizon.HidSize); - - InitializeJoyconPair( - JoyConColor.Body_Neon_Red, - JoyConColor.Buttons_Neon_Red, - JoyConColor.Body_Neon_Blue, - JoyConColor.Buttons_Neon_Blue); - } - - private void InitializeJoyconPair( - JoyConColor LeftColorBody, - JoyConColor LeftColorButtons, - JoyConColor RightColorBody, - JoyConColor RightColorButtons) - { - long BaseControllerOffset = HidPosition + HidControllersOffset + 8 * HidControllerSize; - - HidControllerType Type = HidControllerType.ControllerType_Handheld; - - bool IsHalf = false; - - HidControllerColorDesc SingleColorDesc = - HidControllerColorDesc.ColorDesc_ColorsNonexistent; - - JoyConColor SingleColorBody = JoyConColor.Black; - JoyConColor SingleColorButtons = JoyConColor.Black; - - HidControllerColorDesc SplitColorDesc = 0; - - Device.Memory.WriteInt32(BaseControllerOffset + 0x00, (int)Type); - - Device.Memory.WriteInt32(BaseControllerOffset + 0x04, IsHalf ? 1 : 0); - - Device.Memory.WriteInt32(BaseControllerOffset + 0x08, (int)SingleColorDesc); - Device.Memory.WriteInt32(BaseControllerOffset + 0x0c, (int)SingleColorBody); - Device.Memory.WriteInt32(BaseControllerOffset + 0x10, (int)SingleColorButtons); - Device.Memory.WriteInt32(BaseControllerOffset + 0x14, (int)SplitColorDesc); - - Device.Memory.WriteInt32(BaseControllerOffset + 0x18, (int)LeftColorBody); - Device.Memory.WriteInt32(BaseControllerOffset + 0x1c, (int)LeftColorButtons); - - Device.Memory.WriteInt32(BaseControllerOffset + 0x20, (int)RightColorBody); - Device.Memory.WriteInt32(BaseControllerOffset + 0x24, (int)RightColorButtons); - } - - private HidControllerButtons UpdateStickButtons( - HidJoystickPosition LeftStick, - HidJoystickPosition RightStick) - { - HidControllerButtons Result = 0; - - if (RightStick.DX < 0) - { - Result |= HidControllerButtons.KEY_RSTICK_LEFT; - } - - if (RightStick.DX > 0) - { - Result |= HidControllerButtons.KEY_RSTICK_RIGHT; - } - - if (RightStick.DY < 0) - { - Result |= HidControllerButtons.KEY_RSTICK_DOWN; - } - - if (RightStick.DY > 0) - { - Result |= HidControllerButtons.KEY_RSTICK_UP; - } - - if (LeftStick.DX < 0) - { - Result |= HidControllerButtons.KEY_LSTICK_LEFT; - } - - if (LeftStick.DX > 0) - { - Result |= HidControllerButtons.KEY_LSTICK_RIGHT; - } - - if (LeftStick.DY < 0) - { - Result |= HidControllerButtons.KEY_LSTICK_DOWN; - } - - if (LeftStick.DY > 0) - { - Result |= HidControllerButtons.KEY_LSTICK_UP; - } - - return Result; - } - - public void SetJoyconButton( - HidControllerId ControllerId, - HidControllerLayouts ControllerLayout, - HidControllerButtons Buttons, - HidJoystickPosition LeftStick, - HidJoystickPosition RightStick) - { - Buttons |= UpdateStickButtons(LeftStick, RightStick); - - long ControllerOffset = HidPosition + HidControllersOffset; - - ControllerOffset += (int)ControllerId * HidControllerSize; - - ControllerOffset += 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); - - Device.Memory.WriteInt64(ControllerOffset + 0x28, - (uint)HidControllerConnState.Controller_State_Connected | - (uint)HidControllerConnState.Controller_State_Wired); - } - - public void SetTouchPoints(params HidTouchPoint[] Points) - { - long TouchScreenOffset = HidPosition + HidTouchScreenOffset; - - long LastEntry = Device.Memory.ReadInt64(TouchScreenOffset + 0x10); - - long CurrEntry = (LastEntry + 1) % HidEntryCount; - - long Timestamp = GetTimestamp(); - - Device.Memory.WriteInt64(TouchScreenOffset + 0x00, Timestamp); - 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, Timestamp); - Device.Memory.WriteInt32(TouchEntryOffset + 0x08, Padding); - Device.Memory.WriteInt32(TouchEntryOffset + 0x0c, Index++); - Device.Memory.WriteInt32(TouchEntryOffset + 0x10, Point.X); - Device.Memory.WriteInt32(TouchEntryOffset + 0x14, Point.Y); - 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; - } - } - - private static long GetTimestamp() - { - return PerformanceCounter.ElapsedMilliseconds * 19200; - } - } -} diff --git a/Ryujinx.HLE/Hid/HidControllerButtons.cs b/Ryujinx.HLE/Hid/HidControllerButtons.cs deleted file mode 100644 index f41d17e1..00000000 --- a/Ryujinx.HLE/Hid/HidControllerButtons.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; - -namespace Ryujinx.HLE.Input -{ - [Flags] - public enum HidControllerButtons - { - KEY_A = (1 << 0), - KEY_B = (1 << 1), - KEY_X = (1 << 2), - KEY_Y = (1 << 3), - KEY_LSTICK = (1 << 4), - KEY_RSTICK = (1 << 5), - KEY_L = (1 << 6), - KEY_R = (1 << 7), - KEY_ZL = (1 << 8), - KEY_ZR = (1 << 9), - KEY_PLUS = (1 << 10), - KEY_MINUS = (1 << 11), - KEY_DLEFT = (1 << 12), - KEY_DUP = (1 << 13), - KEY_DRIGHT = (1 << 14), - KEY_DDOWN = (1 << 15), - KEY_LSTICK_LEFT = (1 << 16), - KEY_LSTICK_UP = (1 << 17), - KEY_LSTICK_RIGHT = (1 << 18), - KEY_LSTICK_DOWN = (1 << 19), - KEY_RSTICK_LEFT = (1 << 20), - KEY_RSTICK_UP = (1 << 21), - KEY_RSTICK_RIGHT = (1 << 22), - KEY_RSTICK_DOWN = (1 << 23), - KEY_SL = (1 << 24), - KEY_SR = (1 << 25) - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/Hid/HidControllerColorDesc.cs b/Ryujinx.HLE/Hid/HidControllerColorDesc.cs deleted file mode 100644 index b8cf2a5e..00000000 --- a/Ryujinx.HLE/Hid/HidControllerColorDesc.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Ryujinx.HLE.Input -{ - [Flags] - public enum HidControllerColorDesc - { - ColorDesc_ColorsNonexistent = (1 << 1) - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/Hid/HidControllerConnState.cs b/Ryujinx.HLE/Hid/HidControllerConnState.cs deleted file mode 100644 index 1fc9482a..00000000 --- a/Ryujinx.HLE/Hid/HidControllerConnState.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Ryujinx.HLE.Input -{ - [Flags] - public enum HidControllerConnState - { - Controller_State_Connected = (1 << 0), - Controller_State_Wired = (1 << 1) - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/Hid/HidControllerId.cs b/Ryujinx.HLE/Hid/HidControllerId.cs deleted file mode 100644 index e4a0e26c..00000000 --- a/Ryujinx.HLE/Hid/HidControllerId.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Ryujinx.HLE.Input -{ - public enum HidControllerId - { - CONTROLLER_PLAYER_1 = 0, - CONTROLLER_PLAYER_2 = 1, - CONTROLLER_PLAYER_3 = 2, - CONTROLLER_PLAYER_4 = 3, - CONTROLLER_PLAYER_5 = 4, - CONTROLLER_PLAYER_6 = 5, - CONTROLLER_PLAYER_7 = 6, - CONTROLLER_PLAYER_8 = 7, - CONTROLLER_HANDHELD = 8, - CONTROLLER_UNKNOWN = 9 - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/Hid/HidControllerLayouts.cs b/Ryujinx.HLE/Hid/HidControllerLayouts.cs deleted file mode 100644 index 39fdd3fe..00000000 --- a/Ryujinx.HLE/Hid/HidControllerLayouts.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Ryujinx.HLE.Input -{ - public enum HidControllerLayouts - { - Pro_Controller = 0, - Handheld_Joined = 1, - Joined = 2, - Left = 3, - Right = 4, - Main_No_Analog = 5, - Main = 6 - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/Hid/HidControllerType.cs b/Ryujinx.HLE/Hid/HidControllerType.cs deleted file mode 100644 index ea8ddfd4..00000000 --- a/Ryujinx.HLE/Hid/HidControllerType.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace Ryujinx.HLE.Input -{ - [Flags] - public enum HidControllerType - { - ControllerType_ProController = (1 << 0), - ControllerType_Handheld = (1 << 1), - ControllerType_JoyconPair = (1 << 2), - ControllerType_JoyconLeft = (1 << 3), - ControllerType_JoyconRight = (1 << 4) - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/Hid/HidJoystickPosition.cs b/Ryujinx.HLE/Hid/HidJoystickPosition.cs deleted file mode 100644 index a06ef7b2..00000000 --- a/Ryujinx.HLE/Hid/HidJoystickPosition.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Ryujinx.HLE.Input -{ - public struct HidJoystickPosition - { - public int DX; - public int DY; - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/Hid/HidTouchPoint.cs b/Ryujinx.HLE/Hid/HidTouchPoint.cs deleted file mode 100644 index 25412456..00000000 --- a/Ryujinx.HLE/Hid/HidTouchPoint.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Ryujinx.HLE.Input -{ - public struct HidTouchPoint - { - public int X; - public int Y; - public int DiameterX; - public int DiameterY; - public int Angle; - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/Hid/JoyConColor.cs b/Ryujinx.HLE/Hid/JoyConColor.cs deleted file mode 100644 index 514ec21b..00000000 --- a/Ryujinx.HLE/Hid/JoyConColor.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Ryujinx.HLE.Input -{ - public enum JoyConColor //Thanks to CTCaer - { - Black = 0, - - Body_Grey = 0x828282, - Body_Neon_Blue = 0x0AB9E6, - Body_Neon_Red = 0xFF3C28, - Body_Neon_Yellow = 0xE6FF00, - Body_Neon_Pink = 0xFF3278, - Body_Neon_Green = 0x1EDC00, - Body_Red = 0xE10F00, - - Buttons_Grey = 0x0F0F0F, - Buttons_Neon_Blue = 0x001E1E, - Buttons_Neon_Red = 0x1E0A0A, - Buttons_Neon_Yellow = 0x142800, - Buttons_Neon_Pink = 0x28001E, - Buttons_Neon_Green = 0x002800, - Buttons_Red = 0x280A0A - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/Input/Hid.cs b/Ryujinx.HLE/Input/Hid.cs new file mode 100644 index 00000000..edcfe42d --- /dev/null +++ b/Ryujinx.HLE/Input/Hid.cs @@ -0,0 +1,140 @@ +using Ryujinx.Common; +using Ryujinx.HLE.HOS; + +namespace Ryujinx.HLE.Input +{ + public partial class Hid + { + private Switch Device; + + public HidControllerBase PrimaryController { get; private set; } + + internal long HidPosition; + + public Hid(Switch Device, long HidPosition) + { + this.Device = Device; + this.HidPosition = HidPosition; + + Device.Memory.FillWithZeros(HidPosition, Horizon.HidSize); + } + + public void InitilizePrimaryController(HidControllerType ControllerType) + { + HidControllerId ControllerId = ControllerType == HidControllerType.Handheld ? + HidControllerId.CONTROLLER_HANDHELD : HidControllerId.CONTROLLER_PLAYER_1; + + if (ControllerType == HidControllerType.ProController) + { + PrimaryController = new HidProController(Device); + } + else + { + PrimaryController = new HidNpadController(ControllerType, + Device, + (NpadColor.Body_Neon_Red, NpadColor.Body_Neon_Red), + (NpadColor.Buttons_Neon_Blue, NpadColor.Buttons_Neon_Blue)); + } + + PrimaryController.Connect(ControllerId); + } + + private HidControllerButtons UpdateStickButtons( + HidJoystickPosition LeftStick, + HidJoystickPosition RightStick) + { + HidControllerButtons Result = 0; + + if (RightStick.DX < 0) + { + Result |= HidControllerButtons.RStickLeft; + } + + if (RightStick.DX > 0) + { + Result |= HidControllerButtons.RStickRight; + } + + if (RightStick.DY < 0) + { + Result |= HidControllerButtons.RStickDown; + } + + if (RightStick.DY > 0) + { + Result |= HidControllerButtons.RStickUp; + } + + if (LeftStick.DX < 0) + { + Result |= HidControllerButtons.LStickLeft; + } + + if (LeftStick.DX > 0) + { + Result |= HidControllerButtons.LStickRight; + } + + if (LeftStick.DY < 0) + { + Result |= HidControllerButtons.LStickDown; + } + + if (LeftStick.DY > 0) + { + Result |= HidControllerButtons.LStickUp; + } + + return Result; + } + + public void SetTouchPoints(params HidTouchPoint[] Points) + { + long TouchScreenOffset = HidPosition + HidTouchScreenOffset; + long LastEntry = Device.Memory.ReadInt64(TouchScreenOffset + 0x10); + long CurrEntry = (LastEntry + 1) % HidEntryCount; + long Timestamp = GetTimestamp(); + + Device.Memory.WriteInt64(TouchScreenOffset + 0x00, Timestamp); + 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); + Device.Memory.WriteInt32(TouchEntryOffset + 0x08, Padding); + Device.Memory.WriteInt32(TouchEntryOffset + 0x0c, Index++); + Device.Memory.WriteInt32(TouchEntryOffset + 0x10, Point.X); + Device.Memory.WriteInt32(TouchEntryOffset + 0x14, Point.Y); + 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; + } + } + + internal static long GetTimestamp() + { + return PerformanceCounter.ElapsedMilliseconds * 19200; + } + } +} diff --git a/Ryujinx.HLE/Input/HidBaseController.cs b/Ryujinx.HLE/Input/HidBaseController.cs new file mode 100644 index 00000000..9b9bb7ea --- /dev/null +++ b/Ryujinx.HLE/Input/HidBaseController.cs @@ -0,0 +1,76 @@ +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) + { + this.Device = Device; + + HidControllerType = ControllerType; + } + + public virtual void Connect(HidControllerId ControllerId) + { + this.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; + } + } +} diff --git a/Ryujinx.HLE/Input/HidControllerButtons.cs b/Ryujinx.HLE/Input/HidControllerButtons.cs new file mode 100644 index 00000000..07a3a118 --- /dev/null +++ b/Ryujinx.HLE/Input/HidControllerButtons.cs @@ -0,0 +1,35 @@ +using System; + +namespace Ryujinx.HLE.Input +{ + [Flags] + public enum HidControllerButtons + { + 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 + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/Input/HidControllerColorDesc.cs b/Ryujinx.HLE/Input/HidControllerColorDesc.cs new file mode 100644 index 00000000..b8cf2a5e --- /dev/null +++ b/Ryujinx.HLE/Input/HidControllerColorDesc.cs @@ -0,0 +1,10 @@ +using System; + +namespace Ryujinx.HLE.Input +{ + [Flags] + public enum HidControllerColorDesc + { + ColorDesc_ColorsNonexistent = (1 << 1) + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/Input/HidControllerConnState.cs b/Ryujinx.HLE/Input/HidControllerConnState.cs new file mode 100644 index 00000000..1fc9482a --- /dev/null +++ b/Ryujinx.HLE/Input/HidControllerConnState.cs @@ -0,0 +1,11 @@ +using System; + +namespace Ryujinx.HLE.Input +{ + [Flags] + public enum HidControllerConnState + { + Controller_State_Connected = (1 << 0), + Controller_State_Wired = (1 << 1) + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/Input/HidControllerId.cs b/Ryujinx.HLE/Input/HidControllerId.cs new file mode 100644 index 00000000..e4a0e26c --- /dev/null +++ b/Ryujinx.HLE/Input/HidControllerId.cs @@ -0,0 +1,16 @@ +namespace Ryujinx.HLE.Input +{ + public enum HidControllerId + { + CONTROLLER_PLAYER_1 = 0, + CONTROLLER_PLAYER_2 = 1, + CONTROLLER_PLAYER_3 = 2, + CONTROLLER_PLAYER_4 = 3, + CONTROLLER_PLAYER_5 = 4, + CONTROLLER_PLAYER_6 = 5, + CONTROLLER_PLAYER_7 = 6, + CONTROLLER_PLAYER_8 = 7, + CONTROLLER_HANDHELD = 8, + CONTROLLER_UNKNOWN = 9 + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/Input/HidControllerLayouts.cs b/Ryujinx.HLE/Input/HidControllerLayouts.cs new file mode 100644 index 00000000..39fdd3fe --- /dev/null +++ b/Ryujinx.HLE/Input/HidControllerLayouts.cs @@ -0,0 +1,13 @@ +namespace Ryujinx.HLE.Input +{ + public enum HidControllerLayouts + { + Pro_Controller = 0, + Handheld_Joined = 1, + Joined = 2, + Left = 3, + Right = 4, + Main_No_Analog = 5, + Main = 6 + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/Input/HidControllerType.cs b/Ryujinx.HLE/Input/HidControllerType.cs new file mode 100644 index 00000000..74bca365 --- /dev/null +++ b/Ryujinx.HLE/Input/HidControllerType.cs @@ -0,0 +1,14 @@ +using System; + +namespace Ryujinx.HLE.Input +{ + [Flags] + public enum HidControllerType + { + ProController = 1 << 0, + Handheld = 1 << 1, + NpadPair = 1 << 2, + NpadLeft = 1 << 3, + NpadRight = 1 << 4 + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/Input/HidJoystickPosition.cs b/Ryujinx.HLE/Input/HidJoystickPosition.cs new file mode 100644 index 00000000..a06ef7b2 --- /dev/null +++ b/Ryujinx.HLE/Input/HidJoystickPosition.cs @@ -0,0 +1,8 @@ +namespace Ryujinx.HLE.Input +{ + public struct HidJoystickPosition + { + public int DX; + public int DY; + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/Input/HidNpadController.cs b/Ryujinx.HLE/Input/HidNpadController.cs new file mode 100644 index 00000000..7b3fa64c --- /dev/null +++ b/Ryujinx.HLE/Input/HidNpadController.cs @@ -0,0 +1,86 @@ +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) + { + this.NpadBodyColors = NpadBodyColors; + this.NpadButtonColors = NpadButtonColors; + + CurrentLayout = HidControllerLayouts.Handheld_Joined; + + 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.Handheld_Joined ? HidControllerId.CONTROLLER_HANDHELD : ControllerId); + + HidControllerColorDesc SingleColorDesc = + HidControllerColorDesc.ColorDesc_ColorsNonexistent; + + 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.Controller_State_Connected : 0) | + (CurrentLayout == HidControllerLayouts.Handheld_Joined ? (uint)HidControllerConnState.Controller_State_Wired : 0)); + } + } +} diff --git a/Ryujinx.HLE/Input/HidProController.cs b/Ryujinx.HLE/Input/HidProController.cs new file mode 100644 index 00000000..40c79fed --- /dev/null +++ b/Ryujinx.HLE/Input/HidProController.cs @@ -0,0 +1,44 @@ +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.ColorDesc_ColorsNonexistent; + + 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.Pro_Controller); + + Device.Memory.WriteInt64(ControllerOffset + 0x28, + (Connected ? (uint)HidControllerConnState.Controller_State_Connected : 0) | + (Wired ? (uint)HidControllerConnState.Controller_State_Wired : 0)); + } + } +} diff --git a/Ryujinx.HLE/Input/HidTouchPoint.cs b/Ryujinx.HLE/Input/HidTouchPoint.cs new file mode 100644 index 00000000..25412456 --- /dev/null +++ b/Ryujinx.HLE/Input/HidTouchPoint.cs @@ -0,0 +1,11 @@ +namespace Ryujinx.HLE.Input +{ + public struct HidTouchPoint + { + public int X; + public int Y; + public int DiameterX; + public int DiameterY; + public int Angle; + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/Input/HidValues.cs b/Ryujinx.HLE/Input/HidValues.cs new file mode 100644 index 00000000..62bf0707 --- /dev/null +++ b/Ryujinx.HLE/Input/HidValues.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Text; + +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 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; + } +} diff --git a/Ryujinx.HLE/Input/IHidDevice.cs b/Ryujinx.HLE/Input/IHidDevice.cs new file mode 100644 index 00000000..cc67b01a --- /dev/null +++ b/Ryujinx.HLE/Input/IHidDevice.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ryujinx.HLE.Input +{ + interface IHidDevice + { + long Offset { get; } + bool Connected { get; } + } +} diff --git a/Ryujinx.HLE/Input/NpadColor.cs b/Ryujinx.HLE/Input/NpadColor.cs new file mode 100644 index 00000000..b152b789 --- /dev/null +++ b/Ryujinx.HLE/Input/NpadColor.cs @@ -0,0 +1,23 @@ +namespace Ryujinx.HLE.Input +{ + public enum NpadColor //Thanks to CTCaer + { + Black = 0, + + Body_Grey = 0x828282, + Body_Neon_Blue = 0x0AB9E6, + Body_Neon_Red = 0xFF3C28, + Body_Neon_Yellow = 0xE6FF00, + Body_Neon_Pink = 0xFF3278, + Body_Neon_Green = 0x1EDC00, + Body_Red = 0xE10F00, + + Buttons_Grey = 0x0F0F0F, + Buttons_Neon_Blue = 0x001E1E, + Buttons_Neon_Red = 0x1E0A0A, + Buttons_Neon_Yellow = 0x142800, + Buttons_Neon_Pink = 0x28001E, + Buttons_Neon_Green = 0x002800, + Buttons_Red = 0x280A0A + } +} \ No newline at end of file diff --git a/Ryujinx/Config.cs b/Ryujinx/Config.cs index dcead648..216ed0a5 100644 --- a/Ryujinx/Config.cs +++ b/Ryujinx/Config.cs @@ -1,10 +1,11 @@ using LibHac; using Ryujinx.Common.Logging; using Ryujinx.HLE; +using Ryujinx.HLE.Input; using Ryujinx.UI.Input; using System; -using System.Globalization; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Reflection; @@ -13,8 +14,8 @@ namespace Ryujinx { public static class Config { - public static JoyConKeyboard JoyConKeyboard { get; private set; } - public static JoyConController JoyConController { get; private set; } + public static NpadKeyboard NpadKeyboard { get; private set; } + public static NpadController NpadController { get; private set; } public static void Read(Switch device) { @@ -73,9 +74,13 @@ namespace Ryujinx ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None; - JoyConKeyboard = new JoyConKeyboard( + HidControllerType ControllerType = Enum.Parse(parser.Value("Controller_Type")); + + device.Hid.InitilizePrimaryController(ControllerType); + + NpadKeyboard = new NpadKeyboard( - new JoyConKeyboardLeft + new NpadKeyboardLeft { StickUp = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Up")), StickDown = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Down")), @@ -91,7 +96,7 @@ namespace Ryujinx ButtonZl = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Button_ZL")) }, - new JoyConKeyboardRight + new NpadKeyboardRight { StickUp = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Up")), StickDown = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Down")), @@ -107,14 +112,14 @@ namespace Ryujinx ButtonZr = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_ZR")) }); - JoyConController = new JoyConController( + NpadController = new NpadController( Convert.ToBoolean(parser.Value("GamePad_Enable")), Convert.ToInt32 (parser.Value("GamePad_Index")), (float)Convert.ToDouble (parser.Value("GamePad_Deadzone"), CultureInfo.InvariantCulture), (float)Convert.ToDouble (parser.Value("GamePad_Trigger_Threshold"), CultureInfo.InvariantCulture), - new JoyConControllerLeft + new NpadControllerLeft { Stick = ToId(parser.Value("Controls_Left_JoyConController_Stick")), StickButton = ToId(parser.Value("Controls_Left_JoyConController_Stick_Button")), @@ -127,7 +132,7 @@ namespace Ryujinx ButtonZl = ToId(parser.Value("Controls_Left_JoyConController_Button_ZL")) }, - new JoyConControllerRight + new NpadControllerRight { Stick = ToId(parser.Value("Controls_Right_JoyConController_Stick")), StickButton = ToId(parser.Value("Controls_Right_JoyConController_Stick_Button")), diff --git a/Ryujinx/Ryujinx.conf b/Ryujinx/Ryujinx.conf index 45f545d0..5b646a2a 100644 --- a/Ryujinx/Ryujinx.conf +++ b/Ryujinx/Ryujinx.conf @@ -46,6 +46,9 @@ GamePad_Trigger_Threshold = 0.5 #Whether or not to enable Controller support GamePad_Enable = true +#The primary controller's type. Supported Values: ProController, Handheld, NpadPair, NpadLeft, NpadRight +Controller_Type = Handheld + #https://github.com/opentk/opentk/blob/develop/src/OpenTK/Input/Key.cs Controls_Left_JoyConKeyboard_Stick_Up = 105 Controls_Left_JoyConKeyboard_Stick_Down = 101 diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index a654d150..6acb199c 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -142,25 +142,24 @@ namespace Ryujinx { KeyboardState keyboard = _keyboard.Value; - currentButton = Config.JoyConKeyboard.GetButtons(keyboard); + currentButton = Config.NpadKeyboard.GetButtons(keyboard); - (leftJoystickDx, leftJoystickDy) = Config.JoyConKeyboard.GetLeftStick(keyboard); + (leftJoystickDx, leftJoystickDy) = Config.NpadKeyboard.GetLeftStick(keyboard); - (rightJoystickDx, rightJoystickDy) = Config.JoyConKeyboard.GetRightStick(keyboard); + (rightJoystickDx, rightJoystickDy) = Config.NpadKeyboard.GetRightStick(keyboard); } - - //Controller Input - currentButton |= Config.JoyConController.GetButtons(); + + currentButton |= Config.NpadController.GetButtons(); //Keyboard has priority stick-wise if (leftJoystickDx == 0 && leftJoystickDy == 0) { - (leftJoystickDx, leftJoystickDy) = Config.JoyConController.GetLeftStick(); + (leftJoystickDx, leftJoystickDy) = Config.NpadController.GetLeftStick(); } if (rightJoystickDx == 0 && rightJoystickDy == 0) { - (rightJoystickDx, rightJoystickDy) = Config.JoyConController.GetRightStick(); + (rightJoystickDx, rightJoystickDy) = Config.NpadController.GetRightStick(); } leftJoystick = new HidJoystickPosition @@ -234,19 +233,9 @@ namespace Ryujinx _device.Hid.SetTouchPoints(); } - _device.Hid.SetJoyconButton( - HidControllerId.CONTROLLER_HANDHELD, - HidControllerLayouts.Handheld_Joined, - currentButton, - leftJoystick, - rightJoystick); - - _device.Hid.SetJoyconButton( - HidControllerId.CONTROLLER_HANDHELD, - HidControllerLayouts.Main, - currentButton, - leftJoystick, - rightJoystick); + HidControllerBase controller = _device.Hid.PrimaryController; + + controller.SendInput(currentButton, leftJoystick, rightJoystick); } private new void RenderFrame() diff --git a/Ryujinx/Ui/JoyConController.cs b/Ryujinx/Ui/JoyConController.cs deleted file mode 100644 index 28b631b2..00000000 --- a/Ryujinx/Ui/JoyConController.cs +++ /dev/null @@ -1,216 +0,0 @@ -using OpenTK; -using OpenTK.Input; -using Ryujinx.HLE.Input; -using System; - -namespace Ryujinx.UI.Input -{ - public enum ControllerInputId - { - Invalid, - - LStick, - DPadUp, - DPadDown, - DPadLeft, - DPadRight, - Back, - LShoulder, - - RStick, - A, - B, - X, - Y, - Start, - RShoulder, - - LTrigger, - RTrigger, - - LJoystick, - RJoystick - } - - public struct JoyConControllerLeft - { - public ControllerInputId Stick; - public ControllerInputId StickButton; - public ControllerInputId DPadUp; - public ControllerInputId DPadDown; - public ControllerInputId DPadLeft; - public ControllerInputId DPadRight; - public ControllerInputId ButtonMinus; - public ControllerInputId ButtonL; - public ControllerInputId ButtonZl; - } - - public struct JoyConControllerRight - { - public ControllerInputId Stick; - public ControllerInputId StickButton; - public ControllerInputId ButtonA; - public ControllerInputId ButtonB; - public ControllerInputId ButtonX; - public ControllerInputId ButtonY; - public ControllerInputId ButtonPlus; - public ControllerInputId ButtonR; - public ControllerInputId ButtonZr; - } - - public class JoyConController - { - public bool Enabled { private set; get; } - public int Index { private set; get; } - public float Deadzone { private set; get; } - public float TriggerThreshold { private set; get; } - - public JoyConControllerLeft Left { private set; get; } - public JoyConControllerRight Right { private set; get; } - - public JoyConController( - bool enabled, - int index, - float deadzone, - float triggerThreshold, - JoyConControllerLeft left, - JoyConControllerRight right) - { - Enabled = enabled; - Index = index; - Deadzone = deadzone; - TriggerThreshold = triggerThreshold; - Left = left; - Right = right; - - //Unmapped controllers are problematic, skip them - if (GamePad.GetName(index) == "Unmapped Controller") - { - Enabled = false; - } - } - - public HidControllerButtons GetButtons() - { - if (!Enabled) - { - return 0; - } - - GamePadState gpState = GamePad.GetState(Index); - - HidControllerButtons buttons = 0; - - if (IsPressed(gpState, Left.DPadUp)) buttons |= HidControllerButtons.KEY_DUP; - if (IsPressed(gpState, Left.DPadDown)) buttons |= HidControllerButtons.KEY_DDOWN; - if (IsPressed(gpState, Left.DPadLeft)) buttons |= HidControllerButtons.KEY_DLEFT; - if (IsPressed(gpState, Left.DPadRight)) buttons |= HidControllerButtons.KEY_DRIGHT; - if (IsPressed(gpState, Left.StickButton)) buttons |= HidControllerButtons.KEY_LSTICK; - if (IsPressed(gpState, Left.ButtonMinus)) buttons |= HidControllerButtons.KEY_MINUS; - if (IsPressed(gpState, Left.ButtonL)) buttons |= HidControllerButtons.KEY_L; - if (IsPressed(gpState, Left.ButtonZl)) buttons |= HidControllerButtons.KEY_ZL; - - if (IsPressed(gpState, Right.ButtonA)) buttons |= HidControllerButtons.KEY_A; - if (IsPressed(gpState, Right.ButtonB)) buttons |= HidControllerButtons.KEY_B; - if (IsPressed(gpState, Right.ButtonX)) buttons |= HidControllerButtons.KEY_X; - if (IsPressed(gpState, Right.ButtonY)) buttons |= HidControllerButtons.KEY_Y; - if (IsPressed(gpState, Right.StickButton)) buttons |= HidControllerButtons.KEY_RSTICK; - if (IsPressed(gpState, Right.ButtonPlus)) buttons |= HidControllerButtons.KEY_PLUS; - if (IsPressed(gpState, Right.ButtonR)) buttons |= HidControllerButtons.KEY_R; - if (IsPressed(gpState, Right.ButtonZr)) buttons |= HidControllerButtons.KEY_ZR; - - return buttons; - } - - public (short, short) GetLeftStick() - { - if (!Enabled) - { - return (0, 0); - } - - return GetStick(Left.Stick); - } - - public (short, short) GetRightStick() - { - if (!Enabled) - { - return (0, 0); - } - - return GetStick(Right.Stick); - } - - private (short, short) GetStick(ControllerInputId joystick) - { - GamePadState gpState = GamePad.GetState(Index); - - switch (joystick) - { - case ControllerInputId.LJoystick: - return ApplyDeadzone(gpState.ThumbSticks.Left); - - case ControllerInputId.RJoystick: - return ApplyDeadzone(gpState.ThumbSticks.Right); - - default: - return (0, 0); - } - } - - private (short, short) ApplyDeadzone(Vector2 axis) - { - return (ClampAxis(MathF.Abs(axis.X) > Deadzone ? axis.X : 0f), - ClampAxis(MathF.Abs(axis.Y) > Deadzone ? axis.Y : 0f)); - } - - private static short ClampAxis(float value) - { - if (value <= -short.MaxValue) - { - return -short.MaxValue; - } - else - { - return (short)(value * short.MaxValue); - } - } - - private bool IsPressed(GamePadState gpState, ControllerInputId button) - { - switch (button) - { - case ControllerInputId.A: return gpState.Buttons.A == ButtonState.Pressed; - case ControllerInputId.B: return gpState.Buttons.B == ButtonState.Pressed; - case ControllerInputId.X: return gpState.Buttons.X == ButtonState.Pressed; - case ControllerInputId.Y: return gpState.Buttons.Y == ButtonState.Pressed; - case ControllerInputId.LStick: return gpState.Buttons.LeftStick == ButtonState.Pressed; - case ControllerInputId.RStick: return gpState.Buttons.RightStick == ButtonState.Pressed; - case ControllerInputId.LShoulder: return gpState.Buttons.LeftShoulder == ButtonState.Pressed; - case ControllerInputId.RShoulder: return gpState.Buttons.RightShoulder == ButtonState.Pressed; - case ControllerInputId.DPadUp: return gpState.DPad.Up == ButtonState.Pressed; - case ControllerInputId.DPadDown: return gpState.DPad.Down == ButtonState.Pressed; - case ControllerInputId.DPadLeft: return gpState.DPad.Left == ButtonState.Pressed; - case ControllerInputId.DPadRight: return gpState.DPad.Right == ButtonState.Pressed; - case ControllerInputId.Start: return gpState.Buttons.Start == ButtonState.Pressed; - case ControllerInputId.Back: return gpState.Buttons.Back == ButtonState.Pressed; - - case ControllerInputId.LTrigger: return gpState.Triggers.Left >= TriggerThreshold; - case ControllerInputId.RTrigger: return gpState.Triggers.Right >= TriggerThreshold; - - //Using thumbsticks as buttons is not common, but it would be nice not to ignore them - case ControllerInputId.LJoystick: - return gpState.ThumbSticks.Left.X >= Deadzone || - gpState.ThumbSticks.Left.Y >= Deadzone; - - case ControllerInputId.RJoystick: - return gpState.ThumbSticks.Right.X >= Deadzone || - gpState.ThumbSticks.Right.Y >= Deadzone; - - default: - return false; - } - } - } -} diff --git a/Ryujinx/Ui/JoyConKeyboard.cs b/Ryujinx/Ui/JoyConKeyboard.cs deleted file mode 100644 index fd399fe8..00000000 --- a/Ryujinx/Ui/JoyConKeyboard.cs +++ /dev/null @@ -1,102 +0,0 @@ -using OpenTK.Input; -using Ryujinx.HLE.Input; - -namespace Ryujinx.UI.Input -{ - public struct JoyConKeyboardLeft - { - public int StickUp; - public int StickDown; - public int StickLeft; - public int StickRight; - public int StickButton; - public int DPadUp; - public int DPadDown; - public int DPadLeft; - public int DPadRight; - public int ButtonMinus; - public int ButtonL; - public int ButtonZl; - } - - public struct JoyConKeyboardRight - { - public int StickUp; - public int StickDown; - public int StickLeft; - public int StickRight; - public int StickButton; - public int ButtonA; - public int ButtonB; - public int ButtonX; - public int ButtonY; - public int ButtonPlus; - public int ButtonR; - public int ButtonZr; - } - - public class JoyConKeyboard - { - public JoyConKeyboardLeft Left; - public JoyConKeyboardRight Right; - - public JoyConKeyboard( - JoyConKeyboardLeft left, - JoyConKeyboardRight right) - { - Left = left; - Right = right; - } - - public HidControllerButtons GetButtons(KeyboardState keyboard) - { - HidControllerButtons buttons = 0; - - if (keyboard[(Key)Left.StickButton]) buttons |= HidControllerButtons.KEY_LSTICK; - if (keyboard[(Key)Left.DPadUp]) buttons |= HidControllerButtons.KEY_DUP; - if (keyboard[(Key)Left.DPadDown]) buttons |= HidControllerButtons.KEY_DDOWN; - if (keyboard[(Key)Left.DPadLeft]) buttons |= HidControllerButtons.KEY_DLEFT; - if (keyboard[(Key)Left.DPadRight]) buttons |= HidControllerButtons.KEY_DRIGHT; - if (keyboard[(Key)Left.ButtonMinus]) buttons |= HidControllerButtons.KEY_MINUS; - if (keyboard[(Key)Left.ButtonL]) buttons |= HidControllerButtons.KEY_L; - if (keyboard[(Key)Left.ButtonZl]) buttons |= HidControllerButtons.KEY_ZL; - - if (keyboard[(Key)Right.StickButton]) buttons |= HidControllerButtons.KEY_RSTICK; - if (keyboard[(Key)Right.ButtonA]) buttons |= HidControllerButtons.KEY_A; - if (keyboard[(Key)Right.ButtonB]) buttons |= HidControllerButtons.KEY_B; - if (keyboard[(Key)Right.ButtonX]) buttons |= HidControllerButtons.KEY_X; - if (keyboard[(Key)Right.ButtonY]) buttons |= HidControllerButtons.KEY_Y; - if (keyboard[(Key)Right.ButtonPlus]) buttons |= HidControllerButtons.KEY_PLUS; - if (keyboard[(Key)Right.ButtonR]) buttons |= HidControllerButtons.KEY_R; - if (keyboard[(Key)Right.ButtonZr]) buttons |= HidControllerButtons.KEY_ZR; - - return buttons; - } - - public (short, short) GetLeftStick(KeyboardState keyboard) - { - short dx = 0; - short dy = 0; - - if (keyboard[(Key)Left.StickUp]) dy = short.MaxValue; - if (keyboard[(Key)Left.StickDown]) dy = -short.MaxValue; - if (keyboard[(Key)Left.StickLeft]) dx = -short.MaxValue; - if (keyboard[(Key)Left.StickRight]) dx = short.MaxValue; - - return (dx, dy); - } - - public (short, short) GetRightStick(KeyboardState keyboard) - { - short dx = 0; - short dy = 0; - - if (keyboard[(Key)Right.StickUp]) dy = short.MaxValue; - if (keyboard[(Key)Right.StickDown]) dy = -short.MaxValue; - if (keyboard[(Key)Right.StickLeft]) dx = -short.MaxValue; - if (keyboard[(Key)Right.StickRight]) dx = short.MaxValue; - - return (dx, dy); - } - } -} diff --git a/Ryujinx/Ui/NpadController.cs b/Ryujinx/Ui/NpadController.cs new file mode 100644 index 00000000..58d2d46a --- /dev/null +++ b/Ryujinx/Ui/NpadController.cs @@ -0,0 +1,216 @@ +using OpenTK; +using OpenTK.Input; +using Ryujinx.HLE.Input; +using System; + +namespace Ryujinx.UI.Input +{ + public enum ControllerInputId + { + Invalid, + + LStick, + DPadUp, + DPadDown, + DPadLeft, + DPadRight, + Back, + LShoulder, + + RStick, + A, + B, + X, + Y, + Start, + RShoulder, + + LTrigger, + RTrigger, + + LJoystick, + RJoystick + } + + public struct NpadControllerLeft + { + public ControllerInputId Stick; + public ControllerInputId StickButton; + public ControllerInputId DPadUp; + public ControllerInputId DPadDown; + public ControllerInputId DPadLeft; + public ControllerInputId DPadRight; + public ControllerInputId ButtonMinus; + public ControllerInputId ButtonL; + public ControllerInputId ButtonZl; + } + + public struct NpadControllerRight + { + public ControllerInputId Stick; + public ControllerInputId StickButton; + public ControllerInputId ButtonA; + public ControllerInputId ButtonB; + public ControllerInputId ButtonX; + public ControllerInputId ButtonY; + public ControllerInputId ButtonPlus; + public ControllerInputId ButtonR; + public ControllerInputId ButtonZr; + } + + public class NpadController + { + public bool Enabled { private set; get; } + public int Index { private set; get; } + public float Deadzone { private set; get; } + public float TriggerThreshold { private set; get; } + + public NpadControllerLeft Left { private set; get; } + public NpadControllerRight Right { private set; get; } + + public NpadController( + bool enabled, + int index, + float deadzone, + float triggerThreshold, + NpadControllerLeft left, + NpadControllerRight right) + { + Enabled = enabled; + Index = index; + Deadzone = deadzone; + TriggerThreshold = triggerThreshold; + Left = left; + Right = right; + + //Unmapped controllers are problematic, skip them + if (GamePad.GetName(index) == "Unmapped Controller") + { + Enabled = false; + } + } + + public HidControllerButtons GetButtons() + { + if (!Enabled) + { + return 0; + } + + GamePadState gpState = GamePad.GetState(Index); + + HidControllerButtons buttons = 0; + + if (IsPressed(gpState, Left.DPadUp)) buttons |= HidControllerButtons.DpadUp; + if (IsPressed(gpState, Left.DPadDown)) buttons |= HidControllerButtons.DpadDown; + if (IsPressed(gpState, Left.DPadLeft)) buttons |= HidControllerButtons.DpadLeft; + if (IsPressed(gpState, Left.DPadRight)) buttons |= HidControllerButtons.DPadRight; + if (IsPressed(gpState, Left.StickButton)) buttons |= HidControllerButtons.StickLeft; + if (IsPressed(gpState, Left.ButtonMinus)) buttons |= HidControllerButtons.Minus; + if (IsPressed(gpState, Left.ButtonL)) buttons |= HidControllerButtons.L; + if (IsPressed(gpState, Left.ButtonZl)) buttons |= HidControllerButtons.Zl; + + if (IsPressed(gpState, Right.ButtonA)) buttons |= HidControllerButtons.A; + if (IsPressed(gpState, Right.ButtonB)) buttons |= HidControllerButtons.B; + if (IsPressed(gpState, Right.ButtonX)) buttons |= HidControllerButtons.X; + if (IsPressed(gpState, Right.ButtonY)) buttons |= HidControllerButtons.Y; + if (IsPressed(gpState, Right.StickButton)) buttons |= HidControllerButtons.StickRight; + if (IsPressed(gpState, Right.ButtonPlus)) buttons |= HidControllerButtons.Plus; + if (IsPressed(gpState, Right.ButtonR)) buttons |= HidControllerButtons.R; + if (IsPressed(gpState, Right.ButtonZr)) buttons |= HidControllerButtons.Zr; + + return buttons; + } + + public (short, short) GetLeftStick() + { + if (!Enabled) + { + return (0, 0); + } + + return GetStick(Left.Stick); + } + + public (short, short) GetRightStick() + { + if (!Enabled) + { + return (0, 0); + } + + return GetStick(Right.Stick); + } + + private (short, short) GetStick(ControllerInputId joystick) + { + GamePadState gpState = GamePad.GetState(Index); + + switch (joystick) + { + case ControllerInputId.LJoystick: + return ApplyDeadzone(gpState.ThumbSticks.Left); + + case ControllerInputId.RJoystick: + return ApplyDeadzone(gpState.ThumbSticks.Right); + + default: + return (0, 0); + } + } + + private (short, short) ApplyDeadzone(Vector2 axis) + { + return (ClampAxis(MathF.Abs(axis.X) > Deadzone ? axis.X : 0f), + ClampAxis(MathF.Abs(axis.Y) > Deadzone ? axis.Y : 0f)); + } + + private static short ClampAxis(float value) + { + if (value <= -short.MaxValue) + { + return -short.MaxValue; + } + else + { + return (short)(value * short.MaxValue); + } + } + + private bool IsPressed(GamePadState gpState, ControllerInputId button) + { + switch (button) + { + case ControllerInputId.A: return gpState.Buttons.A == ButtonState.Pressed; + case ControllerInputId.B: return gpState.Buttons.B == ButtonState.Pressed; + case ControllerInputId.X: return gpState.Buttons.X == ButtonState.Pressed; + case ControllerInputId.Y: return gpState.Buttons.Y == ButtonState.Pressed; + case ControllerInputId.LStick: return gpState.Buttons.LeftStick == ButtonState.Pressed; + case ControllerInputId.RStick: return gpState.Buttons.RightStick == ButtonState.Pressed; + case ControllerInputId.LShoulder: return gpState.Buttons.LeftShoulder == ButtonState.Pressed; + case ControllerInputId.RShoulder: return gpState.Buttons.RightShoulder == ButtonState.Pressed; + case ControllerInputId.DPadUp: return gpState.DPad.Up == ButtonState.Pressed; + case ControllerInputId.DPadDown: return gpState.DPad.Down == ButtonState.Pressed; + case ControllerInputId.DPadLeft: return gpState.DPad.Left == ButtonState.Pressed; + case ControllerInputId.DPadRight: return gpState.DPad.Right == ButtonState.Pressed; + case ControllerInputId.Start: return gpState.Buttons.Start == ButtonState.Pressed; + case ControllerInputId.Back: return gpState.Buttons.Back == ButtonState.Pressed; + + case ControllerInputId.LTrigger: return gpState.Triggers.Left >= TriggerThreshold; + case ControllerInputId.RTrigger: return gpState.Triggers.Right >= TriggerThreshold; + + //Using thumbsticks as buttons is not common, but it would be nice not to ignore them + case ControllerInputId.LJoystick: + return gpState.ThumbSticks.Left.X >= Deadzone || + gpState.ThumbSticks.Left.Y >= Deadzone; + + case ControllerInputId.RJoystick: + return gpState.ThumbSticks.Right.X >= Deadzone || + gpState.ThumbSticks.Right.Y >= Deadzone; + + default: + return false; + } + } + } +} diff --git a/Ryujinx/Ui/NpadKeyboard.cs b/Ryujinx/Ui/NpadKeyboard.cs new file mode 100644 index 00000000..704c61ab --- /dev/null +++ b/Ryujinx/Ui/NpadKeyboard.cs @@ -0,0 +1,102 @@ +using OpenTK.Input; +using Ryujinx.HLE.Input; + +namespace Ryujinx.UI.Input +{ + public struct NpadKeyboardLeft + { + public int StickUp; + public int StickDown; + public int StickLeft; + public int StickRight; + public int StickButton; + public int DPadUp; + public int DPadDown; + public int DPadLeft; + public int DPadRight; + public int ButtonMinus; + public int ButtonL; + public int ButtonZl; + } + + public struct NpadKeyboardRight + { + public int StickUp; + public int StickDown; + public int StickLeft; + public int StickRight; + public int StickButton; + public int ButtonA; + public int ButtonB; + public int ButtonX; + public int ButtonY; + public int ButtonPlus; + public int ButtonR; + public int ButtonZr; + } + + public class NpadKeyboard + { + public NpadKeyboardLeft Left; + public NpadKeyboardRight Right; + + public NpadKeyboard( + NpadKeyboardLeft left, + NpadKeyboardRight right) + { + Left = left; + Right = right; + } + + public HidControllerButtons GetButtons(KeyboardState keyboard) + { + HidControllerButtons buttons = 0; + + if (keyboard[(Key)Left.StickButton]) buttons |= HidControllerButtons.StickLeft; + if (keyboard[(Key)Left.DPadUp]) buttons |= HidControllerButtons.DpadUp; + if (keyboard[(Key)Left.DPadDown]) buttons |= HidControllerButtons.DpadDown; + if (keyboard[(Key)Left.DPadLeft]) buttons |= HidControllerButtons.DpadLeft; + if (keyboard[(Key)Left.DPadRight]) buttons |= HidControllerButtons.DPadRight; + if (keyboard[(Key)Left.ButtonMinus]) buttons |= HidControllerButtons.Minus; + if (keyboard[(Key)Left.ButtonL]) buttons |= HidControllerButtons.L; + if (keyboard[(Key)Left.ButtonZl]) buttons |= HidControllerButtons.Zl; + + if (keyboard[(Key)Right.StickButton]) buttons |= HidControllerButtons.StickRight; + if (keyboard[(Key)Right.ButtonA]) buttons |= HidControllerButtons.A; + if (keyboard[(Key)Right.ButtonB]) buttons |= HidControllerButtons.B; + if (keyboard[(Key)Right.ButtonX]) buttons |= HidControllerButtons.X; + if (keyboard[(Key)Right.ButtonY]) buttons |= HidControllerButtons.Y; + if (keyboard[(Key)Right.ButtonPlus]) buttons |= HidControllerButtons.Plus; + if (keyboard[(Key)Right.ButtonR]) buttons |= HidControllerButtons.R; + if (keyboard[(Key)Right.ButtonZr]) buttons |= HidControllerButtons.Zr; + + return buttons; + } + + public (short, short) GetLeftStick(KeyboardState keyboard) + { + short dx = 0; + short dy = 0; + + if (keyboard[(Key)Left.StickUp]) dy = short.MaxValue; + if (keyboard[(Key)Left.StickDown]) dy = -short.MaxValue; + if (keyboard[(Key)Left.StickLeft]) dx = -short.MaxValue; + if (keyboard[(Key)Left.StickRight]) dx = short.MaxValue; + + return (dx, dy); + } + + public (short, short) GetRightStick(KeyboardState keyboard) + { + short dx = 0; + short dy = 0; + + if (keyboard[(Key)Right.StickUp]) dy = short.MaxValue; + if (keyboard[(Key)Right.StickDown]) dy = -short.MaxValue; + if (keyboard[(Key)Right.StickLeft]) dx = -short.MaxValue; + if (keyboard[(Key)Right.StickRight]) dx = short.MaxValue; + + return (dx, dy); + } + } +} -- cgit v1.2.3