diff --git a/assets/Locales/Root.json b/assets/Locales/Root.json index 757ddeec8..d9139904c 100644 --- a/assets/Locales/Root.json +++ b/assets/Locales/Root.json @@ -12250,6 +12250,56 @@ "zh_TW": "弱震動調節:" } }, + { + "ID": "ControllerSettingsRumbleUseHDRumble", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Enable HD Rumble", + "es_ES": "Activa vibración HD", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "HDRumbleTooltip", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Sends more data to the controller for better rumble.\n\nCurrently only supports first-party Nintendo Switch controllers.\n\nLeave ON if you're using JoyCons or a Pro Controller.", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "DialogMessageSaveNotAvailableMessage", "Translations": { diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/RumbleConfigController.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/RumbleConfigController.cs index ee8ab457d..f190996c1 100644 --- a/src/Ryujinx.Common/Configuration/Hid/Controller/RumbleConfigController.cs +++ b/src/Ryujinx.Common/Configuration/Hid/Controller/RumbleConfigController.cs @@ -16,5 +16,10 @@ namespace Ryujinx.Common.Configuration.Hid.Controller /// Enable Rumble /// public bool EnableRumble { get; set; } + + /// + /// Enable HD Rumble support + /// = 0) + { + return true; + } + + if (!String.IsNullOrEmpty(SDL_GetError())) + { + Logger.Error?.PrintMsg(LogClass.Hid, SDL_GetError()); + SDL_ClearError(); + } + return false; } } - private static int EncodeLowFreq(float lowFreq) { float lf = Math.Clamp(lowFreq, 40.875885f, 626.286133f); - return (int)Math.Round(32 * Math.Log2(lf * 0.1f)) - 0x40; + return (int) Math.Round(32 * Math.Log2(lf * 0.1f) - 0x40); } private static int EncodeHighFreq(float highFreq) { float hf = Math.Clamp(highFreq, 81.75177f, 1252.572266f); - return ((int)Math.Round(32 * Math.Log2(hf * 0.1f)) - 0x60) * 4; + return (int) Math.Round((32 * Math.Log2(hf * 0.1f) - 0x60) * 4); } private static int EncodeLowAmp(float rawAmp) { - int encodedAmp = 0; + double encodedAmp = 0; if (rawAmp is > 0 and < 0.012f) { @@ -92,15 +103,15 @@ namespace Ryujinx.Input.SDL3 } else if (rawAmp is >= 0.012f and < 0.112f) { - encodedAmp = (int)Math.Round(4 * Math.Log2(rawAmp * 110f)); + encodedAmp = 4 * Math.Log2(rawAmp * 110f); } else if (rawAmp is >= 0.112f and < 0.225f) { - encodedAmp = (int)Math.Round(16 * Math.Log2(rawAmp * 17f)); + encodedAmp = 16 * Math.Log2(rawAmp * 17f); } else if (rawAmp is >= 0.225f and <= 1f) { - encodedAmp = (int)Math.Round(32 * Math.Log2(rawAmp * 8.7f)); + encodedAmp = 32 * Math.Log2(rawAmp * 8.7f); } return (int)Math.Floor(encodedAmp / 2.0) + 64; @@ -108,7 +119,7 @@ namespace Ryujinx.Input.SDL3 private static int EncodeHighAmp(float rawAmp) { - int encodedAmp = 0; + double encodedAmp = 0; if (rawAmp is > 0 and < 0.012f) { @@ -116,23 +127,23 @@ namespace Ryujinx.Input.SDL3 } else if (rawAmp is >= 0.012f and < 0.112f) { - encodedAmp = (int)Math.Round(4 * Math.Log2(rawAmp * 110f)); + encodedAmp = 4 * Math.Log2(rawAmp * 110f); } else if (rawAmp is >= 0.112f and < 0.225f) { - encodedAmp = (int)Math.Round(16 * Math.Log2(rawAmp * 17f)); + encodedAmp = 16 * Math.Log2(rawAmp * 17f); } else if (rawAmp is >= 0.225f and <= 1f) { - encodedAmp = (int)Math.Round(32 * Math.Log2(rawAmp * 8.7f)); + encodedAmp = 32 * Math.Log2(rawAmp * 8.7f); } - return encodedAmp * 2; + return (int) Math.Round(encodedAmp * 2); } public bool HdRumble(VibrationValue left, VibrationValue right) { - WriteHdRumble(EncodeLowFreq(left.FrequencyLow), + return WriteHdRumble(EncodeLowFreq(left.FrequencyLow), EncodeLowAmp(left.AmplitudeLow), EncodeHighFreq(left.FrequencyHigh), EncodeHighAmp(left.AmplitudeHigh), @@ -140,7 +151,34 @@ namespace Ryujinx.Input.SDL3 EncodeLowAmp(right.AmplitudeLow), EncodeHighFreq(right.FrequencyHigh), EncodeHighAmp(right.AmplitudeHigh)); - return true; + } + + private int SendHDRumble(byte* data, nuint length) + { + int result = 0; + ulong currentTicks = SDL_GetTicks(); + + // Ditch rumble if we haven't hit the poll-rate yet. + // TODO: figure out a better way to do this + // While the polling check makes the rumble accurate, it also causes it to miss signals. + if ((currentTicks - _lastWriteTicks) < 8) // https://docs.handheldlegend.com/s/progcc-3/doc/lag-comparison-aAR1mV3JLX + { + return result; + } + + SDL_LockJoysticks(); + { + // Fun fact: Mario Kart 8 Deluxe sends rumble packets + // where the amplitude is zero, but the frequency isn't. + result = SDL_hid_write(_hidHandle, data, length); + if (result >= 0) + { + _lastWriteTicks = currentTicks; + } + } + SDL_UnlockJoysticks(); + + return result; } public void Dispose() @@ -148,4 +186,18 @@ namespace Ryujinx.Input.SDL3 SDL_hid_close(_hidHandle); } } + + public enum HDRumbleSupported : ushort + { + JoyConLeft = 0x2006, + JoyConRight = 0x2007, + JoyconPair = 0x2008, + ProController = 0x2009, + JoyconGrip = 0x200e, + Joycon2Right = 0x2066, + Joycon2Left = 0x2067, + Joycon2Pair = 0x2068, + Switch2ProController = 0x2069, + GamecubeController = 0x2073 + } } diff --git a/src/Ryujinx.Input.SDL3/SDL3Gamepad.cs b/src/Ryujinx.Input.SDL3/SDL3Gamepad.cs index c23b64304..57f2940c8 100644 --- a/src/Ryujinx.Input.SDL3/SDL3Gamepad.cs +++ b/src/Ryujinx.Input.SDL3/SDL3Gamepad.cs @@ -197,10 +197,12 @@ namespace Ryujinx.Input.SDL3 return _hdRumble?.HdRumble(left, right) ?? false; } - public void Rumble(float lowFrequency, float highFrequency, uint durationMs) + public bool Rumble(float lowFrequency, float highFrequency, uint durationMs) { if ((Features & GamepadFeaturesFlag.Rumble) == 0) - return; + { + return false; + } ushort lowFrequencyRaw = (ushort)(lowFrequency * ushort.MaxValue); ushort highFrequencyRaw = (ushort)(highFrequency * ushort.MaxValue); @@ -219,6 +221,15 @@ namespace Ryujinx.Input.SDL3 if (!SDL_RumbleGamepad(_gamepadHandle, lowFrequencyRaw, highFrequencyRaw, durationMs)) Logger.Error?.Print(LogClass.Hid, "Rumble is not supported on this game controller."); } + + if (!String.IsNullOrEmpty(SDL_GetError())) + { + Logger.Error?.PrintMsg(LogClass.Hid, SDL_GetError()); + SDL_ClearError(); + return false; + } + + return true; } public Vector3 GetMotionData(MotionInputId inputId) diff --git a/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs b/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs index 5d779518d..e9f11d713 100644 --- a/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs +++ b/src/Ryujinx.Input.SDL3/SDL3JoyCon.cs @@ -162,7 +162,7 @@ namespace Ryujinx.Input.SDL3 public void SetTriggerThreshold(float triggerThreshold) { - + // No operations } public bool HDRumble(VibrationValue left, VibrationValue right) @@ -170,10 +170,12 @@ namespace Ryujinx.Input.SDL3 return _hdRumble?.HdRumble(left, right) ?? false; } - public void Rumble(float lowFrequency, float highFrequency, uint durationMs) + public bool Rumble(float lowFrequency, float highFrequency, uint durationMs) { if ((Features & GamepadFeaturesFlag.Rumble) == 0) - return; + { + return false; + } ushort lowFrequencyRaw = (ushort)(lowFrequency * ushort.MaxValue); ushort highFrequencyRaw = (ushort)(highFrequency * ushort.MaxValue); @@ -192,6 +194,15 @@ namespace Ryujinx.Input.SDL3 if (!SDL_RumbleGamepad(_gamepadHandle, lowFrequencyRaw, highFrequencyRaw, durationMs)) Logger.Error?.Print(LogClass.Hid, "Rumble is not supported on this game controller."); } + + if (!String.IsNullOrEmpty(SDL_GetError())) + { + Logger.Error?.PrintMsg(LogClass.Hid, SDL_GetError()); + SDL_ClearError(); + return false; + } + + return true; } public Vector3 GetMotionData(MotionInputId inputId) diff --git a/src/Ryujinx.Input.SDL3/SDL3JoyConPair.cs b/src/Ryujinx.Input.SDL3/SDL3JoyConPair.cs index 14352e5a4..6114674ad 100644 --- a/src/Ryujinx.Input.SDL3/SDL3JoyConPair.cs +++ b/src/Ryujinx.Input.SDL3/SDL3JoyConPair.cs @@ -1,4 +1,7 @@ +using Gommon; using Ryujinx.Common.Configuration.Hid; +using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Services.Hid; using System.Collections.Generic; using System.Linq; using System.Numerics; @@ -61,7 +64,14 @@ namespace Ryujinx.Input.SDL3 return left.IsPressed(inputId) || right.IsPressed(inputId); } - public void Rumble(float lowFrequency, float highFrequency, uint durationMs) + public bool HDRumble(VibrationValue left, VibrationValue right) + { + // return _hdRumble?.HdRumble(left, right) ?? false; + // TODO: Track rumble and motion on both controllers + return false; + } + + public bool Rumble(float lowFrequency, float highFrequency, uint durationMs) { if (lowFrequency != 0) { @@ -78,6 +88,15 @@ namespace Ryujinx.Input.SDL3 left.Rumble(0, 0, durationMs); right.Rumble(0, 0, durationMs); } + + if (!SDL_GetError().IsNullOrEmpty()) + { + Logger.Error?.PrintMsg(LogClass.Hid, SDL_GetError()); + SDL_ClearError(); + return false; + } + + return true; } public void SetConfiguration(InputConfig configuration) diff --git a/src/Ryujinx.Input.SDL3/SDL3Keyboard.cs b/src/Ryujinx.Input.SDL3/SDL3Keyboard.cs index f5da11a19..8b179f43f 100644 --- a/src/Ryujinx.Input.SDL3/SDL3Keyboard.cs +++ b/src/Ryujinx.Input.SDL3/SDL3Keyboard.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid.Keyboard; using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Services.Hid; using System; using System.Collections.Generic; using System.Numerics; @@ -396,9 +397,14 @@ namespace Ryujinx.Input.SDL3 // No operations } - public void Rumble(float lowFrequency, float highFrequency, uint durationMs) + public bool HDRumble(VibrationValue left, VibrationValue right) { - // No operations + return false; + } + + public bool Rumble(float lowFrequency, float highFrequency, uint durationMs) + { + return false; } public Vector3 GetMotionData(MotionInputId inputId) diff --git a/src/Ryujinx.Input.SDL3/SDL3Mouse.cs b/src/Ryujinx.Input.SDL3/SDL3Mouse.cs index 9fdeb36ab..289a60d85 100644 --- a/src/Ryujinx.Input.SDL3/SDL3Mouse.cs +++ b/src/Ryujinx.Input.SDL3/SDL3Mouse.cs @@ -1,5 +1,6 @@ using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Services.Hid; using System; using System.Drawing; using System.Numerics; @@ -67,7 +68,12 @@ namespace Ryujinx.Input.SDL3 throw new NotImplementedException(); } - public void Rumble(float lowFrequency, float highFrequency, uint durationMs) + public bool HDRumble(VibrationValue left, VibrationValue right) + { + throw new NotImplementedException(); + } + + public bool Rumble(float lowFrequency, float highFrequency, uint durationMs) { throw new NotImplementedException(); } diff --git a/src/Ryujinx.Input/HLE/NpadController.cs b/src/Ryujinx.Input/HLE/NpadController.cs index a46ff8daf..85ca5ffcb 100644 --- a/src/Ryujinx.Input/HLE/NpadController.cs +++ b/src/Ryujinx.Input/HLE/NpadController.cs @@ -5,7 +5,6 @@ using Ryujinx.Common.Configuration.Hid.Controller.Motion; using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Services.Hid; using System; -using System.Buffers; using System.Collections.Concurrent; using System.Numerics; using System.Runtime.CompilerServices; @@ -555,34 +554,37 @@ namespace Ryujinx.Input.HLE { if (queue.TryDequeue(out (VibrationValue, VibrationValue) dualVibrationValue)) { - if (_config is StandardControllerInputConfig controllerConfig && controllerConfig.Rumble.EnableRumble) + if (_config is not StandardControllerInputConfig controllerConfig || + !controllerConfig.Rumble.EnableRumble) { - VibrationValue leftVibrationValue = dualVibrationValue.Item1; - VibrationValue rightVibrationValue = dualVibrationValue.Item2; - - float low = Math.Min(1f, (float)((rightVibrationValue.AmplitudeLow * 0.85 + rightVibrationValue.AmplitudeHigh * 0.15) * controllerConfig.Rumble.StrongRumble)); - float high = Math.Min(1f, (float)((leftVibrationValue.AmplitudeLow * 0.15 + leftVibrationValue.AmplitudeHigh * 0.85) * controllerConfig.Rumble.WeakRumble)); - - leftVibrationValue.AmplitudeLow *= controllerConfig.Rumble.WeakRumble; - leftVibrationValue.AmplitudeHigh *= controllerConfig.Rumble.StrongRumble; - rightVibrationValue.AmplitudeLow *= controllerConfig.Rumble.WeakRumble; - rightVibrationValue.AmplitudeHigh *= controllerConfig.Rumble.StrongRumble; - - if (_gamepad?.HDRumble(leftVibrationValue, rightVibrationValue) == false) - { - _gamepad?.Rumble(low, high, uint.MaxValue); - } - - Logger.Debug?.Print(LogClass.Hid, $"Effect for {controllerConfig.PlayerIndex} " + - $"L.low.amp={leftVibrationValue.AmplitudeLow}, " + - $"L.high.amp={leftVibrationValue.AmplitudeHigh}, " + - $"L.low.freq={leftVibrationValue.FrequencyLow}, " + - $"L.high.freq={leftVibrationValue.FrequencyHigh}, " + - $"R.low.amp={rightVibrationValue.AmplitudeLow}, " + - $"R.high.amp={rightVibrationValue.AmplitudeHigh} " + - $"R.low.freq={rightVibrationValue.FrequencyLow}, " + - $"R.high.freq={rightVibrationValue.FrequencyHigh}"); + return; } + + VibrationValue leftVibrationValue = dualVibrationValue.Item1; + VibrationValue rightVibrationValue = dualVibrationValue.Item2; + + leftVibrationValue.AmplitudeLow *= controllerConfig.Rumble.WeakRumble; + leftVibrationValue.AmplitudeHigh *= controllerConfig.Rumble.StrongRumble; + rightVibrationValue.AmplitudeLow *= controllerConfig.Rumble.WeakRumble; + rightVibrationValue.AmplitudeHigh *= controllerConfig.Rumble.StrongRumble; + + if (!controllerConfig.Rumble.UseHDRumble || _gamepad?.HDRumble(leftVibrationValue, rightVibrationValue) == false) + { + float low = Math.Min(1f, (float)((rightVibrationValue.AmplitudeLow * 0.85 + rightVibrationValue.AmplitudeHigh * 0.15))); + float high = Math.Min(1f, (float)((leftVibrationValue.AmplitudeLow * 0.15 + leftVibrationValue.AmplitudeHigh * 0.85))); + _gamepad?.Rumble(low, high, 0xFFFFFFFF); + } + + Logger.Debug?.Print(LogClass.Hid, $"Effect for {controllerConfig.PlayerIndex} " + + // Value=value/multiplier * multiplier (result) + $"L.low.amp={leftVibrationValue.AmplitudeLow / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.AmplitudeLow}), " + + $"L.high.amp={leftVibrationValue.AmplitudeHigh / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.AmplitudeHigh}), " + + $"L.low.freq={leftVibrationValue.FrequencyLow / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.FrequencyLow}), " + + $"L.high.freq={leftVibrationValue.FrequencyHigh / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.FrequencyHigh}), " + + $"R.low.amp={rightVibrationValue.AmplitudeLow / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.AmplitudeLow}), " + + $"R.high.amp={rightVibrationValue.AmplitudeHigh / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.AmplitudeHigh}), " + + $"R.low.freq={rightVibrationValue.FrequencyLow / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.FrequencyLow}), " + + $"R.high.freq={rightVibrationValue.FrequencyHigh / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.FrequencyHigh})"); } } } diff --git a/src/Ryujinx.Input/IGamepad.cs b/src/Ryujinx.Input/IGamepad.cs index d45ac0444..587fd53c0 100644 --- a/src/Ryujinx.Input/IGamepad.cs +++ b/src/Ryujinx.Input/IGamepad.cs @@ -80,10 +80,7 @@ namespace Ryujinx.Input /// /// The vibration data for the left side /// The vibration data for the right side - bool HDRumble(VibrationValue left, VibrationValue right) - { - return false; - } + bool HDRumble(VibrationValue left, VibrationValue right); /// /// Starts a rumble effect on the gamepad. @@ -91,10 +88,10 @@ namespace Ryujinx.Input /// The intensity of the low frequency from 0.0f to 1.0f /// The intensity of the high frequency from 0.0f to 1.0f /// The duration of the rumble effect in milliseconds. - void Rumble(float lowFrequency, float highFrequency, uint durationMs); + bool Rumble(float lowFrequency, float highFrequency, uint durationMs); /// - /// Get a snaphost of the state of the gamepad that is remapped with the informations from the set via . + /// Get a snaphost of the state of the gamepad that is remapped with the information from the set via . /// /// A remapped snaphost of the state of the gamepad. GamepadStateSnapshot GetMappedStateSnapshot(); diff --git a/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs b/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs index af61b7b63..3574c3061 100644 --- a/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs +++ b/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs @@ -221,6 +221,7 @@ namespace Ryujinx.Headless StrongRumble = 1f, WeakRumble = 1f, EnableRumble = false, + UseHDRumble = true }, }; } diff --git a/src/Ryujinx/Input/AvaloniaKeyboard.cs b/src/Ryujinx/Input/AvaloniaKeyboard.cs index 031d8b033..704a15ba7 100644 --- a/src/Ryujinx/Input/AvaloniaKeyboard.cs +++ b/src/Ryujinx/Input/AvaloniaKeyboard.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid.Keyboard; using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Services.Hid; using Ryujinx.Input; using System; using System.Collections.Generic; @@ -149,9 +150,20 @@ namespace Ryujinx.Ava.Input Logger.Info?.Print(LogClass.UI, "SetLed called on an AvaloniaKeyboard"); } - public void SetTriggerThreshold(float triggerThreshold) { } + public void SetTriggerThreshold(float triggerThreshold) + { + // No operations + } - public void Rumble(float lowFrequency, float highFrequency, uint durationMs) { } + public bool HDRumble(VibrationValue left, VibrationValue right) + { + return false; + } + + public bool Rumble(float lowFrequency, float highFrequency, uint durationMs) + { + return false; + } public Vector3 GetMotionData(MotionInputId inputId) => Vector3.Zero; diff --git a/src/Ryujinx/Input/AvaloniaMouse.cs b/src/Ryujinx/Input/AvaloniaMouse.cs index 52a341a01..8c449b9ee 100644 --- a/src/Ryujinx/Input/AvaloniaMouse.cs +++ b/src/Ryujinx/Input/AvaloniaMouse.cs @@ -1,5 +1,6 @@ using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Services.Hid; using Ryujinx.Input; using System; using System.Drawing; @@ -64,8 +65,13 @@ namespace Ryujinx.Ava.Input { throw new NotImplementedException(); } + + public bool HDRumble(VibrationValue left, VibrationValue right) + { + throw new NotImplementedException(); + } - public void Rumble(float lowFrequency, float highFrequency, uint durationMs) + public bool Rumble(float lowFrequency, float highFrequency, uint durationMs) { throw new NotImplementedException(); } diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs index 0b451eacb..1fe98ee69 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs @@ -17,7 +17,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// /// The current version of the file format /// - public const int CurrentVersion = 72; + public const int CurrentVersion = 73; /// /// Version of the configuration file format diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs index 90a045a67..728321985 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs @@ -333,6 +333,7 @@ namespace Ryujinx.Ava.Systems.Configuration EnableRumble = false, StrongRumble = 1f, WeakRumble = 1f, + UseHDRumble = true }; } } diff --git a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs index 0eeef45f5..2a076f525 100644 --- a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs +++ b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs @@ -20,6 +20,7 @@ namespace Ryujinx.Ava.UI.Models.Input public float WeakRumble { get; set; } public float StrongRumble { get; set; } + public bool UseHDRumble { get; set; } public string Id { get; set; } @@ -236,6 +237,7 @@ namespace Ryujinx.Ava.UI.Models.Input EnableRumble = controllerInput.Rumble.EnableRumble; WeakRumble = controllerInput.Rumble.WeakRumble; StrongRumble = controllerInput.Rumble.StrongRumble; + UseHDRumble = controllerInput.Rumble.UseHDRumble; } if (controllerInput.Led != null) @@ -307,6 +309,7 @@ namespace Ryujinx.Ava.UI.Models.Input EnableRumble = EnableRumble, WeakRumble = WeakRumble, StrongRumble = StrongRumble, + UseHDRumble = UseHDRumble, }, Led = new LedConfigController { diff --git a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs index 51229af72..68559d6c1 100644 --- a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs @@ -789,6 +789,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input StrongRumble = 1f, WeakRumble = 1f, EnableRumble = false, + UseHDRumble = true }, }; } diff --git a/src/Ryujinx/UI/ViewModels/Input/RumbleInputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/RumbleInputViewModel.cs index e2323f567..74e0cd289 100644 --- a/src/Ryujinx/UI/ViewModels/Input/RumbleInputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/RumbleInputViewModel.cs @@ -9,5 +9,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input [ObservableProperty] public partial float WeakRumble { get; set; } + + [ObservableProperty] + public partial bool EnableHDRumble { get; set; } } } diff --git a/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml b/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml index 98489aab0..49eb1a717 100644 --- a/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml +++ b/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml @@ -53,6 +53,15 @@ Margin="5,0" Text="{Binding WeakRumble, StringFormat=\{0:0.00\}}" /> + + + diff --git a/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml.cs index 347d011d5..655bdf591 100644 --- a/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml.cs @@ -22,6 +22,7 @@ namespace Ryujinx.Ava.UI.Views.Input { StrongRumble = config.StrongRumble, WeakRumble = config.WeakRumble, + EnableHDRumble = config.UseHDRumble }; InitializeComponent(); @@ -45,6 +46,7 @@ namespace Ryujinx.Ava.UI.Views.Input GamepadInputConfig config = viewModel.Config; config.StrongRumble = content.ViewModel.StrongRumble; config.WeakRumble = content.ViewModel.WeakRumble; + config.UseHDRumble = content.ViewModel.EnableHDRumble; }; await contentDialog.ShowAsync();