Compare commits

...

12 Commits

Author SHA1 Message Date
Evan Husted
33079422fe misc: chore: code cleanups 2025-01-23 16:47:11 -06:00
Evan Husted
f81cb093fc misc: chore: Change references of GreemDev/Ryujinx to Ryubing/Ryujinx 2025-01-23 16:27:49 -06:00
Evan Husted
dc0c7a2912 infra: clarify how stable builds are made now 2025-01-23 16:27:25 -06:00
Evan Husted
1fbee5a584 infra: Metal label 2025-01-23 14:39:36 -06:00
Evan Husted
c140e9b23c UI: Localize LED color & hide it until it's functional
Also moved IgnoreApplet to the System config section object.
2025-01-23 00:48:42 -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
Evan Husted
069f630776 docs: compat: boots: ENDER MAGNOLIA: Bloom in the Mist 2025-01-22 18:00:14 -06:00
Evan Husted
13d411e4de misc: chore: also ToLower the titleID for the OpenShaderDirectory button 2025-01-22 08:54:39 -06:00
Evan Husted
9f53b07491 misc: chore: Fix shader cache & CPU cache being in different folders on non-Windows
fixes #565
2025-01-22 08:52:21 -06:00
Evan Husted
cd8113dadf misc: chore: Collapse adding a game/autoload dir into a single reusable method. 2025-01-21 18:59:56 -06:00
Evan Husted
9089c4ffe5 misc: chore: Multi/Single file/folder picker extensions (for convenience)
The result of these extensions is an empty Optional when the user hits Cancel on the shown file picker.
2025-01-21 18:59:19 -06:00
36 changed files with 297 additions and 118 deletions

4
.github/labeler.yml vendored
View File

@@ -18,6 +18,10 @@ gpu:
- changed-files: - changed-files:
- any-glob-to-any-file: ['src/Ryujinx.Graphics.Vulkan/**', 'src/Spv.Generator/**'] - any-glob-to-any-file: ['src/Ryujinx.Graphics.Vulkan/**', 'src/Spv.Generator/**']
'graphics-backend:metal':
- changed-files:
- any-glob-to-any-file: ['src/Ryujinx.Graphics.Metal/**', 'src/Ryujinx.Graphics.Metal.SharpMetalExtensions/**']
gui: gui:
- changed-files: - changed-files:
- any-glob-to-any-file: ['src/Ryujinx/**', 'src/Ryujinx.UI.Common/**', 'src/Ryujinx.UI.LocaleGenerator/**'] - any-glob-to-any-file: ['src/Ryujinx/**', 'src/Ryujinx.UI.Common/**', 'src/Ryujinx.UI.LocaleGenerator/**']

View File

