From 467707cf7ee359be72e9c87e23e13ef127092374 Mon Sep 17 00:00:00 2001 From: Maki Date: Sun, 23 Nov 2025 16:20:06 -0500 Subject: [PATCH 1/3] fix: JoyCon input mapping --- src/Ryujinx.Input.SDL3/SDL3JoyCon.cs | 61 ++++++++++++++++++---------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs b/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs index d71b06dda..d9419e368 100644 --- a/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs +++ b/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs @@ -24,30 +24,33 @@ namespace Ryujinx.Input.SDL3 private readonly Dictionary _leftButtonsDriverMapping = new() { {GamepadButtonInputId.LeftStick, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_LEFT_STICK}, - {GamepadButtonInputId.DpadUp, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_NORTH}, - {GamepadButtonInputId.DpadDown, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_SOUTH}, - {GamepadButtonInputId.DpadLeft, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_EAST}, - {GamepadButtonInputId.DpadRight, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_WEST}, - {GamepadButtonInputId.Minus, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_START}, - {GamepadButtonInputId.LeftShoulder, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_LEFT_PADDLE1}, - {GamepadButtonInputId.LeftTrigger, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_LEFT_PADDLE2}, - {GamepadButtonInputId.SingleRightTrigger0, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER}, - {GamepadButtonInputId.SingleLeftTrigger0, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_LEFT_SHOULDER}, + {GamepadButtonInputId.DpadUp, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_DPAD_UP}, + {GamepadButtonInputId.DpadDown, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_DPAD_DOWN}, + {GamepadButtonInputId.DpadLeft, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_DPAD_LEFT}, + {GamepadButtonInputId.DpadRight, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_DPAD_RIGHT}, + {GamepadButtonInputId.Minus, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_BACK}, + {GamepadButtonInputId.LeftShoulder, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_LEFT_SHOULDER}, + {GamepadButtonInputId.LeftTrigger, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_INVALID}, + {GamepadButtonInputId.SingleRightTrigger0, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_LEFT_PADDLE2}, + {GamepadButtonInputId.SingleLeftTrigger0, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_LEFT_PADDLE1}, }; private readonly Dictionary _rightButtonsDriverMapping = new() { - {GamepadButtonInputId.RightStick, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_LEFT_STICK}, + {GamepadButtonInputId.RightStick, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_RIGHT_STICK}, {GamepadButtonInputId.A, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_EAST}, - {GamepadButtonInputId.B, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_NORTH}, - {GamepadButtonInputId.X, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_SOUTH}, + {GamepadButtonInputId.B, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_SOUTH}, + {GamepadButtonInputId.X, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_NORTH}, {GamepadButtonInputId.Y, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_WEST}, {GamepadButtonInputId.Plus, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_START}, - {GamepadButtonInputId.RightShoulder, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1}, - {GamepadButtonInputId.RightTrigger, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2}, - {GamepadButtonInputId.SingleRightTrigger1, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER}, - {GamepadButtonInputId.SingleLeftTrigger1, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_LEFT_SHOULDER} + {GamepadButtonInputId.RightShoulder, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER}, + {GamepadButtonInputId.RightTrigger, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_INVALID}, + {GamepadButtonInputId.SingleRightTrigger1, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2}, + {GamepadButtonInputId.SingleLeftTrigger1, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1} }; + private const string LeftMapping = "050067007e0500000620000001800000,Nintendo Switch Joy-Con (L),back:b5,dpdown:b8,dpleft:b9,dpright:b10,dpup:b7,leftshoulder:b1,leftstick:b6,lefttrigger:b3,leftx:a1,lefty:a0,misc1:b0,paddle2:b2,paddle4:b4,"; + private const string RightMapping = "05006ea07e0500000720000001800000,Nintendo Switch Joy-Con (R),a:b0,b:b1,guide:b9,paddle1:b6,paddle3:b4,rightshoulder:b5,rightstick:b10,righttrigger:b7,leftx:a1,lefty:a0,start:b8,x:b3,y:b2,"; + private readonly Dictionary _buttonsDriverMapping; private readonly Lock _userMappingLock = new(); @@ -104,12 +107,18 @@ namespace Ryujinx.Input.SDL3 { _buttonsDriverMapping = _leftButtonsDriverMapping; _joyConType = JoyConType.Left; + if (SDL_AddGamepadMapping(LeftMapping) == -1) { + Logger.Error?.Print(LogClass.Hid, $"Could not set SDL input map for {Name}"); + } break; } case RightName: { _buttonsDriverMapping = _rightButtonsDriverMapping; _joyConType = JoyConType.Right; + if (SDL_AddGamepadMapping(RightMapping) == -1) { + Logger.Error?.Print(LogClass.Hid, $"Could not set SDL input map for {Name}"); + } break; } } @@ -152,9 +161,11 @@ namespace Ryujinx.Input.SDL3 Dispose(true); } + private float _triggerThreshold; + public void SetTriggerThreshold(float triggerThreshold) { - + _triggerThreshold = triggerThreshold; } public void Rumble(float lowFrequency, float highFrequency, uint durationMs) @@ -350,8 +361,8 @@ namespace Ryujinx.Input.SDL3 (short stickX, short stickY) = GetStickXY(); - float resultX = ConvertRawStickValue(stickX); - float resultY = -ConvertRawStickValue(stickY); + float resultX = -ConvertRawStickValue(stickX); + float resultY = ConvertRawStickValue(stickY); if (HasConfiguration) { @@ -376,8 +387,8 @@ namespace Ryujinx.Input.SDL3 return inputId switch { - StickInputId.Left when _joyConType == JoyConType.Left => (resultY, -resultX), - StickInputId.Right when _joyConType == JoyConType.Right => (-resultY, resultX), + StickInputId.Left when _joyConType == JoyConType.Left => (resultY, resultX), + StickInputId.Right when _joyConType == JoyConType.Right => (resultY, resultX), _ => (0.0f, 0.0f) }; } @@ -391,6 +402,14 @@ namespace Ryujinx.Input.SDL3 public bool IsPressed(GamepadButtonInputId inputId) { + switch (inputId) + { + case GamepadButtonInputId.LeftTrigger: + return ConvertRawStickValue(SDL_GetGamepadAxis(_gamepadHandle, SDL_GamepadAxis.SDL_GAMEPAD_AXIS_LEFT_TRIGGER)) > _triggerThreshold; + case GamepadButtonInputId.RightTrigger: + return ConvertRawStickValue(SDL_GetGamepadAxis(_gamepadHandle, SDL_GamepadAxis.SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)) > _triggerThreshold; + } + if (!_buttonsDriverMapping.TryGetValue(inputId, out SDL_GamepadButton button)) { return false; From 28b85302e42ea54382e356156acb4343c36528f5 Mon Sep 17 00:00:00 2001 From: Maki Date: Sun, 30 Nov 2025 12:23:51 -0500 Subject: [PATCH 2/3] limit mappings to linux hosts --- src/Ryujinx.Input.SDL3/SDL3JoyCon.cs | 9 --------- src/Ryujinx.SDL3.Common/SDL3Driver.cs | 10 ++++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs b/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs index d9419e368..7c8561da8 100644 --- a/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs +++ b/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs @@ -48,9 +48,6 @@ namespace Ryujinx.Input.SDL3 {GamepadButtonInputId.SingleLeftTrigger1, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1} }; - private const string LeftMapping = "050067007e0500000620000001800000,Nintendo Switch Joy-Con (L),back:b5,dpdown:b8,dpleft:b9,dpright:b10,dpup:b7,leftshoulder:b1,leftstick:b6,lefttrigger:b3,leftx:a1,lefty:a0,misc1:b0,paddle2:b2,paddle4:b4,"; - private const string RightMapping = "05006ea07e0500000720000001800000,Nintendo Switch Joy-Con (R),a:b0,b:b1,guide:b9,paddle1:b6,paddle3:b4,rightshoulder:b5,rightstick:b10,righttrigger:b7,leftx:a1,lefty:a0,start:b8,x:b3,y:b2,"; - private readonly Dictionary _buttonsDriverMapping; private readonly Lock _userMappingLock = new(); @@ -107,18 +104,12 @@ namespace Ryujinx.Input.SDL3 { _buttonsDriverMapping = _leftButtonsDriverMapping; _joyConType = JoyConType.Left; - if (SDL_AddGamepadMapping(LeftMapping) == -1) { - Logger.Error?.Print(LogClass.Hid, $"Could not set SDL input map for {Name}"); - } break; } case RightName: { _buttonsDriverMapping = _rightButtonsDriverMapping; _joyConType = JoyConType.Right; - if (SDL_AddGamepadMapping(RightMapping) == -1) { - Logger.Error?.Print(LogClass.Hid, $"Could not set SDL input map for {Name}"); - } break; } } diff --git a/src/Ryujinx.SDL3.Common/SDL3Driver.cs b/src/Ryujinx.SDL3.Common/SDL3Driver.cs index 529a846e0..94329b7e4 100644 --- a/src/Ryujinx.SDL3.Common/SDL3Driver.cs +++ b/src/Ryujinx.SDL3.Common/SDL3Driver.cs @@ -28,6 +28,9 @@ namespace Ryujinx.SDL3.Common private const SDL_InitFlags SdlInitFlags = SDL_InitFlags.SDL_INIT_EVENTS | SDL_InitFlags.SDL_INIT_GAMEPAD | SDL_InitFlags.SDL_INIT_JOYSTICK | SDL_InitFlags.SDL_INIT_AUDIO | SDL_InitFlags.SDL_INIT_VIDEO; + private const string JoyconLeftMappingLinux = "050067007e0500000620000001800000,Nintendo Switch Joy-Con (L),platform:Linux,back:b5,dpdown:b8,dpleft:b9,dpright:b10,dpup:b7,leftshoulder:b1,leftstick:b6,lefttrigger:b3,leftx:a1,lefty:a0,misc1:b0,paddle2:b2,paddle4:b4,"; + private const string JoyconRightMappingLinux = "05006ea07e0500000720000001800000,Nintendo Switch Joy-Con (R),platform:Linux,a:b0,b:b1,guide:b9,leftx:a1,lefty:a0,paddle1:b6,paddle3:b4,rightshoulder:b5,rightstick:b10,righttrigger:b7,start:b8,x:b3,y:b2,"; + private bool _isRunning; private uint _refereceCount; private Thread _worker; @@ -96,6 +99,13 @@ namespace Ryujinx.SDL3.Common SDL_SetEventEnabled((uint)SDL_EventType.SDL_EVENT_GAMEPAD_SENSOR_UPDATE, false); + if (SDL_AddGamepadMapping(JoyconLeftMappingLinux) == -1) { + Logger.Error?.Print(LogClass.Hid, $"Could not set SDL Joycon (L) mappings"); + } + if (SDL_AddGamepadMapping(JoyconRightMappingLinux) == -1) { + Logger.Error?.Print(LogClass.Hid, $"Could not set SDL Joycon (R) mappings"); + } + string gamepadDbPath = Path.Combine(AppDataManager.BaseDirPath, "SDL_GameControllerDB.txt"); if (File.Exists(gamepadDbPath)) From b0fdaf15dfea4f1313ecfc5c5d98b75dd5aa261b Mon Sep 17 00:00:00 2001 From: Maki Date: Sun, 30 Nov 2025 13:00:14 -0500 Subject: [PATCH 3/3] Add macOS Joycon mappings --- src/Ryujinx.SDL3.Common/SDL3Driver.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.SDL3.Common/SDL3Driver.cs b/src/Ryujinx.SDL3.Common/SDL3Driver.cs index 94329b7e4..6e46ee558 100644 --- a/src/Ryujinx.SDL3.Common/SDL3Driver.cs +++ b/src/Ryujinx.SDL3.Common/SDL3Driver.cs @@ -30,6 +30,8 @@ namespace Ryujinx.SDL3.Common private const string JoyconLeftMappingLinux = "050067007e0500000620000001800000,Nintendo Switch Joy-Con (L),platform:Linux,back:b5,dpdown:b8,dpleft:b9,dpright:b10,dpup:b7,leftshoulder:b1,leftstick:b6,lefttrigger:b3,leftx:a1,lefty:a0,misc1:b0,paddle2:b2,paddle4:b4,"; private const string JoyconRightMappingLinux = "05006ea07e0500000720000001800000,Nintendo Switch Joy-Con (R),platform:Linux,a:b0,b:b1,guide:b9,leftx:a1,lefty:a0,paddle1:b6,paddle3:b4,rightshoulder:b5,rightstick:b10,righttrigger:b7,start:b8,x:b3,y:b2,"; + private const string JoyconLeftMappingMac = "050067007e0500000620000001006801,Nintendo Switch Joy-Con (L),platform:macOS,back:b6,dpdown:b1,dpleft:b0,dpright:b3,dpup:b2,leftshoulder:b13,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1~,misc1:b5,paddle2:b9,paddle4:b10,"; + private const string JoyconRightMappingMac = "05006ea07e0500000720000001006802,Nintendo Switch Joy-Con (R),platform:macOS,a:b2,b:b0,guide:b5,leftx:a0~,lefty:a1,paddle1:b10,paddle3:b9,rightshoulder:b12,rightstick:b7,righttrigger:b14,start:b6,x:b3,y:b1,"; private bool _isRunning; private uint _refereceCount; @@ -100,10 +102,16 @@ namespace Ryujinx.SDL3.Common SDL_SetEventEnabled((uint)SDL_EventType.SDL_EVENT_GAMEPAD_SENSOR_UPDATE, false); if (SDL_AddGamepadMapping(JoyconLeftMappingLinux) == -1) { - Logger.Error?.Print(LogClass.Hid, $"Could not set SDL Joycon (L) mappings"); + Logger.Warning?.Print(LogClass.Hid, $"Could not set SDL Joycon (L) mappings"); } if (SDL_AddGamepadMapping(JoyconRightMappingLinux) == -1) { - Logger.Error?.Print(LogClass.Hid, $"Could not set SDL Joycon (R) mappings"); + Logger.Warning?.Print(LogClass.Hid, $"Could not set SDL Joycon (R) mappings"); + } + if (SDL_AddGamepadMapping(JoyconLeftMappingMac) == -1) { + Logger.Warning?.Print(LogClass.Hid, $"Could not set SDL Joycon (L) mappings"); + } + if (SDL_AddGamepadMapping(JoyconRightMappingMac) == -1) { + Logger.Warning?.Print(LogClass.Hid, $"Could not set SDL Joycon (R) mappings"); } string gamepadDbPath = Path.Combine(AppDataManager.BaseDirPath, "SDL_GameControllerDB.txt");