From f4e74823125b1069a214308770bb225e1b0c1b86 Mon Sep 17 00:00:00 2001 From: madwind Date: Sat, 11 Jan 2025 23:10:08 +0800 Subject: [PATCH] fix sdl3 motion --- .../SDL3HardwareDeviceDriver.cs | 10 -- .../SDL3HardwareDeviceSession.cs | 1 - src/Ryujinx.Input.SDL3/GamepadInfo.cs | 4 + src/Ryujinx.Input.SDL3/SDL3Gamepad.cs | 9 +- src/Ryujinx.Input.SDL3/SDL3GamepadDriver.cs | 124 ++++++++---------- src/Ryujinx.Input.SDL3/SDL3JoyCon.cs | 26 ++-- src/Ryujinx.Input.SDL3/SDL3JoyConPair.cs | 37 ++---- src/Ryujinx.SDL3-CS/SDL3.cs | 4 +- src/Ryujinx.SDL3.Common/SDL3Driver.cs | 13 +- 9 files changed, 100 insertions(+), 128 deletions(-) create mode 100644 src/Ryujinx.Input.SDL3/GamepadInfo.cs diff --git a/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceDriver.cs b/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceDriver.cs index 04ff7b8c5..4481cdc83 100644 --- a/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceDriver.cs +++ b/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceDriver.cs @@ -49,14 +49,6 @@ namespace Ryujinx.Audio.Backends.SDL3 private static bool IsSupportedInternal() { - var devices = SDL_GetAudioPlaybackDevices(out int count); - var joystickIDs = new int[count]; - Marshal.Copy(devices, joystickIDs, 0, count); - for (int i = 0; i < count; ++i) - { - Console.WriteLine(joystickIDs[i]); - } - var device = OpenStream(SampleFormat.PcmInt16, Constants.TargetSampleRate, Constants.ChannelCountMax, Constants.TargetSampleCount, null); @@ -147,11 +139,9 @@ namespace Ryujinx.Audio.Backends.SDL3 return 0; } - Console.WriteLine(SDL_GetAudioDeviceName(device)); bool isValid = false; if (SDL_GetAudioDeviceFormat(device, out SDL_AudioSpec got, out int i)) { - Console.WriteLine(got.freq); isValid = got.format == desired.format && got.freq == desired.freq && got.channels == desired.channels; } diff --git a/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceSession.cs b/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceSession.cs index 8eaf000e0..0c23db989 100644 --- a/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceSession.cs +++ b/src/Ryujinx.Audio.Backends.SDL3/SDL3HardwareDeviceSession.cs @@ -151,7 +151,6 @@ namespace Ryujinx.Audio.Backends.SDL3 public override void QueueBuffer(AudioBuffer buffer) { - Console.WriteLine(buffer); EnsureAudioStreamSetup(buffer); if (_outputStream != 0) diff --git a/src/Ryujinx.Input.SDL3/GamepadInfo.cs b/src/Ryujinx.Input.SDL3/GamepadInfo.cs new file mode 100644 index 000000000..d0f3d88cf --- /dev/null +++ b/src/Ryujinx.Input.SDL3/GamepadInfo.cs @@ -0,0 +1,4 @@ +namespace Ryujinx.Input.SDL3 +{ + public record GamepadInfo(string driverId, nint gamepadHandle); +} diff --git a/src/Ryujinx.Input.SDL3/SDL3Gamepad.cs b/src/Ryujinx.Input.SDL3/SDL3Gamepad.cs index 519ecb1cb..ea019badc 100644 --- a/src/Ryujinx.Input.SDL3/SDL3Gamepad.cs +++ b/src/Ryujinx.Input.SDL3/SDL3Gamepad.cs @@ -60,13 +60,13 @@ namespace Ryujinx.Input.SDL3 private float _triggerThreshold; - public SDL3Gamepad(nint gamepadHandle, string driverId) + public SDL3Gamepad(GamepadInfo gamepadInfo) { - _gamepadHandle = gamepadHandle; + _gamepadHandle = gamepadInfo.gamepadHandle; _buttonsUserMapping = new List(20); Name = SDL_GetGamepadName(_gamepadHandle); - Id = driverId; + Id = gamepadInfo.driverId; Features = GetFeaturesFlag(); _triggerThreshold = 0.0f; @@ -181,8 +181,7 @@ namespace Ryujinx.Input.SDL3 private static Vector3 RadToDegree(Vector3 rad) => rad * (180 / MathF.PI); - //TODO: miss constant SDL_STANDARD_GRAVITY 9.80665f - private static Vector3 GsToMs2(Vector3 gs) => gs / 9.80665f; + private static Vector3 GsToMs2(Vector3 gs) => gs / SDL_STANDARD_GRAVITY; public void SetConfiguration(InputConfig configuration) { diff --git a/src/Ryujinx.Input.SDL3/SDL3GamepadDriver.cs b/src/Ryujinx.Input.SDL3/SDL3GamepadDriver.cs index a0e13985d..d810d36d7 100644 --- a/src/Ryujinx.Input.SDL3/SDL3GamepadDriver.cs +++ b/src/Ryujinx.Input.SDL3/SDL3GamepadDriver.cs @@ -4,7 +4,6 @@ using Ryujinx.SDL3.Common; using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.InteropServices; using System.Text; using System.Threading; using static SDL3.SDL; @@ -13,7 +12,7 @@ namespace Ryujinx.Input.SDl3 { public class SDL3GamepadDriver : IGamepadDriver { - private readonly Dictionary _gamepadsInstanceIdsMapping; + private readonly Dictionary _gamepadsInstanceIdsMapping; private readonly List _gamepadsIds; private readonly Lock _lock = new(); @@ -35,7 +34,7 @@ namespace Ryujinx.Input.SDl3 public SDL3GamepadDriver() { - _gamepadsInstanceIdsMapping = new Dictionary(); + _gamepadsInstanceIdsMapping = new Dictionary(); _gamepadsIds = new List(); SDL3Driver.Instance.Initialize(); @@ -43,20 +42,19 @@ namespace Ryujinx.Input.SDl3 SDL3Driver.Instance.OnJoystickDisconnected += HandleJoyStickDisconnected; SDL3Driver.Instance.OnJoyBatteryUpdated += HandleJoyBatteryUpdated; - IntPtr joystickArray = SDL_GetJoysticks(out int count); - - var joystickIDs = new int[count]; - Marshal.Copy(joystickArray, joystickIDs, 0, count); - - for (int i = 0; i < count; i++) - { - HandleJoyStickConnected((uint)joystickIDs[i]); - } + // IntPtr joystickArray = SDL_GetJoysticks(out int count); + // + // var joystickIDs = new int[count]; + // Marshal.Copy(joystickArray, joystickIDs, 0, count); + // + // for (int i = 0; i < count; i++) + // { + // HandleJoyStickConnected((uint)joystickIDs[i]); + // } } private string GenerateGamepadId(uint joystickIndex) { - int bufferSize = 33; Span pszGUID = stackalloc byte[bufferSize]; SDL_GUIDToString(SDL_GetJoystickGUIDForID(joystickIndex), pszGUID, bufferSize); @@ -82,23 +80,24 @@ namespace Ryujinx.Input.SDl3 return id; } - private uint GetJoystickIndexByGamepadId(string id) + private GamepadInfo GetJoystickIndexByGamepadId(string id) { lock (_lock) { - return _gamepadsInstanceIdsMapping.FirstOrDefault(x=>x.Value == id).Key; + return _gamepadsInstanceIdsMapping.FirstOrDefault(x => x.Value.driverId == id).Value; } } private void HandleJoyStickDisconnected(uint joystickInstanceId) { bool joyConPairDisconnected = false; - if (!_gamepadsInstanceIdsMapping.Remove(joystickInstanceId, out string id)) + if (!_gamepadsInstanceIdsMapping.Remove(joystickInstanceId, out GamepadInfo gamepadInfo)) return; lock (_lock) { - _gamepadsIds.Remove(id); + _gamepadsIds.Remove(gamepadInfo.driverId); + SDL_CloseGamepad(gamepadInfo.gamepadHandle); if (!SDL3JoyConPair.IsCombinable(_gamepadsInstanceIdsMapping)) { _gamepadsIds.Remove(SDL3JoyConPair.Id); @@ -106,62 +105,58 @@ namespace Ryujinx.Input.SDl3 } } - OnGamepadDisconnected?.Invoke(id); + OnGamepadDisconnected?.Invoke(gamepadInfo.driverId); if (joyConPairDisconnected) { OnGamepadDisconnected?.Invoke(SDL3JoyConPair.Id); } } - private void HandleJoyStickConnected(uint joystickInstanceId) + private void HandleJoyStickConnected(uint gamepadInstanceId) { bool joyConPairConnected = false; - - if (SDL_IsGamepad(joystickInstanceId)) + if (_gamepadsInstanceIdsMapping.ContainsKey(gamepadInstanceId)) { - if (_gamepadsInstanceIdsMapping.ContainsKey(joystickInstanceId)) + // Sometimes a JoyStick connected event fires after the app starts even though it was connected before + // so it is rejected to avoid doubling the entries. + return; + } + + string id = GenerateGamepadId(gamepadInstanceId); + if (id == null) + { + return; + } + + if (_gamepadsInstanceIdsMapping.TryAdd(gamepadInstanceId, new GamepadInfo(id, SDL_OpenGamepad(gamepadInstanceId)))) + { + lock (_lock) { - // Sometimes a JoyStick connected event fires after the app starts even though it was connected before - // so it is rejected to avoid doubling the entries. - return; + if (gamepadInstanceId <= _gamepadsIds.FindLastIndex(_ => true)) + { + // _gamepadsIds.Insert(joystickDeviceId, id); + } + else + _gamepadsIds.Add(id); + + if (SDL3JoyConPair.IsCombinable(_gamepadsInstanceIdsMapping)) + { + _gamepadsIds.Remove(SDL3JoyConPair.Id); + _gamepadsIds.Add(SDL3JoyConPair.Id); + joyConPairConnected = true; + } } - string id = GenerateGamepadId(joystickInstanceId); - if (id == null) + OnGamepadConnected?.Invoke(id); + if (joyConPairConnected) { - return; - } - - if (_gamepadsInstanceIdsMapping.TryAdd(joystickInstanceId, id)) - { - lock (_lock) - { - if (joystickInstanceId <= _gamepadsIds.FindLastIndex(_ => true)) - { - // _gamepadsIds.Insert(joystickDeviceId, id); - } - else - _gamepadsIds.Add(id); - - if (SDL3JoyConPair.IsCombinable(_gamepadsInstanceIdsMapping)) - { - _gamepadsIds.Remove(SDL3JoyConPair.Id); - _gamepadsIds.Add(SDL3JoyConPair.Id); - joyConPairConnected = true; - } - } - - OnGamepadConnected?.Invoke(id); - if (joyConPairConnected) - { - OnGamepadConnected?.Invoke(SDL3JoyConPair.Id); - } + OnGamepadConnected?.Invoke(SDL3JoyConPair.Id); } } } - private void HandleJoyBatteryUpdated(uint joystickDeviceId, SDL_JoyBatteryEvent joyBatteryEvent) + private void HandleJoyBatteryUpdated(uint joystickDeviceId, SDL_JoyBatteryEvent joyBatteryEvent) { Logger.Info?.Print(LogClass.Hid, $"{SDL_GetGamepadNameForID(joystickDeviceId)}, Battery percent: {joyBatteryEvent.percent}"); @@ -205,27 +200,18 @@ namespace Ryujinx.Input.SDl3 } } - var instanceId = GetJoystickIndexByGamepadId(id); - - if (instanceId == nint.Zero) - { - return null; - } - - nint gamepadHandle = SDL_OpenGamepad(instanceId); - - if (gamepadHandle == nint.Zero) + var gamepadInfo = GetJoystickIndexByGamepadId(id); + if (gamepadInfo == null) { return null; } - Console.WriteLine(SDL_GetGamepadName(gamepadHandle)); - if (SDL_GetGamepadName(gamepadHandle).StartsWith(SDL3JoyCon.Prefix)) + if (SDL3JoyCon.IsJoyCon(gamepadInfo.gamepadHandle)) { - return new SDL3JoyCon(gamepadHandle, id); + return new SDL3JoyCon(gamepadInfo); } - return new SDL3Gamepad(gamepadHandle, id); + return new SDL3Gamepad(gamepadInfo); } } } diff --git a/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs b/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs index c44f42580..02451b17e 100644 --- a/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs +++ b/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs @@ -61,27 +61,27 @@ namespace Ryujinx.Input.SDL3 public GamepadFeaturesFlag Features { get; } private nint _gamepadHandle; - + private enum JoyConType { Left, Right } - public const string Prefix = "Nintendo Switch Joy-Con"; public const string LeftName = "Nintendo Switch Joy-Con (L)"; public const string RightName = "Nintendo Switch Joy-Con (R)"; private readonly JoyConType _joyConType; - public SDL3JoyCon(nint gamepadHandle, string driverId) + public SDL3JoyCon(GamepadInfo gamepadInfo) { - _gamepadHandle = gamepadHandle; + _gamepadHandle = gamepadInfo.gamepadHandle; _buttonsUserMapping = new List(10); Name = SDL_GetGamepadName(_gamepadHandle); - Id = driverId; + Id = gamepadInfo.driverId; Features = GetFeaturesFlag(); - + Console.WriteLine(Name+": "+Features); + // Enable motion tracking if (Features.HasFlag(GamepadFeaturesFlag.Motion)) { @@ -118,7 +118,6 @@ namespace Ryujinx.Input.SDL3 private GamepadFeaturesFlag GetFeaturesFlag() { GamepadFeaturesFlag result = GamepadFeaturesFlag.None; - if (SDL_GamepadHasSensor(_gamepadHandle, SDL_SensorType.SDL_SENSOR_ACCEL) && SDL_GamepadHasSensor(_gamepadHandle, SDL_SensorType.SDL_SENSOR_GYRO)) { @@ -141,8 +140,7 @@ namespace Ryujinx.Input.SDL3 { if (disposing && _gamepadHandle != nint.Zero) { - SDL_CloseGamepad(_gamepadHandle); - + // SDL_CloseGamepad(_gamepadHandle); _gamepadHandle = nint.Zero; } } @@ -210,9 +208,7 @@ namespace Ryujinx.Input.SDL3 } private static Vector3 RadToDegree(Vector3 rad) => rad * (180 / MathF.PI); - - //TODO: miss constant SDL_STANDARD_GRAVITY 9.80665f - private static Vector3 GsToMs2(Vector3 gs) => gs / 9.80665f; + private static Vector3 GsToMs2(Vector3 gs) => gs / SDL_STANDARD_GRAVITY; public void SetConfiguration(InputConfig configuration) { @@ -416,5 +412,11 @@ namespace Ryujinx.Input.SDL3 // } return SDL_GetGamepadButton(_gamepadHandle, button); } + + public static bool IsJoyCon(IntPtr gamepadHandle) + { + var gamepadName = SDL_GetGamepadName(gamepadHandle); + return gamepadName is LeftName or RightName; + } } } diff --git a/src/Ryujinx.Input.SDL3/SDL3JoyConPair.cs b/src/Ryujinx.Input.SDL3/SDL3JoyConPair.cs index 519c99531..558392afa 100644 --- a/src/Ryujinx.Input.SDL3/SDL3JoyConPair.cs +++ b/src/Ryujinx.Input.SDL3/SDL3JoyConPair.cs @@ -101,41 +101,32 @@ namespace Ryujinx.Input.SDL3 right.SetTriggerThreshold(triggerThreshold); } - public static bool IsCombinable(Dictionary gamepadsInstanceIdsMapping) + public static bool IsCombinable(Dictionary gamepadsInstanceIdsMapping) { - (uint leftIndex, uint rightIndex) = DetectJoyConPair(gamepadsInstanceIdsMapping); - return leftIndex != 0 && rightIndex != 0; + (GamepadInfo leftGamepadInfo, GamepadInfo rightGamepadInfo) = DetectJoyConPair(gamepadsInstanceIdsMapping); + return leftGamepadInfo != null && rightGamepadInfo != null; } - private static (uint leftInstance, uint rightInstance) DetectJoyConPair( - Dictionary gamepadsInstanceIdsMapping) + private static (GamepadInfo leftGamepadInfo, GamepadInfo rightGamepadInfo) DetectJoyConPair( + Dictionary gamepadsInstanceIdsMapping) { - var leftInstance = gamepadsInstanceIdsMapping - .FirstOrDefault(item => SDL_GetGamepadNameForID(item.Key) == SDL3JoyCon.LeftName).Key; - var rightInstance = gamepadsInstanceIdsMapping - .FirstOrDefault(item => SDL_GetGamepadNameForID(item.Key) == SDL3JoyCon.RightName).Key; + var leftGamepadInfo = gamepadsInstanceIdsMapping + .FirstOrDefault(item => SDL_GetGamepadNameForID(item.Key) == SDL3JoyCon.LeftName).Value; + var rightGamepadInfo = gamepadsInstanceIdsMapping + .FirstOrDefault(item => SDL_GetGamepadNameForID(item.Key) == SDL3JoyCon.RightName).Value; - return (leftInstance, rightInstance); + return (leftGamepadInfo, rightGamepadInfo); } - public static IGamepad GetGamepad(Dictionary gamepadsInstanceIdsMapping) + public static IGamepad GetGamepad(Dictionary gamepadsInstanceIdsMapping) { - (uint leftInstance, uint rightInstance) = DetectJoyConPair(gamepadsInstanceIdsMapping); - if (leftInstance == 0 || rightInstance == 0) + (GamepadInfo leftGamepadInfo, GamepadInfo rightGamepadInfo) = DetectJoyConPair(gamepadsInstanceIdsMapping); + if (leftGamepadInfo == null || rightGamepadInfo == null) { return null; } - nint leftGamepadHandle = SDL_OpenGamepad(leftInstance); - nint rightGamepadHandle = SDL_OpenGamepad(rightInstance); - - if (leftGamepadHandle == nint.Zero || rightGamepadHandle == nint.Zero) - { - return null; - } - - return new SDL3JoyConPair(new SDL3JoyCon(leftGamepadHandle, gamepadsInstanceIdsMapping[leftInstance]), - new SDL3JoyCon(rightGamepadHandle, gamepadsInstanceIdsMapping[rightInstance])); + return new SDL3JoyConPair(new SDL3JoyCon(leftGamepadInfo), new SDL3JoyCon(rightGamepadInfo)); } } } diff --git a/src/Ryujinx.SDL3-CS/SDL3.cs b/src/Ryujinx.SDL3-CS/SDL3.cs index d1f50c76f..ffb7261f6 100644 --- a/src/Ryujinx.SDL3-CS/SDL3.cs +++ b/src/Ryujinx.SDL3-CS/SDL3.cs @@ -8048,6 +8048,6 @@ public static unsafe partial class SDL [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial int SDL_EnterAppMainCallbacks(int argc, IntPtr argv, SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit); - public const uint SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK = 0xFFFFFFFFu; - + public const uint SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK = 0xFFFFFFFFu; + public const float SDL_STANDARD_GRAVITY = 9.80665f; } diff --git a/src/Ryujinx.SDL3.Common/SDL3Driver.cs b/src/Ryujinx.SDL3.Common/SDL3Driver.cs index bcdd89e3f..73982ef12 100644 --- a/src/Ryujinx.SDL3.Common/SDL3Driver.cs +++ b/src/Ryujinx.SDL3.Common/SDL3Driver.cs @@ -25,7 +25,8 @@ namespace Ryujinx.SDL3.Common public static Action MainThreadDispatcher { get; set; } - private const SDL_InitFlags SdlInitFlags = SDL_InitFlags.SDL_INIT_GAMEPAD | SDL_InitFlags.SDL_INIT_AUDIO; + private const SDL_InitFlags SdlInitFlags = SDL_InitFlags.SDL_INIT_GAMEPAD | SDL_InitFlags.SDL_INIT_AUDIO | + SDL_InitFlags.SDL_INIT_VIDEO; private bool _isRunning; private uint _refereceCount; @@ -123,19 +124,18 @@ namespace Ryujinx.SDL3.Common private void HandleSDLEvent(ref SDL_Event evnt) { var type = (SDL_EventType)evnt.type; - if (type == SDL_EventType.SDL_EVENT_JOYSTICK_ADDED) + if (type == SDL_EventType.SDL_EVENT_GAMEPAD_ADDED) { - uint instanceId = evnt.jdevice.which; Logger.Debug?.Print(LogClass.Application, $"Added joystick instance id {instanceId}"); OnJoyStickConnected?.Invoke(instanceId); } - else if (type == SDL_EventType.SDL_EVENT_JOYSTICK_REMOVED) + else if (type == SDL_EventType.SDL_EVENT_GAMEPAD_REMOVED) { uint instanceId = evnt.jdevice.which; - + Logger.Debug?.Print(LogClass.Application, $"Removed joystick instance id {instanceId}"); OnJoystickDisconnected?.Invoke(instanceId); @@ -144,7 +144,8 @@ namespace Ryujinx.SDL3.Common { OnJoyBatteryUpdated?.Invoke(evnt.jbattery.which, evnt.jbattery); } - else if (type is >= SDL_EventType.SDL_EVENT_WINDOW_FIRST and <= SDL_EventType.SDL_EVENT_WINDOW_LAST or SDL_EventType.SDL_EVENT_MOUSE_BUTTON_DOWN + else if (type is >= SDL_EventType.SDL_EVENT_WINDOW_FIRST and <= SDL_EventType.SDL_EVENT_WINDOW_LAST + or SDL_EventType.SDL_EVENT_MOUSE_BUTTON_DOWN or SDL_EventType.SDL_EVENT_MOUSE_BUTTON_UP) { if (_registeredWindowHandlers.TryGetValue(evnt.window.windowID, out Action handler))