@@ -54,12 +54,13 @@ failing to meet this requirement may result in a poor gameplay experience or une
## Latest build ## Latest build
Stable builds are made every so often onto a separate "release" branch that then gets put into the releases you know and love. Stable builds are made every so often, based on the `master` branch, that then gets put into the releases you know and love.
These stable builds exist so that the end user can get a more **enjoyable and stable experience**. These stable builds exist so that the end user can get a more **enjoyable and stable experience**.
They are released every month or so, to ensure consistent updates, while not being an annoying amount of individual updates to download over the course of that month.
You can find the latest stable release [here](https://github.com/GreemDev/Ryujinx/releases/latest). You can find the latest stable release [here](https://github.com/GreemDev/Ryujinx/releases/latest).
Canary builds are compiled automatically for each commit on the master branch. Canary builds are compiled automatically for each commit on the `master` branch.
While we strive to ensure optimal stability and performance prior to pushing an update, these builds **may be unstable or completely broken**. While we strive to ensure optimal stability and performance prior to pushing an update, these builds **may be unstable or completely broken**.
These canary builds are only recommended for experienced users. These canary builds are only recommended for experienced users.
@@ -109,7 +110,7 @@ If you are planning to contribute or just want to learn more about this project
- **Configuration** - **Configuration**
The emulator has settings for enabling or disabling some logging, remapping controllers, and more. The emulator has settings for enabling or disabling some logging, remapping controllers, and more.
You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the user folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI. You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the Ryujinx data folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
## License ## License

View File

@@ -1070,6 +1070,7 @@
010017B0102A8000,"Emma: Lost in Memories",nvdec,playable,2021-01-28 16:19:10 010017B0102A8000,"Emma: Lost in Memories",nvdec,playable,2021-01-28 16:19:10
010068300E08E000,"Enchanted in the Moonlight - Kiryu, Chikage & Yukinojo -",gpu;nvdec,ingame,2022-11-20 16:18:45 010068300E08E000,"Enchanted in the Moonlight - Kiryu, Chikage & Yukinojo -",gpu;nvdec,ingame,2022-11-20 16:18:45
01007A4008486000,"Enchanting Mahjong Match",gpu,ingame,2020-04-17 22:01:31 01007A4008486000,"Enchanting Mahjong Match",gpu,ingame,2020-04-17 22:01:31
0100EF901E552000,"ENDER MAGNOLIA: Bloom in the Mist",deadlock,boots,2025-01-22 17:59:00
01004F3011F92000,"Endless Fables: Dark Moor",gpu;nvdec,ingame,2021-03-07 15:31:03 01004F3011F92000,"Endless Fables: Dark Moor",gpu;nvdec,ingame,2021-03-07 15:31:03
010067B017588000,"Endless Ocean™ Luminous",services-horizon;crash,ingame,2024-05-30 02:05:57 010067B017588000,"Endless Ocean™ Luminous",services-horizon;crash,ingame,2024-05-30 02:05:57
0100B8700BD14000,"Energy Cycle Edge",services,ingame,2021-11-30 05:02:31 0100B8700BD14000,"Energy Cycle Edge",services,ingame,2021-11-30 05:02:31
1 title_id game_name labels status last_updated
1070 010017B0102A8000 Emma: Lost in Memories nvdec playable 2021-01-28 16:19:10
1071 010068300E08E000 Enchanted in the Moonlight - Kiryu, Chikage & Yukinojo - gpu;nvdec ingame 2022-11-20 16:18:45
1072 01007A4008486000 Enchanting Mahjong Match gpu ingame 2020-04-17 22:01:31
1073 0100EF901E552000 ENDER MAGNOLIA: Bloom in the Mist deadlock boots 2025-01-22 17:59:00
1074 01004F3011F92000 Endless Fables: Dark Moor gpu;nvdec ingame 2021-03-07 15:31:03
1075 010067B017588000 Endless Ocean™ Luminous services-horizon;crash ingame 2024-05-30 02:05:57
1076 0100B8700BD14000 Energy Cycle Edge services ingame 2021-11-30 05:02:31

View File

@@ -78,5 +78,10 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
/// Controller Rumble Settings /// Controller Rumble Settings
/// </summary> /// </summary>
public RumbleConfigController Rumble { get; set; } 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

@@ -8,7 +8,7 @@ namespace Ryujinx.Common
{ {
public static class TitleIDs public static class TitleIDs
{ {
public static ReactiveObject<Optional<string>> CurrentApplication { get; set; } = new(); public static ReactiveObject<Optional<string>> CurrentApplication { get; } = new();
public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend) public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend)
{ {

View File

@@ -118,7 +118,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
private static string GetDiskCachePath() private static string GetDiskCachePath()
{ {
return GraphicsConfig.EnableShaderCache && GraphicsConfig.TitleId != null return GraphicsConfig.EnableShaderCache && GraphicsConfig.TitleId != null
? Path.Combine(AppDataManager.GamesDirPath, GraphicsConfig.TitleId, "cache", "shader") ? Path.Combine(AppDataManager.GamesDirPath, GraphicsConfig.TitleId.ToLower(), "cache", "shader")
: null; : null;
} }

View File

@@ -710,9 +710,8 @@ namespace Ryujinx.HLE.FileSystem
{ {
updateNcasItem.Add((nca.Header.ContentType, entry.FullName)); 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)); 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)); 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)); updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullPath));
} }

View File

@@ -659,7 +659,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
if (string.IsNullOrWhiteSpace(filePath)) if (string.IsNullOrWhiteSpace(filePath))
{ {
throw new InvalidSystemResourceException("JIT (010000000000003B) system title not found! The JIT will not work, provide the system archive to fix this error. (See https://github.com/GreemDev/Ryujinx#requirements for more information)"); throw new InvalidSystemResourceException("JIT (010000000000003B) system title not found! The JIT will not work, provide the system archive to fix this error. (See https://github.com/Ryubing/Ryujinx#requirements for more information)");
} }
context.Device.LoadNca(filePath); context.Device.LoadNca(filePath);

View File

@@ -105,7 +105,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pl
titleName = "Unknown"; titleName = "Unknown";
} }
throw new InvalidSystemResourceException($"{titleName} ({fontTitle:x8}) system title not found! This font will not work, provide the system archive to fix this error. (See https://github.com/GreemDev/Ryujinx#requirements for more information)"); throw new InvalidSystemResourceException($"{titleName} ({fontTitle:x8}) system title not found! This font will not work, provide the system archive to fix this error. (See https://github.com/Ryubing/Ryujinx#requirements for more information)");
} }
} }
else else

View File

@@ -161,5 +161,20 @@ namespace Ryujinx.HLE
{ {
return 1000 / _frameRate[FrameTypeGame]; return 1000 / _frameRate[FrameTypeGame];
} }
public string FormatGameFrameRate()
{
double frameRate = GetGameFrameRate();
double frameTime = GetGameFrameTime();
return $"{frameRate:00.00} FPS ({frameTime:00.00}ms)";
}
public string FormatFifoPercent()
{
double fifoPercent = GetFifoPercent();
return $"FIFO: {fifoPercent:00.00}%";
}
} }
} }

