Compare commits

...

4 Commits

Author SHA1 Message Date
Daenorth
2ee6ba7411 Merge a076410d02 into 9c8055440e 2025-01-23 00:10:17 -06:00
Evan Husted
9c8055440e HLE: TryAdd firmware NCAs 2025-01-22 23:58:11 -06:00
Evan Husted
c03cd50fa3 UI: Add the ability to change a DualSense/DualShock 4's LED color.
Not functional yet. This is the UI & persistence side of #572.
2025-01-22 19:53:39 -06:00
Daenorth
a076410d02 Update TitleIDs.cs
Added some more titles to the RPC environment

-Brawlhalla
-Minecraft
-Risk
-Stardew Vallet
-Valkyria Chronicles 4
-Super bomberman R
-Arcade archives Super mario bros
-Divinity Original sin 2 DE
-Monopoly
-titan Quest
2025-01-22 19:11:14 +01:00
13 changed files with 137 additions and 18 deletions

View File

@@ -78,5 +78,10 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
/// Controller Rumble Settings
/// </summary>
public RumbleConfigController Rumble { get; set; }
/// <summary>
/// Controller LED Settings
/// </summary>
public LedConfigController Led { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
namespace Ryujinx.Common.Configuration.Hid.Controller
{
public class LedConfigController
{
/// <summary>
/// Packed RGB int of the color
/// </summary>
public uint LedColor { get; set; }
/// <summary>
/// Enable LED color changing by the emulator
/// </summary>
public bool EnableLed { get; set; }
}
}

View File

@@ -104,6 +104,7 @@ namespace Ryujinx.Common
"0100b04011742000", // Monster Hunter Rise
//Mario Franchise
"010021d00812a000", // Arcade Archives VS. SUPER MARIO BROS.
"01006d0017f7a000", // Mario & Luigi: Brothership
"010003000e146000", // Mario & Sonic at the Olympic Games Tokyo 2020
"010067300059a000", // Mario + Rabbids: Kingdom Battle
@@ -211,32 +212,41 @@ namespace Ryujinx.Common
//Misc Games
"010056e00853a000", // A Hat in Time
"0100fd1014726000", // Baldurs Gate: Dark Alliance
"0100c6800b934000", // Brawlhalla
"0100dbf01000a000", // Burnout Paradise Remastered
"0100744001588000", // Cars 3: Driven to Win
"0100b41013c82000", // Cruis'n Blast
"010085900337e000", // Death Squared
"01001b300b9be000", // Diablo III: Eternal Collection
"010027400cdc6000", // Divinity Original 2 - Definitive Edition
"01008c8012920000", // Dying Light Platinum Edition
"01001cc01b2d4000", // Goat Simulator 3
"01003620068ea000", // Hand of Fate 2
"010085500130a000", // Lego City: Undercover
"010073c01af34000", // LEGO Horizon Adventures
"0100d71004694000", // Minecraft
"01007430037f6000", // Monopoly
"0100853015e86000", // No Man's Sky
"01007bb017812000", // Portal
"0100abd01785c000", // Portal 2
"01008e200c5c2000", // Muse Dash
"01007820196a6000", // Red Dead Redemption
"0100e8300a67a000", // Risk
"01002f7013224000", // Rune Factory 5
"01008d100d43e000", // Saints Row IV
"0100de600beee000", // Saints Row: The Third - The Full Package
"01001180021fa000", // Shovel Knight: Specter of Torment
"0100e65002bb8000", // Stardew Valley
"0100d7a01b7a2000", // Star Wars: Bounty Hunter
"0100800015926000", // Suika Game
"01007ad00013e000", // Super Bomberman R
"0100e46006708000", // Terraria
"0100605008268000", // Titan Quest
"01000a10041ea000", // The Elder Scrolls V: Skyrim
"010057a01e4d4000", // TSUKIHIME -A piece of blue glass moon-
"010080b00ad66000", // Undertale
"010069401adb8000", // Unicorn Overlord
"01005c600ac68000", // Valkyria Chronicles 4
"0100534009ff2000", // Yonder - The cloud catcher chronicles
];
}

View File

@@ -710,9 +710,8 @@ namespace Ryujinx.HLE.FileSystem
{
updateNcasItem.Add((nca.Header.ContentType, entry.FullName));
}
else
else if (updateNcas.TryAdd(nca.Header.TitleId, new List<(NcaContentType, string)>()))
{
updateNcas.Add(nca.Header.TitleId, new List<(NcaContentType, string)>());
updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullName));
}
}
@@ -898,9 +897,8 @@ namespace Ryujinx.HLE.FileSystem
{
updateNcasItem.Add((nca.Header.ContentType, entry.FullPath));
}
else
else if (updateNcas.TryAdd(nca.Header.TitleId, new List<(NcaContentType, string)>()))
{
updateNcas.Add(nca.Header.TitleId, new List<(NcaContentType, string)>());
updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullPath));
}

View File

@@ -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;
}

View File

@@ -24,5 +24,10 @@ namespace Ryujinx.Input
/// <remarks>Also named sixaxis</remarks>
/// </summary>
Motion,
/// <summary>
/// The LED on the back of modern PlayStation controllers (DualSense &amp; DualShock 4).
/// </summary>
Led,
}
}

View File

@@ -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,

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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 @@
</Button>
</Grid>
</Border>
<Border
BorderBrush="{DynamicResource ThemeControlBorderColor}"
BorderThickness="1"
CornerRadius="5"
HorizontalAlignment="Stretch"
Margin="0,-1,0,0">
<Grid IsVisible="{Binding ParentModel.HasLed}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox
Margin="10"
MinWidth="0"
Grid.Column="0"
IsChecked="{Binding Config.EnableLedChanging, Mode=TwoWay}">
<TextBlock Text="Custom LED color" />
</CheckBox>
<ui:ColorPickerButton
Grid.Column="1"
Margin="10"
IsMoreButtonVisible="False"
UseColorPalette="False"
UseColorTriangle="False"
UseColorWheel="False"
ShowAcceptDismissButtons="False"
IsAlphaEnabled="False"
Color="{Binding Config.LedColor, Mode=TwoWay}">
</ui:ColorPickerButton>
</Grid>
</Border>
</StackPanel>
</StackPanel>
<!-- Right Controls -->

View File

@@ -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

View File

@@ -17,7 +17,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// <summary>
/// The current version of the file format
/// </summary>
public const int CurrentVersion = 60;
public const int CurrentVersion = 61;
/// <summary>
/// Version of the configuration file format

View File

@@ -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<StandardControllerInputConfig>())
{
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<StandardControllerInputConfig>())
{
config.Led = new LedConfigController
{
EnableLed = false,
LedColor = 328189
};
}
})
);
}
}