diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs
index e6fe74d53..fbb19767c 100644
--- a/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs
+++ b/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs
@@ -78,5 +78,10 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
/// Controller Rumble Settings
///
public RumbleConfigController Rumble { get; set; }
+
+ ///
+ /// Controller LED Settings
+ ///
+ public LedConfigController Led { get; set; }
}
}
diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs
new file mode 100644
index 000000000..21727d62e
--- /dev/null
+++ b/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs
@@ -0,0 +1,15 @@
+namespace Ryujinx.Common.Configuration.Hid.Controller
+{
+ public class LedConfigController
+ {
+ ///
+ /// Packed RGB int of the color
+ ///
+ public uint LedColor { get; set; }
+
+ ///
+ /// Enable LED color changing by the emulator
+ ///
+ public bool EnableLed { get; set; }
+ }
+}
diff --git a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs
index 12bfab4bb..ed22c3661 100644
--- a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs
+++ b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs
@@ -1,6 +1,7 @@
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Logging;
+using SDL2;
using System;
using System.Collections.Generic;
using System.Numerics;
@@ -118,6 +119,11 @@ namespace Ryujinx.Input.SDL2
result |= GamepadFeaturesFlag.Rumble;
}
+ if (SDL_GameControllerHasLED(_gamepadHandle) == SDL_bool.SDL_TRUE)
+ {
+ result |= GamepadFeaturesFlag.Led;
+ }
+
return result;
}
diff --git a/src/Ryujinx.Input/GamepadFeaturesFlag.cs b/src/Ryujinx.Input/GamepadFeaturesFlag.cs
index 69ec23686..52e8519d1 100644
--- a/src/Ryujinx.Input/GamepadFeaturesFlag.cs
+++ b/src/Ryujinx.Input/GamepadFeaturesFlag.cs
@@ -24,5 +24,10 @@ namespace Ryujinx.Input
/// Also named sixaxis
///
Motion,
+
+ ///
+ /// The LED on the back of modern PlayStation controllers (DualSense & DualShock 4).
+ ///
+ Led,
}
}
diff --git a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs
index 833670bdc..ea7dd34c3 100644
--- a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs
+++ b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs
@@ -1,3 +1,4 @@
+using Avalonia.Media;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller;
@@ -387,6 +388,30 @@ namespace Ryujinx.Ava.UI.Models.Input
}
}
+ private bool _enableLedChanging;
+
+ public bool EnableLedChanging
+ {
+ get => _enableLedChanging;
+ set
+ {
+ _enableLedChanging = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private Color _ledColor;
+
+ public Color LedColor
+ {
+ get => _ledColor;
+ set
+ {
+ _ledColor = value;
+ OnPropertyChanged();
+ }
+ }
+
private bool _enableMotion;
public bool EnableMotion
{
@@ -483,12 +508,23 @@ namespace Ryujinx.Ava.UI.Models.Input
WeakRumble = controllerInput.Rumble.WeakRumble;
StrongRumble = controllerInput.Rumble.StrongRumble;
}
+
+ if (controllerInput.Led != null)
+ {
+ EnableLedChanging = controllerInput.Led.EnableLed;
+ uint rawColor = controllerInput.Led.LedColor;
+ byte alpha = (byte)(rawColor >> 24);
+ byte red = (byte)(rawColor >> 16);
+ byte green = (byte)(rawColor >> 8);
+ byte blue = (byte)(rawColor % 256);
+ LedColor = new Color(alpha, red, green, blue);
+ }
}
}
public InputConfig GetConfig()
{
- var config = new StandardControllerInputConfig
+ StandardControllerInputConfig config = new()
{
Id = Id,
Backend = InputBackendType.GamepadSDL2,
@@ -540,6 +576,11 @@ namespace Ryujinx.Ava.UI.Models.Input
WeakRumble = WeakRumble,
StrongRumble = StrongRumble,
},
+ Led = new LedConfigController
+ {
+ EnableLed = EnableLedChanging,
+ LedColor = LedColor.ToUInt32()
+ },
Version = InputConfig.CurrentVersion,
DeadzoneLeft = DeadzoneLeft,
DeadzoneRight = DeadzoneRight,
diff --git a/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs
index 482fe2981..0380ef598 100644
--- a/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs
@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
[ObservableProperty] private SvgImage _image;
- public readonly InputViewModel ParentModel;
+ public InputViewModel ParentModel { get; }
public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config)
{
diff --git a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs
index 05f479d9f..7fda4e2d0 100644
--- a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs
@@ -68,6 +68,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public bool IsKeyboard => !IsController;
public bool IsRight { get; set; }
public bool IsLeft { get; set; }
+
+ public bool HasLed => SelectedGamepad.Features.HasFlag(GamepadFeaturesFlag.Led);
public bool IsModified { get; set; }
public event Action NotifyChangesEvent;
diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml
index 7daf23eb6..73f74e36f 100644
--- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml
+++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml
@@ -4,6 +4,7 @@
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
@@ -486,6 +487,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs
index ee84fbc37..52a6d51b9 100644
--- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs
+++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs
@@ -4,14 +4,11 @@ using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
-using DiscordRPC;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels.Input;
using Ryujinx.Common.Configuration.Hid.Controller;
-using Ryujinx.Common.Logging;
using Ryujinx.Input;
using Ryujinx.Input.Assigner;
-using System;
using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
namespace Ryujinx.Ava.UI.Views.Input
diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs
index 6d3570850..4bbc5e622 100644
--- a/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs
+++ b/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs
@@ -17,7 +17,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
///
/// The current version of the file format
///
- public const int CurrentVersion = 60;
+ public const int CurrentVersion = 61;
///
/// Version of the configuration file format
diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs
index 943aab513..521780e94 100644
--- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs
+++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs
@@ -263,15 +263,12 @@ namespace Ryujinx.Ava.Utilities.Configuration
}),
(30, static cff =>
{
- foreach (InputConfig config in cff.InputConfig)
+ foreach (StandardControllerInputConfig config in cff.InputConfig.OfType())
{
- if (config is StandardControllerInputConfig controllerConfig)
+ config.Rumble = new RumbleConfigController
{
- controllerConfig.Rumble = new RumbleConfigController
- {
- EnableRumble = false, StrongRumble = 1f, WeakRumble = 1f,
- };
- }
+ EnableRumble = false, StrongRumble = 1f, WeakRumble = 1f,
+ };
}
}),
(31, static cff => cff.BackendThreading = BackendThreading.Auto),
@@ -416,7 +413,18 @@ namespace Ryujinx.Ava.Utilities.Configuration
// so as a compromise users who want to use it will simply need to re-enable it once after updating.
cff.IgnoreApplet = false;
}),
- (60, static cff => cff.StartNoUI = false)
+ (60, static cff => cff.StartNoUI = false),
+ (61, static cff =>
+ {
+ foreach (StandardControllerInputConfig config in cff.InputConfig.OfType())
+ {
+ config.Led = new LedConfigController
+ {
+ EnableLed = false,
+ LedColor = 328189
+ };
+ }
+ })
);
}
}