View File

@@ -34,8 +34,8 @@ namespace Ryujinx.HLE
public int CpuCoresCount = 4; //Switch 1 has 4 cores public int CpuCoresCount = 4; //Switch 1 has 4 cores
public VSyncMode VSyncMode { get; set; } = VSyncMode.Switch; public VSyncMode VSyncMode { get; set; }
public bool CustomVSyncIntervalEnabled { get; set; } = false; public bool CustomVSyncIntervalEnabled { get; set; }
public int CustomVSyncInterval { get; set; } public int CustomVSyncInterval { get; set; }
public long TargetVSyncInterval { get; set; } = 60; public long TargetVSyncInterval { get; set; } = 60;

View File

@@ -1,6 +1,7 @@
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using SDL2;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics; using System.Numerics;
@@ -118,6 +119,11 @@ namespace Ryujinx.Input.SDL2
result |= GamepadFeaturesFlag.Rumble; result |= GamepadFeaturesFlag.Rumble;
} }
if (SDL_GameControllerHasLED(_gamepadHandle) == SDL_bool.SDL_TRUE)
{
result |= GamepadFeaturesFlag.Led;
}
return result; return result;
} }

View File

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

View File

@@ -1151,8 +1151,8 @@ namespace Ryujinx.Ava
LocaleManager.Instance[LocaleKeys.VolumeShort] + $": {(int)(Device.GetVolume() * 100)}%", LocaleManager.Instance[LocaleKeys.VolumeShort] + $": {(int)(Device.GetVolume() * 100)}%",
dockedMode, dockedMode,
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(), ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
$"{Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)", Device.Statistics.FormatGameFrameRate(),
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %", Device.Statistics.FormatFifoPercent(),
_displayCount)); _displayCount));
} }

View File

@@ -7622,6 +7622,31 @@
"zh_TW": "陀螺儀無感帶:" "zh_TW": "陀螺儀無感帶:"
} }
}, },
{
"ID": "ControllerSettingsLedColor",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Custom LED",
"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": "ControllerSettingsSave", "ID": "ControllerSettingsSave",
"Translations": { "Translations": {

View File

@@ -1,6 +1,6 @@
using Avalonia.Controls.Notifications;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using Gommon;
using LibHac; using LibHac;
using LibHac.Account; using LibHac.Account;
using LibHac.Common; using LibHac.Common;
@@ -15,6 +15,7 @@ using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.Configuration; using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common.Helper; using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
@@ -418,35 +419,27 @@ namespace Ryujinx.Ava.Common
public static async Task ExtractAoc(IStorageProvider storageProvider, string updateFilePath, string updateName) public static async Task ExtractAoc(IStorageProvider storageProvider, string updateFilePath, string updateName)
{ {
var result = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions Optional<IStorageFolder> result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions
{ {
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
AllowMultiple = false,
}); });
if (result.Count == 0) if (!result.HasValue) return;
{
return;
}
ExtractAoc(result[0].Path.LocalPath, updateFilePath, updateName); ExtractAoc(result.Value.Path.LocalPath, updateFilePath, updateName);
} }
public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0)
{ {
var result = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions Optional<IStorageFolder> result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions
{ {
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
AllowMultiple = false,
}); });
if (result.Count == 0) if (!result.HasValue) return;
{
return;
}
ExtractSection(result[0].Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex); ExtractSection(result.Value.Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex);
} }
public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token) public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token)

View File

@@ -149,7 +149,7 @@ namespace Ryujinx.Headless
IgnoreMissingServices = configurationState.System.IgnoreMissingServices; IgnoreMissingServices = configurationState.System.IgnoreMissingServices;
if (NeedsOverride(nameof(IgnoreControllerApplet))) if (NeedsOverride(nameof(IgnoreControllerApplet)))
IgnoreControllerApplet = configurationState.IgnoreApplet; IgnoreControllerApplet = configurationState.System.IgnoreApplet;
return; return;

View File

