diff --git a/Ryujinx.Core/Config.cs b/Ryujinx.Core/Config.cs index 7db49319c..c9a76de34 100644 --- a/Ryujinx.Core/Config.cs +++ b/Ryujinx.Core/Config.cs @@ -1,4 +1,5 @@ -using System; +using Ryujinx.Core.Input; +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/Ryujinx.Core/Hid.cs b/Ryujinx.Core/Hid.cs deleted file mode 100644 index bd83e92d4..000000000 --- a/Ryujinx.Core/Hid.cs +++ /dev/null @@ -1,225 +0,0 @@ -using Ryujinx.Core.OsHle; -using System; -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - public class Hid - { - /* - Thanks to: - 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 - - struct HidSharedMemory - { - header[0x400]; - touchscreen[0x3000]; - mouse[0x400]; - keyboard[0x400]; - unkSection1[0x400]; - unkSection2[0x400]; - unkSection3[0x400]; - unkSection4[0x400]; - unkSection5[0x200]; - unkSection6[0x200]; - unkSection7[0x200]; - unkSection8[0x800]; - controllerSerials[0x4000]; - controllers[0x5000 * 10]; - unkSection9[0x4600]; - } - */ - - private const int Hid_Num_Entries = 17; - private Switch Ns; - private long SharedMemOffset; - - public Hid(Switch Ns) - { - this.Ns = Ns; - } - - public void Init(long HidOffset) - { - unsafe - { - if (HidOffset == 0 || HidOffset + Horizon.HidSize > uint.MaxValue) - { - return; - } - - SharedMemOffset = HidOffset; - - uint InnerOffset = (uint)Marshal.SizeOf(typeof(HidSharedMemHeader)); - - IntPtr HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidTouchScreen TouchScreen = new HidTouchScreen(); - TouchScreen.Header.TimestampTicks = (ulong)Environment.TickCount; - TouchScreen.Header.NumEntries = (ulong)Hid_Num_Entries; - TouchScreen.Header.LatestEntry = 0; - TouchScreen.Header.MaxEntryIndex = (ulong)Hid_Num_Entries - 1; - TouchScreen.Header.Timestamp = (ulong)Environment.TickCount; - - Marshal.StructureToPtr(TouchScreen, HidPtr, false); - - InnerOffset += (uint)Marshal.SizeOf(typeof(HidTouchScreen)); - HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidMouse Mouse = new HidMouse(); - Mouse.Header.TimestampTicks = (ulong)Environment.TickCount; - Mouse.Header.NumEntries = (ulong)Hid_Num_Entries; - Mouse.Header.LatestEntry = 0; - Mouse.Header.MaxEntryIndex = (ulong)Hid_Num_Entries - 1; - - //TODO: Write this structure when the input is implemented - //Marshal.StructureToPtr(Mouse, HidPtr, false); - - InnerOffset += (uint)Marshal.SizeOf(typeof(HidMouse)); - HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidKeyboard Keyboard = new HidKeyboard(); - Keyboard.Header.TimestampTicks = (ulong)Environment.TickCount; - Keyboard.Header.NumEntries = (ulong)Hid_Num_Entries; - Keyboard.Header.LatestEntry = 0; - Keyboard.Header.MaxEntryIndex = (ulong)Hid_Num_Entries - 1; - - //TODO: Write this structure when the input is implemented - //Marshal.StructureToPtr(Keyboard, HidPtr, false); - - InnerOffset += (uint)Marshal.SizeOf(typeof(HidKeyboard)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection1)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection2)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection3)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection4)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection5)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection6)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection7)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection8)) + - (uint)Marshal.SizeOf(typeof(HidControllerSerials)); - - //Increase the loop to initialize more controller. - for (int i = 8; i < Enum.GetNames(typeof(HidControllerID)).Length - 1; i++) - { - HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset + (uint)(Marshal.SizeOf(typeof(HidController)) * i)); - - HidController Controller = new HidController(); - Controller.Header.Type = (uint)(HidControllerType.ControllerType_Handheld | HidControllerType.ControllerType_JoyconPair); - Controller.Header.IsHalf = 0; - Controller.Header.SingleColorsDescriptor = (uint)(HidControllerColorDescription.ColorDesc_ColorsNonexistent); - Controller.Header.SingleColorBody = 0; - Controller.Header.SingleColorButtons = 0; - Controller.Header.SplitColorsDescriptor = 0; - Controller.Header.LeftColorBody = (uint)JoyConColor.Body_Neon_Red; - Controller.Header.LeftColorButtons = (uint)JoyConColor.Buttons_Neon_Red; - Controller.Header.RightColorBody = (uint)JoyConColor.Body_Neon_Blue; - Controller.Header.RightColorButtons = (uint)JoyConColor.Buttons_Neon_Blue; - - Controller.Layouts = new HidControllerLayout[Enum.GetNames(typeof(HidControllerLayouts)).Length]; - Controller.Layouts[(int)HidControllerLayouts.Main] = new HidControllerLayout(); - Controller.Layouts[(int)HidControllerLayouts.Main].Header.LatestEntry = (ulong)Hid_Num_Entries; - - Marshal.StructureToPtr(Controller, HidPtr, false); - } - - Logging.Info("HID Initialized!"); - } - } - - public void SendControllerButtons(HidControllerID ControllerId, - HidControllerLayouts Layout, - HidControllerKeys Buttons, - JoystickPosition LeftJoystick, - JoystickPosition RightJoystick) - { - uint InnerOffset = (uint)Marshal.SizeOf(typeof(HidSharedMemHeader)) + - (uint)Marshal.SizeOf(typeof(HidTouchScreen)) + - (uint)Marshal.SizeOf(typeof(HidMouse)) + - (uint)Marshal.SizeOf(typeof(HidKeyboard)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection1)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection2)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection3)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection4)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection5)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection6)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection7)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection8)) + - (uint)Marshal.SizeOf(typeof(HidControllerSerials)) + - ((uint)(Marshal.SizeOf(typeof(HidController)) * (int)ControllerId)) + - (uint)Marshal.SizeOf(typeof(HidControllerHeader)) + - (uint)Layout * (uint)Marshal.SizeOf(typeof(HidControllerLayout)); - - IntPtr HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidControllerLayoutHeader OldControllerHeaderLayout = (HidControllerLayoutHeader)Marshal.PtrToStructure(HidPtr, typeof(HidControllerLayoutHeader)); - - HidControllerLayoutHeader ControllerLayoutHeader = new HidControllerLayoutHeader - { - TimestampTicks = (ulong)Environment.TickCount, - NumEntries = (ulong)Hid_Num_Entries, - MaxEntryIndex = (ulong)Hid_Num_Entries - 1, - LatestEntry = (OldControllerHeaderLayout.LatestEntry < (ulong)Hid_Num_Entries ? OldControllerHeaderLayout.LatestEntry + 1 : 0) - }; - - Marshal.StructureToPtr(ControllerLayoutHeader, HidPtr, false); - - InnerOffset += (uint)Marshal.SizeOf(typeof(HidControllerLayoutHeader)) + (uint)((uint)(ControllerLayoutHeader.LatestEntry) * Marshal.SizeOf(typeof(HidControllerInputEntry))); - HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidControllerInputEntry ControllerInputEntry = new HidControllerInputEntry - { - Timestamp = (ulong)Environment.TickCount, - Timestamp_2 = (ulong)Environment.TickCount, - Buttons = (ulong)Buttons, - Joysticks = new JoystickPosition[(int)HidControllerJoystick.Joystick_Num_Sticks] - }; - ControllerInputEntry.Joysticks[(int)HidControllerJoystick.Joystick_Left] = LeftJoystick; - ControllerInputEntry.Joysticks[(int)HidControllerJoystick.Joystick_Right] = RightJoystick; - ControllerInputEntry.ConnectionState = (ulong)(HidControllerConnectionState.Controller_State_Connected | HidControllerConnectionState.Controller_State_Wired); - - Marshal.StructureToPtr(ControllerInputEntry, HidPtr, false); - } - - public void SendTouchPoint(HidTouchScreenEntryTouch TouchPoint) - { - uint InnerOffset = (uint)Marshal.SizeOf(typeof(HidSharedMemHeader)); - - IntPtr HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidTouchScreenHeader OldTouchScreenHeader = (HidTouchScreenHeader)Marshal.PtrToStructure(HidPtr,typeof(HidTouchScreenHeader)); - - HidTouchScreenHeader TouchScreenHeader = new HidTouchScreenHeader() - { - TimestampTicks = (ulong)Environment.TickCount, - NumEntries = (ulong)Hid_Num_Entries, - MaxEntryIndex = (ulong)Hid_Num_Entries - 1, - Timestamp = (ulong)Environment.TickCount, - LatestEntry = OldTouchScreenHeader.LatestEntry < Hid_Num_Entries-1 ? OldTouchScreenHeader.LatestEntry + 1 : 0 - }; - - Marshal.StructureToPtr(TouchScreenHeader, HidPtr, false); - - InnerOffset += (uint)Marshal.SizeOf(typeof(HidTouchScreenHeader)) - + (uint)((uint)(OldTouchScreenHeader.LatestEntry) * Marshal.SizeOf(typeof(HidTouchScreenEntry))); - HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidTouchScreenEntry hidTouchScreenEntry = new HidTouchScreenEntry() - { - Header = new HidTouchScreenEntryHeader() - { - Timestamp = (ulong)Environment.TickCount, - NumTouches = 1 - }, - Touches = new HidTouchScreenEntryTouch[16] - }; - - //Only supports single touch - hidTouchScreenEntry.Touches[0] = TouchPoint; - - Marshal.StructureToPtr(hidTouchScreenEntry, HidPtr, false); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/Hid.cs b/Ryujinx.Core/Hid/Hid.cs new file mode 100644 index 000000000..4dbac40cb --- /dev/null +++ b/Ryujinx.Core/Hid/Hid.cs @@ -0,0 +1,235 @@ +using ChocolArm64.Memory; +using System.Diagnostics; + +namespace Ryujinx.Core.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 long SharedMemOffset; + + private Switch Ns; + + public Hid(Switch Ns) + { + this.Ns = Ns; + } + + public void Init(long HidOffset) + { + SharedMemOffset = HidOffset; + + InitializeJoyconPair( + JoyConColor.Body_Neon_Red, + JoyConColor.Buttons_Neon_Red, + JoyConColor.Body_Neon_Blue, + JoyConColor.Buttons_Neon_Blue); + } + + public void InitializeJoyconPair( + JoyConColor LeftColorBody, + JoyConColor LeftColorButtons, + JoyConColor RightColorBody, + JoyConColor RightColorButtons) + { + long BaseControllerOffset = HidControllersOffset + 8 * HidControllerSize; + + HidControllerType Type = + HidControllerType.ControllerType_Handheld | + HidControllerType.ControllerType_JoyconPair; + + bool IsHalf = false; + + HidControllerColorDesc SingleColorDesc = + HidControllerColorDesc.ColorDesc_ColorsNonexistent; + + JoyConColor SingleColorBody = JoyConColor.Black; + JoyConColor SingleColorButtons = JoyConColor.Black; + + HidControllerColorDesc SplitColorDesc = 0; + + WriteInt32(BaseControllerOffset + 0x0, (int)Type); + + WriteInt32(BaseControllerOffset + 0x4, IsHalf ? 1 : 0); + + WriteInt32(BaseControllerOffset + 0x8, (int)SingleColorDesc); + WriteInt32(BaseControllerOffset + 0xc, (int)SingleColorBody); + WriteInt32(BaseControllerOffset + 0x10, (int)SingleColorButtons); + WriteInt32(BaseControllerOffset + 0x14, (int)SplitColorDesc); + + WriteInt32(BaseControllerOffset + 0x18, (int)LeftColorBody); + WriteInt32(BaseControllerOffset + 0x1c, (int)LeftColorButtons); + + WriteInt32(BaseControllerOffset + 0x20, (int)RightColorBody); + WriteInt32(BaseControllerOffset + 0x24, (int)RightColorButtons); + } + + public void SetJoyconButton( + HidControllerId ControllerId, + HidControllerLayouts ControllerLayout, + HidControllerButtons Buttons, + HidJoystickPosition LeftStick, + HidJoystickPosition RightStick) + { + long ControllerOffset = HidControllersOffset + (int)ControllerId * HidControllerSize; + + ControllerOffset += HidControllerHeaderSize; + + ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize; + + long LastEntry = ReadInt64(ControllerOffset + 0x10); + + long CurrEntry = (LastEntry + 1) % HidEntryCount; + + long Timestamp = Stopwatch.GetTimestamp(); + + WriteInt64(ControllerOffset + 0x0, Timestamp); + WriteInt64(ControllerOffset + 0x8, HidEntryCount); + WriteInt64(ControllerOffset + 0x10, CurrEntry); + WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1); + + ControllerOffset += HidControllersLayoutHeaderSize; + + ControllerOffset += CurrEntry * HidControllersInputEntrySize; + + WriteInt64(ControllerOffset + 0x0, Timestamp); + WriteInt64(ControllerOffset + 0x8, Timestamp); + + WriteInt64(ControllerOffset + 0x10, (uint)Buttons); + + WriteInt32(ControllerOffset + 0x18, LeftStick.DX); + WriteInt32(ControllerOffset + 0x1c, LeftStick.DY); + + WriteInt64(ControllerOffset + 0x20, RightStick.DX); + WriteInt64(ControllerOffset + 0x24, RightStick.DY); + + WriteInt64(ControllerOffset + 0x28, + (uint)HidControllerConnState.Controller_State_Connected | + (uint)HidControllerConnState.Controller_State_Wired); + } + + public void SetTouchPoints(params HidTouchPoint[] Points) + { + long LastEntry = ReadInt64(HidTouchScreenOffset + 0x10); + + long CurrEntry = (LastEntry + 1) % HidEntryCount; + + long Timestamp = Stopwatch.GetTimestamp(); + + WriteInt64(HidTouchScreenOffset + 0x0, Timestamp); + WriteInt64(HidTouchScreenOffset + 0x8, HidEntryCount); + WriteInt64(HidTouchScreenOffset + 0x10, CurrEntry); + WriteInt64(HidTouchScreenOffset + 0x18, HidEntryCount - 1); + WriteInt64(HidTouchScreenOffset + 0x20, Timestamp); + + long TouchEntryOffset = HidTouchScreenOffset + HidTouchHeaderSize; + + TouchEntryOffset += CurrEntry * HidTouchEntrySize; + + WriteInt64(TouchEntryOffset + 0x0, Timestamp); + WriteInt64(TouchEntryOffset + 0x8, Points.Length); + + TouchEntryOffset += HidTouchEntryHeaderSize; + + const int Padding = 0; + + int Index = 0; + + foreach (HidTouchPoint Point in Points) + { + WriteInt64(TouchEntryOffset + 0x0, Timestamp); + WriteInt32(TouchEntryOffset + 0x8, Padding); + WriteInt32(TouchEntryOffset + 0xc, Index++); + WriteInt32(TouchEntryOffset + 0x10, Point.X); + WriteInt32(TouchEntryOffset + 0x14, Point.Y); + WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX); + WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY); + WriteInt32(TouchEntryOffset + 0x20, Point.Angle); + WriteInt32(TouchEntryOffset + 0x24, Padding); + + TouchEntryOffset += HidTouchEntryTouchSize; + } + } + + private unsafe long ReadInt64(long Position) + { + Position += SharedMemOffset; + + if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return 0; + + return *((long*)((byte*)Ns.Ram + Position)); + } + + private unsafe void WriteInt32(long Position, int Value) + { + Position += SharedMemOffset; + + if ((ulong)Position + 4 > AMemoryMgr.AddrSize) return; + + *((int*)((byte*)Ns.Ram + Position)) = Value; + } + + private unsafe void WriteInt64(long Position, long Value) + { + Position += SharedMemOffset; + + if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return; + + *((long*)((byte*)Ns.Ram + Position)) = Value; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidController.cs b/Ryujinx.Core/Hid/HidController.cs deleted file mode 100644 index 641bc5569..000000000 --- a/Ryujinx.Core/Hid/HidController.cs +++ /dev/null @@ -1,188 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - [Flags] - public enum HidControllerKeys - { - 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), - - // Pseudo-key for at least one finger on the touch screen - KEY_TOUCH = (1 << 26), - - // Buttons by orientation (for single Joy-Con), also works with Joy-Con pairs, Pro Controller - KEY_JOYCON_RIGHT = (1 << 0), - KEY_JOYCON_DOWN = (1 << 1), - KEY_JOYCON_UP = (1 << 2), - KEY_JOYCON_LEFT = (1 << 3), - - // Generic catch-all directions, also works for single Joy-Con - KEY_UP = KEY_DUP | KEY_LSTICK_UP | KEY_RSTICK_UP, - KEY_DOWN = KEY_DDOWN | KEY_LSTICK_DOWN | KEY_RSTICK_DOWN, - KEY_LEFT = KEY_DLEFT | KEY_LSTICK_LEFT | KEY_RSTICK_LEFT, - KEY_RIGHT = KEY_DRIGHT | KEY_LSTICK_RIGHT | KEY_RSTICK_RIGHT, - } - - 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 - } - - public enum HidControllerJoystick - { - Joystick_Left = 0, - Joystick_Right = 1, - Joystick_Num_Sticks = 2 - } - - public enum HidControllerLayouts - { - Pro_Controller, - Handheld_Joined, - Joined, - Left, - Right, - Main_No_Analog, - Main - } - - [Flags] - public enum HidControllerConnectionState - { - Controller_State_Connected = (1 << 0), - Controller_State_Wired = (1 << 1) - } - - [Flags] - public enum HidControllerType - { - ControllerType_ProController = (1 << 0), - ControllerType_Handheld = (1 << 1), - ControllerType_JoyconPair = (1 << 2), - ControllerType_JoyconLeft = (1 << 3), - ControllerType_JoyconRight = (1 << 4) - } - - public enum HidControllerColorDescription - { - ColorDesc_ColorsNonexistent = (1 << 1), - } - - [StructLayout(LayoutKind.Sequential, Size = 0x8)] - public struct JoystickPosition - { - public int DX; - public int DY; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x20)] - public struct HidControllerMAC - { - public ulong Timestamp; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public byte[] MAC; - public ulong Unknown; - public ulong Timestamp_2; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x28)] - public struct HidControllerHeader - { - public uint Type; - public uint IsHalf; - public uint SingleColorsDescriptor; - public uint SingleColorBody; - public uint SingleColorButtons; - public uint SplitColorsDescriptor; - public uint LeftColorBody; - public uint LeftColorButtons; - public uint RightColorBody; - public uint RightColorButtons; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x20)] - public struct HidControllerLayoutHeader - { - public ulong TimestampTicks; - public ulong NumEntries; - public ulong LatestEntry; - public ulong MaxEntryIndex; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x30)] - public struct HidControllerInputEntry - { - public ulong Timestamp; - public ulong Timestamp_2; - public ulong Buttons; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)HidControllerJoystick.Joystick_Num_Sticks)] - public JoystickPosition[] Joysticks; - public ulong ConnectionState; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x350)] - public struct HidControllerLayout - { - public HidControllerLayoutHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] - public HidControllerInputEntry[] Entries; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x5000)] - public struct HidController - { - public HidControllerHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] - public HidControllerLayout[] Layouts; - /* - pro_controller - handheld_joined - joined - left - right - main_no_analog - main - */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x2A70)] - public byte[] Unknown_1; - public HidControllerMAC MacLeft; - public HidControllerMAC MacRight; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xDF8)] - public byte[] Unknown_2; - } -} diff --git a/Ryujinx.Core/Hid/HidControllerButtons.cs b/Ryujinx.Core/Hid/HidControllerButtons.cs new file mode 100644 index 000000000..65eb3f82f --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerButtons.cs @@ -0,0 +1,35 @@ +using System; + +namespace Ryujinx.Core.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.Core/Hid/HidControllerColorDesc.cs b/Ryujinx.Core/Hid/HidControllerColorDesc.cs new file mode 100644 index 000000000..fc7fa2178 --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerColorDesc.cs @@ -0,0 +1,10 @@ +using System; + +namespace Ryujinx.Core.Input +{ + [Flags] + public enum HidControllerColorDesc + { + ColorDesc_ColorsNonexistent = (1 << 1) + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidControllerConnState.cs b/Ryujinx.Core/Hid/HidControllerConnState.cs new file mode 100644 index 000000000..7f47a7f92 --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerConnState.cs @@ -0,0 +1,11 @@ +using System; + +namespace Ryujinx.Core.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.Core/Hid/HidControllerId.cs b/Ryujinx.Core/Hid/HidControllerId.cs new file mode 100644 index 000000000..84b68d27e --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerId.cs @@ -0,0 +1,16 @@ +namespace Ryujinx.Core.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.Core/Hid/HidControllerLayouts.cs b/Ryujinx.Core/Hid/HidControllerLayouts.cs new file mode 100644 index 000000000..e04c40b2d --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerLayouts.cs @@ -0,0 +1,13 @@ +namespace Ryujinx.Core.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.Core/Hid/HidControllerType.cs b/Ryujinx.Core/Hid/HidControllerType.cs new file mode 100644 index 000000000..a4eb674c8 --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerType.cs @@ -0,0 +1,14 @@ +using System; + +namespace Ryujinx.Core.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.Core/Hid/HidJoystickPosition.cs b/Ryujinx.Core/Hid/HidJoystickPosition.cs new file mode 100644 index 000000000..61f8189f4 --- /dev/null +++ b/Ryujinx.Core/Hid/HidJoystickPosition.cs @@ -0,0 +1,8 @@ +namespace Ryujinx.Core.Input +{ + public struct HidJoystickPosition + { + public int DX; + public int DY; + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidKeyboard.cs b/Ryujinx.Core/Hid/HidKeyboard.cs deleted file mode 100644 index f9987f68b..000000000 --- a/Ryujinx.Core/Hid/HidKeyboard.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - [StructLayout(LayoutKind.Sequential, Size = 0x20)] - public struct HidKeyboardHeader - { - public ulong TimestampTicks; - public ulong NumEntries; - public ulong LatestEntry; - public ulong MaxEntryIndex; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x38)] - public struct HidKeyboardEntry - { - public ulong Timestamp; - public ulong Timestamp_2; - public ulong Modifier; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public uint[] Keys; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidKeyboard - { - public HidKeyboardHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] - public HidKeyboardEntry[] Entries; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x28)] - public byte[] Padding; - } -} diff --git a/Ryujinx.Core/Hid/HidMouse.cs b/Ryujinx.Core/Hid/HidMouse.cs deleted file mode 100644 index 9a019dd5f..000000000 --- a/Ryujinx.Core/Hid/HidMouse.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - [StructLayout(LayoutKind.Sequential, Size = 0x20)] - public struct HidMouseHeader - { - public ulong TimestampTicks; - public ulong NumEntries; - public ulong LatestEntry; - public ulong MaxEntryIndex; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x30)] - public struct HidMouseEntry - { - public ulong Timestamp; - public ulong Timestamp_2; - public uint X; - public uint Y; - public uint VelocityX; - public uint VelocityY; - public uint ScrollVelocityX; - public uint ScrollVelocityY; - public ulong Buttons; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidMouse - { - public HidMouseHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] - public HidMouseEntry[] Entries; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xB0)] - public byte[] Padding; - } -} diff --git a/Ryujinx.Core/Hid/HidTouchPoint.cs b/Ryujinx.Core/Hid/HidTouchPoint.cs new file mode 100644 index 000000000..1207e1d53 --- /dev/null +++ b/Ryujinx.Core/Hid/HidTouchPoint.cs @@ -0,0 +1,11 @@ +namespace Ryujinx.Core.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.Core/Hid/HidTouchScreen.cs b/Ryujinx.Core/Hid/HidTouchScreen.cs deleted file mode 100644 index 755ebadca..000000000 --- a/Ryujinx.Core/Hid/HidTouchScreen.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - [StructLayout(LayoutKind.Sequential, Size = 0x28)] - public struct HidTouchScreenHeader - { - public ulong TimestampTicks; - public ulong NumEntries; - public ulong LatestEntry; - public ulong MaxEntryIndex; - public ulong Timestamp; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x10)] - public struct HidTouchScreenEntryHeader - { - public ulong Timestamp; - public ulong NumTouches; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x28)] - public 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 Padding_2; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x298)] - public struct HidTouchScreenEntry - { - public HidTouchScreenEntryHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] - public HidTouchScreenEntryTouch[] Touches; - public ulong Unknown; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x3000)] - public struct HidTouchScreen - { - public HidTouchScreenHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] - public HidTouchScreenEntry[] Entries; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x3C0)] - public byte[] Padding; - } - -} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidUnknown.cs b/Ryujinx.Core/Hid/HidUnknown.cs deleted file mode 100644 index c3fe68a83..000000000 --- a/Ryujinx.Core/Hid/HidUnknown.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidSharedMemHeader - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidUnknownSection1 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidUnknownSection2 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidUnknownSection3 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidUnknownSection4 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x200)] - public struct HidUnknownSection5 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x200)] - public struct HidUnknownSection6 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x200)] - public struct HidUnknownSection7 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x800)] - public struct HidUnknownSection8 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x800)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x4000)] - public struct HidControllerSerials - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x4000)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x4600)] - public struct HidUnknownSection9 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x4600)] - public byte[] Padding; - } -} diff --git a/Ryujinx.Core/Hid/JoyCon.cs b/Ryujinx.Core/Hid/JoyCon.cs index 8c9518e58..1aef82fe0 100644 --- a/Ryujinx.Core/Hid/JoyCon.cs +++ b/Ryujinx.Core/Hid/JoyCon.cs @@ -1,27 +1,6 @@ -namespace Ryujinx +//TODO: This is only used by Config, it doesn't belong to Core. +namespace Ryujinx.Core.Input { - /// - /// Common RGB color hex codes for JoyCon coloring. - /// - public enum JoyConColor //Thanks to CTCaer - { - 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 - } - public struct JoyConLeft { public int StickUp; diff --git a/Ryujinx.Core/Hid/JoyConColor.cs b/Ryujinx.Core/Hid/JoyConColor.cs new file mode 100644 index 000000000..21d89fe42 --- /dev/null +++ b/Ryujinx.Core/Hid/JoyConColor.cs @@ -0,0 +1,23 @@ +namespace Ryujinx.Core.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.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index f0b568c8c..84a21a8c1 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -242,6 +242,16 @@ namespace Ryujinx.Core.OsHle Logging.Trace($"Executing at 0x{e.Position:x16} {e.SubName}"); } + public void EnableCpuTracing() + { + Translator.EnableCpuTrace = true; + } + + public void DisableCpuTracing() + { + Translator.EnableCpuTrace = false; + } + private int GetFreeTlsSlot(AThread Thread) { for (int Index = 1; Index < TotalTlsSlots; Index++) diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs index e7559a140..6969d3793 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs @@ -121,6 +121,8 @@ namespace Ryujinx.Core.OsHle.Svc if (SharedMem != null) { + AMemoryHelper.FillWithZeros(Memory, Src, (int)Size); + SharedMem.AddVirtualPosition(Src); Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm); diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs index 8fd7979e4..0d5f8e72f 100644 --- a/Ryujinx.Core/Switch.cs +++ b/Ryujinx.Core/Switch.cs @@ -1,4 +1,5 @@ using ChocolArm64.Memory; +using Ryujinx.Core.Input; using Ryujinx.Core.OsHle; using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gpu; @@ -14,7 +15,7 @@ namespace Ryujinx.Core internal NsGpu Gpu { get; private set; } internal Horizon Os { get; private set; } internal VirtualFs VFs { get; private set; } - internal Hid Hid { get; private set; } + public Hid Hid { get; private set; } public event EventHandler Finish; @@ -43,20 +44,6 @@ namespace Ryujinx.Core Os.LoadProgram(FileName); } - public void SendControllerButtons(HidControllerID ControllerId, - HidControllerLayouts Layout, - HidControllerKeys Buttons, - JoystickPosition LeftJoystick, - JoystickPosition RightJoystick) - { - Hid.SendControllerButtons(ControllerId, Layout, Buttons, LeftJoystick, RightJoystick); - } - - public void SendTouchScreenEntry(HidTouchScreenEntryTouch TouchPoint) - { - Hid.SendTouchPoint(TouchPoint); - } - internal virtual void OnFinish(EventArgs e) { Finish?.Invoke(this, e); diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index 3219303eb..be49d1fc9 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -1,7 +1,9 @@ using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; +using OpenTK.Input; using Ryujinx.Core; +using Ryujinx.Core.Input; using Ryujinx.Graphics.Gal; using System; @@ -9,6 +11,12 @@ namespace Ryujinx { public class GLScreen : GameWindow { + private const int TouchScreenWidth = 1280; + private const int TouchScreenHeight = 720; + + private const float TouchScreenRatioX = (float)TouchScreenWidth / TouchScreenHeight; + private const float TouchScreenRatioY = (float)TouchScreenHeight / TouchScreenWidth; + private Switch Ns; private IGalRenderer Renderer; @@ -32,86 +40,124 @@ namespace Ryujinx protected override void OnUpdateFrame(FrameEventArgs e) { - HidControllerKeys CurrentButton = 0; - JoystickPosition LeftJoystick; - JoystickPosition RightJoystick; - + HidControllerButtons CurrentButton = 0; + HidJoystickPosition LeftJoystick; + HidJoystickPosition RightJoystick; if (Keyboard[OpenTK.Input.Key.Escape]) this.Exit(); - //RightJoystick int LeftJoystickDX = 0; int LeftJoystickDY = 0; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickUp]) LeftJoystickDY = short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickDown]) LeftJoystickDY = -short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickLeft]) LeftJoystickDX = -short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickRight]) LeftJoystickDX = short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickButton]) CurrentButton |= HidControllerKeys.KEY_LSTICK; - - //LeftButtons - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadUp]) CurrentButton |= HidControllerKeys.KEY_DUP; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadDown]) CurrentButton |= HidControllerKeys.KEY_DDOWN; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadLeft]) CurrentButton |= HidControllerKeys.KEY_DLEFT; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadRight]) CurrentButton |= HidControllerKeys.KEY_DRIGHT; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonMinus]) CurrentButton |= HidControllerKeys.KEY_MINUS; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonL]) CurrentButton |= HidControllerKeys.KEY_L; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonZL]) CurrentButton |= HidControllerKeys.KEY_ZL; - - //RightJoystick int RightJoystickDX = 0; int RightJoystickDY = 0; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickUp]) RightJoystickDY = short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickDown]) RightJoystickDY = -short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickLeft]) RightJoystickDX = -short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickRight]) RightJoystickDX = short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickButton]) CurrentButton |= HidControllerKeys.KEY_RSTICK; + + //RightJoystick + if (Keyboard[(Key)Config.FakeJoyCon.Left.StickUp]) LeftJoystickDY = short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Left.StickDown]) LeftJoystickDY = -short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Left.StickLeft]) LeftJoystickDX = -short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Left.StickRight]) LeftJoystickDX = short.MaxValue; + + //LeftButtons + if (Keyboard[(Key)Config.FakeJoyCon.Left.StickButton]) CurrentButton |= HidControllerButtons.KEY_LSTICK; + if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadUp]) CurrentButton |= HidControllerButtons.KEY_DUP; + if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadDown]) CurrentButton |= HidControllerButtons.KEY_DDOWN; + if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadLeft]) CurrentButton |= HidControllerButtons.KEY_DLEFT; + if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadRight]) CurrentButton |= HidControllerButtons.KEY_DRIGHT; + if (Keyboard[(Key)Config.FakeJoyCon.Left.ButtonMinus]) CurrentButton |= HidControllerButtons.KEY_MINUS; + if (Keyboard[(Key)Config.FakeJoyCon.Left.ButtonL]) CurrentButton |= HidControllerButtons.KEY_L; + if (Keyboard[(Key)Config.FakeJoyCon.Left.ButtonZL]) CurrentButton |= HidControllerButtons.KEY_ZL; + + //RightJoystick + if (Keyboard[(Key)Config.FakeJoyCon.Right.StickUp]) RightJoystickDY = short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Right.StickDown]) RightJoystickDY = -short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Right.StickLeft]) RightJoystickDX = -short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Right.StickRight]) RightJoystickDX = short.MaxValue; //RightButtons - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonA]) CurrentButton |= HidControllerKeys.KEY_A; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonB]) CurrentButton |= HidControllerKeys.KEY_B; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonX]) CurrentButton |= HidControllerKeys.KEY_X; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonY]) CurrentButton |= HidControllerKeys.KEY_Y; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonPlus]) CurrentButton |= HidControllerKeys.KEY_PLUS; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonR]) CurrentButton |= HidControllerKeys.KEY_R; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonZR]) CurrentButton |= HidControllerKeys.KEY_ZR; + if (Keyboard[(Key)Config.FakeJoyCon.Right.StickButton]) CurrentButton |= HidControllerButtons.KEY_RSTICK; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonA]) CurrentButton |= HidControllerButtons.KEY_A; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonB]) CurrentButton |= HidControllerButtons.KEY_B; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonX]) CurrentButton |= HidControllerButtons.KEY_X; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonY]) CurrentButton |= HidControllerButtons.KEY_Y; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonPlus]) CurrentButton |= HidControllerButtons.KEY_PLUS; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonR]) CurrentButton |= HidControllerButtons.KEY_R; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonZR]) CurrentButton |= HidControllerButtons.KEY_ZR; - LeftJoystick = new JoystickPosition + LeftJoystick = new HidJoystickPosition { DX = LeftJoystickDX, DY = LeftJoystickDY }; - RightJoystick = new JoystickPosition + RightJoystick = new HidJoystickPosition { DX = RightJoystickDX, DY = RightJoystickDY }; + bool HasTouch = false; + //Get screen touch position from left mouse click - //Opentk always captures mouse events, even if out of focus, so check if window is focused. - if (Mouse != null && Focused) - if (Mouse.GetState().LeftButton == OpenTK.Input.ButtonState.Pressed) + //OpenTK always captures mouse events, even if out of focus, so check if window is focused. + if (Focused && Mouse?.GetState().LeftButton == OpenTK.Input.ButtonState.Pressed) + { + int ScrnWidth = Width; + int ScrnHeight = Height; + + if (Width > Height * TouchScreenRatioX) { - HidTouchScreenEntryTouch CurrentPoint = new HidTouchScreenEntryTouch + ScrnWidth = (int)(Height * TouchScreenRatioX); + } + else + { + ScrnHeight = (int)(Width * TouchScreenRatioY); + } + + int StartX = (Width - ScrnWidth) >> 1; + int StartY = (Height - ScrnHeight) >> 1; + + int EndX = StartX + ScrnWidth; + int EndY = StartY + ScrnHeight; + + if (Mouse.X >= StartX && + Mouse.Y >= StartY && + Mouse.X < EndX && + Mouse.Y < EndY) + { + int ScrnMouseX = Mouse.X - StartX; + int ScrnMouseY = Mouse.Y - StartY; + + int MX = (int)(((float)ScrnMouseX / ScrnWidth) * TouchScreenWidth); + int MY = (int)(((float)ScrnMouseY / ScrnHeight) * TouchScreenHeight); + + HidTouchPoint CurrentPoint = new HidTouchPoint { - Timestamp = (uint)Environment.TickCount, - X = (uint)Mouse.X, - Y = (uint)Mouse.Y, + X = MX, + Y = MY, //Placeholder values till more data is acquired DiameterX = 10, DiameterY = 10, - Angle = 90, - - //Only support single touch - TouchIndex = 0, + Angle = 90 }; - if (Mouse.X > -1 && Mouse.Y > -1) - Ns.SendTouchScreenEntry(CurrentPoint); - } - //We just need one pair of JoyCon because it's emulate by the keyboard. - Ns.SendControllerButtons(HidControllerID.CONTROLLER_HANDHELD, HidControllerLayouts.Main, CurrentButton, LeftJoystick, RightJoystick); + HasTouch = true; + + Ns.Hid.SetTouchPoints(CurrentPoint); + } + } + + if (!HasTouch) + { + Ns.Hid.SetTouchPoints(); + } + + Ns.Hid.SetJoyconButton( + HidControllerId.CONTROLLER_HANDHELD, + HidControllerLayouts.Main, + CurrentButton, + LeftJoystick, + RightJoystick); } protected override void OnRenderFrame(FrameEventArgs e)