@@ -6,7 +6,6 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.ViewModels.Input;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities.Configuration; using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common; using Ryujinx.Common;
@@ -42,7 +41,7 @@ namespace Ryujinx.Ava.UI.Applet
bool okPressed = false; bool okPressed = false;
if (ConfigurationState.Instance.IgnoreApplet) if (ConfigurationState.Instance.System.IgnoreApplet)
return false; return false;
Dispatcher.UIThread.InvokeAsync(async () => Dispatcher.UIThread.InvokeAsync(async () =>

View File

@@ -251,7 +251,7 @@ namespace Ryujinx.Ava.UI.Controls
{ {
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
{ {
string shaderCacheDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "shader"); string shaderCacheDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString.ToLower(), "cache", "shader");
if (!Directory.Exists(shaderCacheDir)) if (!Directory.Exists(shaderCacheDir))
{ {

View File

@@ -1,3 +1,4 @@
using Avalonia.Media;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller; 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; private bool _enableMotion;
public bool EnableMotion public bool EnableMotion
{ {
@@ -483,12 +508,23 @@ namespace Ryujinx.Ava.UI.Models.Input
WeakRumble = controllerInput.Rumble.WeakRumble; WeakRumble = controllerInput.Rumble.WeakRumble;
StrongRumble = controllerInput.Rumble.StrongRumble; 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() public InputConfig GetConfig()
{ {
var config = new StandardControllerInputConfig StandardControllerInputConfig config = new()
{ {
Id = Id, Id = Id,
Backend = InputBackendType.GamepadSDL2, Backend = InputBackendType.GamepadSDL2,
@@ -540,6 +576,11 @@ namespace Ryujinx.Ava.UI.Models.Input
WeakRumble = WeakRumble, WeakRumble = WeakRumble,
StrongRumble = StrongRumble, StrongRumble = StrongRumble,
}, },
Led = new LedConfigController
{
EnableLed = EnableLedChanging,
LedColor = LedColor.ToUInt32()
},
Version = InputConfig.CurrentVersion, Version = InputConfig.CurrentVersion,
DeadzoneLeft = DeadzoneLeft, DeadzoneLeft = DeadzoneLeft,
DeadzoneRight = DeadzoneRight, DeadzoneRight = DeadzoneRight,

View File

@@ -432,7 +432,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
try try
{ {
HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://raw.githubusercontent.com/GreemDev/Ryujinx/refs/heads/master/assets/amiibo/Amiibo.json")); HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://raw.githubusercontent.com/Ryubing/Ryujinx/refs/heads/master/assets/amiibo/Amiibo.json"));
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
@@ -451,7 +451,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
try try
{ {
HttpResponseMessage response = await _httpClient.GetAsync($"https://raw.githubusercontent.com/GreemDev/Ryujinx/refs/heads/master/assets/amiibo/Amiibo.json"); HttpResponseMessage response = await _httpClient.GetAsync($"https://raw.githubusercontent.com/Ryubing/Ryujinx/refs/heads/master/assets/amiibo/Amiibo.json");
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {

View File

@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
[ObservableProperty] private SvgImage _image; [ObservableProperty] private SvgImage _image;
public readonly InputViewModel ParentModel; public InputViewModel ParentModel { get; }
public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config) public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config)
{ {

View File

@@ -69,6 +69,9 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public bool IsRight { get; set; } public bool IsRight { get; set; }
public bool IsLeft { get; set; } public bool IsLeft { get; set; }
public bool HasLed => false; //temporary
//SelectedGamepad.Features.HasFlag(GamepadFeaturesFlag.Led);
public bool IsModified { get; set; } public bool IsModified { get; set; }
public event Action NotifyChangesEvent; public event Action NotifyChangesEvent;

View File

@@ -488,7 +488,6 @@ namespace Ryujinx.Ava.UI.ViewModels
EnableDiscordIntegration = config.EnableDiscordIntegration; EnableDiscordIntegration = config.EnableDiscordIntegration;
CheckUpdatesOnStart = config.CheckUpdatesOnStart; CheckUpdatesOnStart = config.CheckUpdatesOnStart;
ShowConfirmExit = config.ShowConfirmExit; ShowConfirmExit = config.ShowConfirmExit;
IgnoreApplet = config.IgnoreApplet;
RememberWindowState = config.RememberWindowState; RememberWindowState = config.RememberWindowState;
ShowTitleBar = config.ShowTitleBar; ShowTitleBar = config.ShowTitleBar;
HideCursor = (int)config.HideCursor.Value; HideCursor = (int)config.HideCursor.Value;
@@ -532,6 +531,7 @@ namespace Ryujinx.Ava.UI.ViewModels
EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks; EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks;
DramSize = config.System.DramSize; DramSize = config.System.DramSize;
IgnoreMissingServices = config.System.IgnoreMissingServices; IgnoreMissingServices = config.System.IgnoreMissingServices;
IgnoreApplet = config.System.IgnoreApplet;
// CPU // CPU
EnablePptc = config.System.EnablePtc; EnablePptc = config.System.EnablePtc;
@@ -591,7 +591,6 @@ namespace Ryujinx.Ava.UI.ViewModels
config.EnableDiscordIntegration.Value = EnableDiscordIntegration; config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart; config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
config.ShowConfirmExit.Value = ShowConfirmExit; config.ShowConfirmExit.Value = ShowConfirmExit;
config.IgnoreApplet.Value = IgnoreApplet;
config.RememberWindowState.Value = RememberWindowState; config.RememberWindowState.Value = RememberWindowState;
config.ShowTitleBar.Value = ShowTitleBar; config.ShowTitleBar.Value = ShowTitleBar;
config.HideCursor.Value = (HideCursorMode)HideCursor; config.HideCursor.Value = (HideCursorMode)HideCursor;
@@ -632,12 +631,10 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
config.System.SystemTimeOffset.Value = Convert.ToInt64((CurrentDate.ToUnixTimeSeconds() + CurrentTime.TotalSeconds) - DateTimeOffset.Now.ToUnixTimeSeconds()); config.System.SystemTimeOffset.Value = Convert.ToInt64((CurrentDate.ToUnixTimeSeconds() + CurrentTime.TotalSeconds) - DateTimeOffset.Now.ToUnixTimeSeconds());
config.Graphics.VSyncMode.Value = VSyncMode;
config.Graphics.EnableCustomVSyncInterval.Value = EnableCustomVSyncInterval;
config.Graphics.CustomVSyncInterval.Value = CustomVSyncInterval;
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks; config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
config.System.DramSize.Value = DramSize; config.System.DramSize.Value = DramSize;
config.System.IgnoreMissingServices.Value = IgnoreMissingServices; config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
config.System.IgnoreApplet.Value = IgnoreApplet;
// CPU // CPU
config.System.EnablePtc.Value = EnablePptc; config.System.EnablePtc.Value = EnablePptc;
@@ -646,6 +643,9 @@ namespace Ryujinx.Ava.UI.ViewModels
config.System.UseHypervisor.Value = UseHypervisor; config.System.UseHypervisor.Value = UseHypervisor;
// Graphics // Graphics
config.Graphics.VSyncMode.Value = VSyncMode;
config.Graphics.EnableCustomVSyncInterval.Value = EnableCustomVSyncInterval;
config.Graphics.CustomVSyncInterval.Value = CustomVSyncInterval;
config.Graphics.GraphicsBackend.Value = (GraphicsBackend)GraphicsBackendIndex; config.Graphics.GraphicsBackend.Value = (GraphicsBackend)GraphicsBackendIndex;
config.Graphics.PreferredGpu.Value = _gpuIds.ElementAtOrDefault(PreferredGpuIndex); config.Graphics.PreferredGpu.Value = _gpuIds.ElementAtOrDefault(PreferredGpuIndex);
config.Graphics.EnableShaderCache.Value = EnableShaderCache; config.Graphics.EnableShaderCache.Value = EnableShaderCache;

View File

@@ -4,6 +4,7 @@
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup" xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 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:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
@@ -486,6 +487,37 @@
</Button> </Button>
</Grid> </Grid>
</Border> </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="{ext:Locale ControllerSettingsLedColor}" />
</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>
</StackPanel> </StackPanel>
<!-- Right Controls --> <!-- Right Controls -->

View File

@@ -4,14 +4,11 @@ using Avalonia.Controls.Primitives;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using DiscordRPC;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels.Input; using Ryujinx.Ava.UI.ViewModels.Input;
using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Logging;
using Ryujinx.Input; using Ryujinx.Input;
using Ryujinx.Input.Assigner; using Ryujinx.Input.Assigner;
using System;
using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId; using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
namespace Ryujinx.Ava.UI.Views.Input namespace Ryujinx.Ava.UI.Views.Input

View File

@@ -264,19 +264,19 @@
Name="FaqMenuItem" Name="FaqMenuItem"
Header="{ext:Locale MenuBarHelpFaq}" Header="{ext:Locale MenuBarHelpFaq}"
Icon="{ext:Icon fa-github}" Icon="{ext:Icon fa-github}"
CommandParameter="https://github.com/GreemDev/Ryujinx/wiki/FAQ-and-Troubleshooting" CommandParameter="https://github.com/Ryubing/Ryujinx/wiki/FAQ-and-Troubleshooting"
ToolTip.Tip="{ext:Locale MenuBarHelpFaqTooltip}" /> ToolTip.Tip="{ext:Locale MenuBarHelpFaqTooltip}" />
<MenuItem <MenuItem
Name="SetupGuideMenuItem" Name="SetupGuideMenuItem"
Header="{ext:Locale MenuBarHelpSetup}" Header="{ext:Locale MenuBarHelpSetup}"
Icon="{ext:Icon fa-github}" Icon="{ext:Icon fa-github}"
CommandParameter="https://github.com/GreemDev/Ryujinx/wiki/Ryujinx-Setup-&amp;-Configuration-Guide" CommandParameter="https://github.com/Ryubing/Ryujinx/wiki/Ryujinx-Setup-&amp;-Configuration-Guide"
ToolTip.Tip="{ext:Locale MenuBarHelpSetupTooltip}" /> ToolTip.Tip="{ext:Locale MenuBarHelpSetupTooltip}" />
<MenuItem <MenuItem
Name="LdnGuideMenuItem" Name="LdnGuideMenuItem"
Header="{ext:Locale MenuBarHelpMultiplayer}" Header="{ext:Locale MenuBarHelpMultiplayer}"
Icon="{ext:Icon fa-github}" Icon="{ext:Icon fa-github}"
CommandParameter="https://github.com/GreemDev/Ryujinx/wiki/Multiplayer%E2%80%90(LDN%E2%80%90Local%E2%80%90Wireless)%E2%80%90Guide" CommandParameter="https://github.com/Ryubing/Ryujinx/wiki/Multiplayer%E2%80%90(LDN%E2%80%90Local%E2%80%90Wireless)%E2%80%90Guide"
ToolTip.Tip="{ext:Locale MenuBarHelpMultiplayerTooltip}" /> ToolTip.Tip="{ext:Locale MenuBarHelpMultiplayerTooltip}" />
</MenuItem> </MenuItem>
</MenuItem> </MenuItem>

View File

@@ -114,8 +114,7 @@
Grid.Column="1" Grid.Column="1"
MinWidth="90" MinWidth="90"
Margin="10,0,0,0" Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale AddGameDirTooltip}" ToolTip.Tip="{ext:Locale AddGameDirTooltip}">
Click="AddGameDirButton_OnClick">
<TextBlock HorizontalAlignment="Center" <TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralAdd}" /> Text="{ext:Locale SettingsTabGeneralAdd}" />
</Button> </Button>
@@ -168,8 +167,7 @@
Grid.Column="1" Grid.Column="1"
MinWidth="90" MinWidth="90"
Margin="10,0,0,0" Margin="10,0,0,0"
ToolTip.Tip="{ext:Locale AddAutoloadDirTooltip}" ToolTip.Tip="{ext:Locale AddAutoloadDirTooltip}">
Click="AddAutoloadDirButton_OnClick">
<TextBlock HorizontalAlignment="Center" <TextBlock HorizontalAlignment="Center"
Text="{ext:Locale SettingsTabGeneralAdd}" /> Text="{ext:Locale SettingsTabGeneralAdd}" />
</Button> </Button>

View File

@@ -1,12 +1,17 @@
using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using Gommon;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Utilities;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Views.Settings namespace Ryujinx.Ava.UI.Views.Settings
{ {
@@ -18,31 +23,39 @@ namespace Ryujinx.Ava.UI.Views.Settings
{ {
InitializeComponent(); InitializeComponent();
ShowTitleBarBox.IsVisible = OperatingSystem.IsWindows(); ShowTitleBarBox.IsVisible = OperatingSystem.IsWindows();
AddGameDirButton.Command =
Commands.Create(() => AddDirButton(GameDirPathBox, ViewModel.GameDirectories, true));
AddAutoloadDirButton.Command =
Commands.Create(() => AddDirButton(AutoloadDirPathBox, ViewModel.AutoloadDirectories, false));
} }
private async void AddGameDirButton_OnClick(object sender, RoutedEventArgs e) private async Task AddDirButton(TextBox addDirBox, AvaloniaList<string> directories, bool isGameList)
{ {
string path = GameDirPathBox.Text; string path = addDirBox.Text;
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.GameDirectories.Contains(path)) if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !directories.Contains(path))
{ {
ViewModel.GameDirectories.Add(path); directories.Add(path);
ViewModel.GameDirectoryChanged = true;
addDirBox.Clear();
if (isGameList)
ViewModel.GameDirectoryChanged = true;
else
ViewModel.AutoloadDirectoryChanged = true;
} }
else else
{ {
if (this.GetVisualRoot() is Window window) Optional<IStorageFolder> folder = await RyujinxApp.MainWindow.ViewModel.StorageProvider.OpenSingleFolderPickerAsync();
{
var result = await window.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
AllowMultiple = false,
});
if (result.Count > 0) if (folder.HasValue)
{ {
ViewModel.GameDirectories.Add(result[0].Path.LocalPath); directories.Add(folder.Value.Path.LocalPath);
if (isGameList)
ViewModel.GameDirectoryChanged = true; ViewModel.GameDirectoryChanged = true;
} else
ViewModel.AutoloadDirectoryChanged = true;
} }
} }
} }
@@ -63,33 +76,6 @@ namespace Ryujinx.Ava.UI.Views.Settings
} }
} }
private async void AddAutoloadDirButton_OnClick(object sender, RoutedEventArgs e)
{
string path = AutoloadDirPathBox.Text;
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.AutoloadDirectories.Contains(path))
{
ViewModel.AutoloadDirectories.Add(path);
ViewModel.AutoloadDirectoryChanged = true;
}
else
{
if (this.GetVisualRoot() is Window window)
{
var result = await window.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
AllowMultiple = false,
});
if (result.Count > 0)
{
ViewModel.AutoloadDirectories.Add(result[0].Path.LocalPath);
ViewModel.AutoloadDirectoryChanged = true;
}
}
}
}
private void RemoveAutoloadDirButton_OnClick(object sender, RoutedEventArgs e) private void RemoveAutoloadDirButton_OnClick(object sender, RoutedEventArgs e)
{ {
int oldIndex = AutoloadDirsList.SelectedIndex; int oldIndex = AutoloadDirsList.SelectedIndex;

View File

@@ -182,7 +182,7 @@
HorizontalAlignment="Left" HorizontalAlignment="Left"
Background="Transparent" Background="Transparent"
Click="Button_OnClick" Click="Button_OnClick"
Tag="https://github.com/GreemDev/Ryujinx/graphs/contributors?type=a"> Tag="https://github.com/Ryubing/Ryujinx/graphs/contributors?type=a">
<TextBlock <TextBlock
FontSize="10" FontSize="10"
Text="{ext:Locale AboutRyujinxContributorsButtonHeader}" Text="{ext:Locale AboutRyujinxContributorsButtonHeader}"

View File

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

View File

@@ -45,7 +45,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration; EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
CheckUpdatesOnStart.Value = cff.CheckUpdatesOnStart; CheckUpdatesOnStart.Value = cff.CheckUpdatesOnStart;
ShowConfirmExit.Value = cff.ShowConfirmExit; ShowConfirmExit.Value = cff.ShowConfirmExit;
IgnoreApplet.Value = cff.IgnoreApplet;
RememberWindowState.Value = cff.RememberWindowState; RememberWindowState.Value = cff.RememberWindowState;
ShowTitleBar.Value = cff.ShowTitleBar; ShowTitleBar.Value = cff.ShowTitleBar;
EnableHardwareAcceleration.Value = cff.EnableHardwareAcceleration; EnableHardwareAcceleration.Value = cff.EnableHardwareAcceleration;
@@ -97,6 +96,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
System.MemoryManagerMode.Value = cff.MemoryManagerMode; System.MemoryManagerMode.Value = cff.MemoryManagerMode;
System.DramSize.Value = cff.DramSize; System.DramSize.Value = cff.DramSize;
System.IgnoreMissingServices.Value = cff.IgnoreMissingServices; System.IgnoreMissingServices.Value = cff.IgnoreMissingServices;
System.IgnoreApplet.Value = cff.IgnoreApplet;
System.UseHypervisor.Value = cff.UseHypervisor; System.UseHypervisor.Value = cff.UseHypervisor;
UI.GuiColumns.FavColumn.Value = cff.GuiColumns.FavColumn; UI.GuiColumns.FavColumn.Value = cff.GuiColumns.FavColumn;
@@ -263,15 +263,12 @@ namespace Ryujinx.Ava.Utilities.Configuration
}), }),
(30, static cff => (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), (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. // so as a compromise users who want to use it will simply need to re-enable it once after updating.
cff.IgnoreApplet = false; 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
};
}
})
); );
} }
} }

View File

@@ -367,6 +367,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// </summary> /// </summary>
public ReactiveObject<bool> IgnoreMissingServices { get; private set; } public ReactiveObject<bool> IgnoreMissingServices { get; private set; }
/// <summary>
/// Ignore Controller Applet
/// </summary>
public ReactiveObject<bool> IgnoreApplet { get; private set; }
/// <summary> /// <summary>
/// Uses Hypervisor over JIT if available /// Uses Hypervisor over JIT if available
/// </summary> /// </summary>
@@ -404,6 +409,8 @@ namespace Ryujinx.Ava.Utilities.Configuration
DramSize.LogChangesToValue(nameof(DramSize)); DramSize.LogChangesToValue(nameof(DramSize));
IgnoreMissingServices = new ReactiveObject<bool>(); IgnoreMissingServices = new ReactiveObject<bool>();
IgnoreMissingServices.LogChangesToValue(nameof(IgnoreMissingServices)); IgnoreMissingServices.LogChangesToValue(nameof(IgnoreMissingServices));
IgnoreApplet = new ReactiveObject<bool>();
IgnoreApplet.LogChangesToValue(nameof(IgnoreApplet));
AudioVolume = new ReactiveObject<float>(); AudioVolume = new ReactiveObject<float>();
AudioVolume.LogChangesToValue(nameof(AudioVolume)); AudioVolume.LogChangesToValue(nameof(AudioVolume));
UseHypervisor = new ReactiveObject<bool>(); UseHypervisor = new ReactiveObject<bool>();
@@ -745,11 +752,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// </summary> /// </summary>
public ReactiveObject<bool> ShowConfirmExit { get; private set; } public ReactiveObject<bool> ShowConfirmExit { get; private set; }
/// <summary>
/// Ignore Applet
/// </summary>
public ReactiveObject<bool> IgnoreApplet { get; private set; }
/// <summary> /// <summary>
/// Enables or disables save window size, position and state on close. /// Enables or disables save window size, position and state on close.
/// </summary> /// </summary>
@@ -782,8 +784,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
EnableDiscordIntegration = new ReactiveObject<bool>(); EnableDiscordIntegration = new ReactiveObject<bool>();
CheckUpdatesOnStart = new ReactiveObject<bool>(); CheckUpdatesOnStart = new ReactiveObject<bool>();
ShowConfirmExit = new ReactiveObject<bool>(); ShowConfirmExit = new ReactiveObject<bool>();
IgnoreApplet = new ReactiveObject<bool>();
IgnoreApplet.LogChangesToValue(nameof(IgnoreApplet));
RememberWindowState = new ReactiveObject<bool>(); RememberWindowState = new ReactiveObject<bool>();
ShowTitleBar = new ReactiveObject<bool>(); ShowTitleBar = new ReactiveObject<bool>();
EnableHardwareAcceleration = new ReactiveObject<bool>(); EnableHardwareAcceleration = new ReactiveObject<bool>();

View File

@@ -56,7 +56,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
EnableDiscordIntegration = EnableDiscordIntegration, EnableDiscordIntegration = EnableDiscordIntegration,
CheckUpdatesOnStart = CheckUpdatesOnStart, CheckUpdatesOnStart = CheckUpdatesOnStart,
ShowConfirmExit = ShowConfirmExit, ShowConfirmExit = ShowConfirmExit,
IgnoreApplet = IgnoreApplet,
RememberWindowState = RememberWindowState, RememberWindowState = RememberWindowState,
ShowTitleBar = ShowTitleBar, ShowTitleBar = ShowTitleBar,
EnableHardwareAcceleration = EnableHardwareAcceleration, EnableHardwareAcceleration = EnableHardwareAcceleration,
@@ -78,6 +77,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
MemoryManagerMode = System.MemoryManagerMode, MemoryManagerMode = System.MemoryManagerMode,
DramSize = System.DramSize, DramSize = System.DramSize,
IgnoreMissingServices = System.IgnoreMissingServices, IgnoreMissingServices = System.IgnoreMissingServices,
IgnoreApplet = System.IgnoreApplet,
UseHypervisor = System.UseHypervisor, UseHypervisor = System.UseHypervisor,
GuiColumns = new GuiColumns GuiColumns = new GuiColumns
{ {
@@ -176,7 +176,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
EnableDiscordIntegration.Value = true; EnableDiscordIntegration.Value = true;
CheckUpdatesOnStart.Value = true; CheckUpdatesOnStart.Value = true;
ShowConfirmExit.Value = true; ShowConfirmExit.Value = true;
IgnoreApplet.Value = false;
RememberWindowState.Value = true; RememberWindowState.Value = true;
ShowTitleBar.Value = !OperatingSystem.IsWindows(); ShowTitleBar.Value = !OperatingSystem.IsWindows();
EnableHardwareAcceleration.Value = true; EnableHardwareAcceleration.Value = true;
@@ -200,6 +199,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe; System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe;
System.DramSize.Value = MemoryConfiguration.MemoryConfiguration4GiB; System.DramSize.Value = MemoryConfiguration.MemoryConfiguration4GiB;
System.IgnoreMissingServices.Value = false; System.IgnoreMissingServices.Value = false;
System.IgnoreApplet.Value = false;
System.UseHypervisor.Value = true; System.UseHypervisor.Value = true;
Multiplayer.LanInterfaceId.Value = "0"; Multiplayer.LanInterfaceId.Value = "0";
Multiplayer.Mode.Value = MultiplayerMode.Disabled; Multiplayer.Mode.Value = MultiplayerMode.Disabled;

View File

@@ -0,0 +1,47 @@
using Avalonia.Platform.Storage;
using Gommon;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Utilities
{
public static class StorageProviderExtensions
{
public static async Task<Optional<IStorageFolder>> OpenSingleFolderPickerAsync(this IStorageProvider storageProvider, FolderPickerOpenOptions openOptions = null) =>
await storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, false))
.Then(folders => folders.FindFirst());
public static async Task<Optional<IStorageFile>> OpenSingleFilePickerAsync(this IStorageProvider storageProvider, FilePickerOpenOptions openOptions = null) =>
await storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, false))
.Then(files => files.FindFirst());
public static async Task<Optional<IReadOnlyList<IStorageFolder>>> OpenMultiFolderPickerAsync(this IStorageProvider storageProvider, FolderPickerOpenOptions openOptions = null) =>
await storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, true))
.Then(folders => folders.Count > 0 ? Optional.Of(folders) : default);
public static async Task<Optional<IReadOnlyList<IStorageFile>>> OpenMultiFilePickerAsync(this IStorageProvider storageProvider, FilePickerOpenOptions openOptions = null) =>
await storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, true))
.Then(files => files.Count > 0 ? Optional.Of(files) : default);
private static FilePickerOpenOptions FixOpenOptions(this FilePickerOpenOptions openOptions, bool allowMultiple)
{
if (openOptions is null)
return new FilePickerOpenOptions { AllowMultiple = allowMultiple };
openOptions.AllowMultiple = allowMultiple;
return openOptions;
}
private static FolderPickerOpenOptions FixOpenOptions(this FolderPickerOpenOptions openOptions, bool allowMultiple)
{
if (openOptions is null)
return new FolderPickerOpenOptions { AllowMultiple = allowMultiple };
openOptions.AllowMultiple = allowMultiple;
return openOptions;
}
}
}