Structural and Memory Safety Improvements, Analyzer Cleanup (ryubing/ryujinx!47)

See merge request ryubing/ryujinx!47
This commit is contained in:
MrKev 2025-06-11 17:58:27 -05:00 committed by LotP
parent d03ae9c164
commit ea027d65a7
309 changed files with 1018 additions and 1247 deletions

View file

@ -44,12 +44,12 @@ namespace Ryujinx.Ava.Common.Models
if (obj == null)
return false;
return this.Path == obj.Path;
return Path == obj.Path;
}
public override int GetHashCode()
{
return this.Path.GetHashCode();
return Path.GetHashCode();
}
}
}

View file

@ -119,7 +119,6 @@ namespace Ryujinx.Ava
=> ProcessUnhandledException(sender, e.Exception, false);
AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit();
// Setup base data directory.
AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
@ -160,7 +159,6 @@ namespace Ryujinx.Ava
}
}
public static string GetDirGameUserConfig(string gameId, bool changeFolderForGame = false)
{
if (string.IsNullOrEmpty(gameId))
@ -221,10 +219,7 @@ namespace Ryujinx.Ava
}
// When you first load the program, copy to remember the path for the global configuration
if (GlobalConfigurationPath == null)
{
GlobalConfigurationPath = ConfigurationPath;
}
GlobalConfigurationPath ??= ConfigurationPath;
UseHardwareAcceleration = ConfigurationState.Instance.EnableHardwareAcceleration;
@ -342,7 +337,6 @@ namespace Ryujinx.Ava
log.PrintMsg(LogClass.Application, message);
}
if (isTerminating)
Exit();
}

View file

@ -86,19 +86,17 @@ namespace Ryujinx.Ava.Systems.AppLibrary
public string LocalizedStatusTooltip =>
Compatibility.Convert(x =>
#pragma warning disable CS8509 // It is exhaustive for all possible values this can contain.
LocaleManager.Instance[x.Status switch
#pragma warning restore CS8509
{
LocaleKeys.CompatibilityListPlayable => LocaleKeys.CompatibilityListPlayableTooltip,
LocaleKeys.CompatibilityListIngame => LocaleKeys.CompatibilityListIngameTooltip,
LocaleKeys.CompatibilityListMenus => LocaleKeys.CompatibilityListMenusTooltip,
LocaleKeys.CompatibilityListBoots => LocaleKeys.CompatibilityListBootsTooltip,
LocaleKeys.CompatibilityListNothing => LocaleKeys.CompatibilityListNothingTooltip,
_ => throw new ArgumentOutOfRangeException(nameof(x.Status), "Unknown playability status.")
}]
).OrElse(string.Empty);
[JsonIgnore] public string IdString => Id.ToString("x16");
[JsonIgnore] public ulong IdBase => Id & ~0x1FFFUL;

View file

@ -11,7 +11,6 @@ namespace Ryujinx.Ava.Systems.AppLibrary
LdnData = ldnData ?? [];
}
public LdnGameData[] LdnData { get; set; }
}
}

View file

@ -44,7 +44,6 @@ namespace Ryujinx.Ava.Systems.Configuration
configurationFileUpdated = true;
}
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
UpdateCheckerType.Value = shouldLoadFromFile ? cff.UpdateCheckerType : UpdateCheckerType.Value; // Get from global config only
FocusLostActionType.Value = cff.FocusLostActionType;
@ -147,7 +146,7 @@ namespace Ryujinx.Ava.Systems.Configuration
Hid.EnableMouse.Value = cff.EnableMouse;
Hid.DisableInputWhenOutOfFocus.Value = shouldLoadFromFile ? cff.DisableInputWhenOutOfFocus : Hid.DisableInputWhenOutOfFocus.Value; // Get from global config only
Hid.Hotkeys.Value = shouldLoadFromFile ? cff.Hotkeys : Hid.Hotkeys.Value; // Get from global config only
Hid.InputConfig.Value = cff.InputConfig ?? [] ;
Hid.InputConfig.Value = cff.InputConfig ?? [];
Hid.RainbowSpeed.Value = cff.RainbowSpeed;
Multiplayer.LanInterfaceId.Value = cff.MultiplayerLanInterfaceId;

View file

@ -326,7 +326,6 @@ namespace Ryujinx.Ava.Systems.Configuration
/// </summary>
public ReactiveObject<bool> MatchSystemTime { get; private set; }
/// <summary>
/// Enable or disable use global input config (Independent from controllers binding)
/// </summary>
@ -769,7 +768,7 @@ namespace Ryujinx.Ava.Systems.Configuration
/// </summary>
public static ConfigurationState Instance { get; private set; }
public static ConfigurationState InstanceExtra{ get; private set; }
public static ConfigurationState InstanceExtra { get; private set; }
/// <summary>
/// The UI section

View file

@ -15,13 +15,13 @@ namespace Ryujinx.Ava.Systems.Configuration
{
public static void Initialize()
{
if (Instance != null || InstanceExtra!= null)
if (Instance != null || InstanceExtra != null)
{
throw new InvalidOperationException("Configuration is already initialized");
}
Instance = new ConfigurationState();
InstanceExtra= new ConfigurationState();
InstanceExtra = new ConfigurationState();
}
public ConfigurationFileFormat ToFileFormat()

View file

@ -1,11 +1,9 @@
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Utilities;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Systems

View file

@ -1,4 +1,4 @@
using Gommon;
using Gommon;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Common;
@ -57,10 +57,10 @@ namespace Ryujinx.Ava.Systems
return default;
}
if (CreateUpdateQueryUrl() is not {} updateUrl)
if (CreateUpdateQueryUrl() is not { } updateUrl)
{
Logger.Error?.Print(LogClass.Application, "Could not determine URL for updates.");
_running = false;
return default;
@ -110,7 +110,6 @@ namespace Ryujinx.Ava.Systems
return default;
}
if (!Version.TryParse(_buildVer, out Version newVersion))
{
Logger.Error?.Print(LogClass.Application,
@ -127,7 +126,7 @@ namespace Ryujinx.Ava.Systems
return (currentVersion, newVersion);
}
[JsonSerializable(typeof(UpdaterResponse))]
partial class UpdaterResponseJsonContext : JsonSerializerContext;

View file

@ -5,19 +5,16 @@ using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.Zip;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models.Github;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities;
using Ryujinx.Common;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Runtime.CompilerServices;
@ -43,9 +40,9 @@ namespace Ryujinx.Ava.Systems
private static bool _running;
private static readonly string[] _windowsDependencyDirs = [];
private static string _changelogUrlFormat = null;
public static async Task BeginUpdateAsync(bool showVersionUpToDate = false)
{
if (_running)
@ -88,7 +85,7 @@ namespace Ryujinx.Ava.Systems
try
{
buildSizeClient.DefaultRequestHeaders.Add("Range", "bytes=0-0");
// GitLab instance is located in Ukraine. Connection times will vary across the world.
buildSizeClient.Timeout = TimeSpan.FromSeconds(10);
@ -245,7 +242,7 @@ namespace Ryujinx.Ava.Systems
}
}
private static void DoUpdateWithMultipleThreads(TaskDialog taskDialog, string downloadUrl, string updateFile)
private static async void DoUpdateWithMultipleThreads(TaskDialog taskDialog, string downloadUrl, string updateFile)
{
// Multi-Threaded Updater
long chunkSize = _buildSize / ConnectionCount;
@ -256,111 +253,95 @@ namespace Ryujinx.Ava.Systems
int[] progressPercentage = new int[ConnectionCount];
List<byte[]> list = new(ConnectionCount);
List<WebClient> webClients = new(ConnectionCount);
for (int i = 0; i < ConnectionCount; i++)
{
list.Add([]);
}
using HttpClient httpClient = ConstructHttpClient();
List<Task> downloadTasks = new();
for (int i = 0; i < ConnectionCount; i++)
{
#pragma warning disable SYSLIB0014
// TODO: WebClient is obsolete and need to be replaced with a more complex logic using HttpClient.
using WebClient client = new();
#pragma warning restore SYSLIB0014
int index = i;
long start = chunkSize * index;
long end = (index == ConnectionCount - 1) ? (chunkSize * (index + 1) - 1 + remainderChunk) : (chunkSize * (index + 1) - 1);
webClients.Add(client);
if (i == ConnectionCount - 1)
downloadTasks.Add(Task.Run(async () =>
{
client.Headers.Add("Range", $"bytes={chunkSize * i}-{(chunkSize * (i + 1) - 1) + remainderChunk}");
}
else
{
client.Headers.Add("Range", $"bytes={chunkSize * i}-{chunkSize * (i + 1) - 1}");
}
client.DownloadProgressChanged += (_, args) =>
{
int index = (int)args.UserState;
Interlocked.Add(ref totalProgressPercentage, -1 * progressPercentage[index]);
Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage);
Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage);
taskDialog.SetProgressBarState(totalProgressPercentage / ConnectionCount, TaskDialogProgressState.Normal);
};
client.DownloadDataCompleted += (_, args) =>
{
int index = (int)args.UserState;
if (args.Cancelled)
try
{
webClients[index].Dispose();
HttpRequestMessage request = new(HttpMethod.Get, downloadUrl);
request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(start, end);
taskDialog.Hide();
using HttpResponseMessage response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
return;
}
using Stream contentStream = await response.Content.ReadAsStreamAsync();
using MemoryStream memoryStream = new();
list[index] = args.Result;
Interlocked.Increment(ref completedRequests);
byte[] buffer = new byte[32 * 1024];
int bytesRead;
long totalRead = 0;
long totalSize = end - start + 1;
if (Equals(completedRequests, ConnectionCount))
{
byte[] mergedFileBytes = new byte[_buildSize];
for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < ConnectionCount; connectionIndex++)
while ((bytesRead = await contentStream.ReadAsync(buffer)) > 0)
{
Array.Copy(list[connectionIndex], 0, mergedFileBytes, destinationOffset, list[connectionIndex].Length);
destinationOffset += list[connectionIndex].Length;
memoryStream.Write(buffer, 0, bytesRead);
totalRead += bytesRead;
int progress = (int)(100 * totalRead / totalSize);
Interlocked.Add(ref totalProgressPercentage, -progressPercentage[index]);
progressPercentage[index] = progress;
Interlocked.Add(ref totalProgressPercentage, progress);
taskDialog.SetProgressBarState(totalProgressPercentage / ConnectionCount, TaskDialogProgressState.Normal);
}
File.WriteAllBytes(updateFile, mergedFileBytes);
list[index] = memoryStream.ToArray();
// On macOS, ensure that we remove the quarantine bit to prevent Gatekeeper from blocking execution.
if (OperatingSystem.IsMacOS())
if (Interlocked.Increment(ref completedRequests) == ConnectionCount)
{
using Process xattrProcess = Process.Start("xattr",
["-d", "com.apple.quarantine", updateFile]);
byte[] mergedFileBytes = new byte[_buildSize];
for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < ConnectionCount; connectionIndex++)
{
Array.Copy(list[connectionIndex], 0, mergedFileBytes, destinationOffset, list[connectionIndex].Length);
destinationOffset += list[connectionIndex].Length;
}
xattrProcess.WaitForExit();
}
File.WriteAllBytes(updateFile, mergedFileBytes);
try
{
InstallUpdate(taskDialog, updateFile);
}
catch (Exception e)
{
Logger.Warning?.Print(LogClass.Application, e.Message);
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
// On macOS, ensure that we remove the quarantine bit to prevent Gatekeeper from blocking execution.
if (OperatingSystem.IsMacOS())
{
using Process xattrProcess = Process.Start("xattr",
["-d", "com.apple.quarantine", updateFile]);
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
xattrProcess.WaitForExit();
}
try
{
InstallUpdate(taskDialog, updateFile);
}
catch (Exception e)
{
Logger.Warning?.Print(LogClass.Application, e.Message);
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
}
}
}
};
try
{
client.DownloadDataAsync(new Uri(downloadUrl), i);
}
catch (WebException ex)
{
Logger.Warning?.Print(LogClass.Application, ex.Message);
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
foreach (WebClient webClient in webClients)
catch (Exception ex)
{
webClient.CancelAsync();
Logger.Warning?.Print(LogClass.Application, ex.Message);
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
}
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
return;
}
}));
}
await Task.WhenAll(downloadTasks);
}
private static void DoUpdateWithSingleThreadWorker(TaskDialog taskDialog, string downloadUrl, string updateFile)

View file

@ -118,7 +118,7 @@ namespace Ryujinx.Ava.UI.Applet
await ContentDialogHelper.ShowWindowAsync(_mainWindow.SettingsWindow, _mainWindow);
_mainWindow.SettingsWindow = null;
this.Close();
Close();
});
}
}

View file

@ -1,26 +1,5 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.Input;
using LibHac.Fs;
using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Views.Dialog;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper;
using Ryujinx.HLE.HOS;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.IO;
using Path = System.IO.Path;
namespace Ryujinx.Ava.UI.Controls
{

View file

@ -2,17 +2,15 @@ using Avalonia.Logging;
using Avalonia.Utilities;
using Gommon;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Common.Logging;
using System;
using System.Text;
using AvaLogger = Avalonia.Logging.Logger;
using AvaLogLevel = Avalonia.Logging.LogEventLevel;
using RyuLogClass = Ryujinx.Common.Logging.LogClass;
using RyuLogger = Ryujinx.Common.Logging.Logger;
namespace Ryujinx.Ava.UI.Helpers
{
using AvaLogger = Avalonia.Logging.Logger;
using AvaLogLevel = LogEventLevel;
using RyuLogClass = LogClass;
using RyuLogger = Ryujinx.Common.Logging.Logger;
internal class LoggerAdapter : ILogSink
{
private static bool _avaloniaLogsEnabled = ConfigurationState.Instance.Logger.EnableAvaloniaLog;

View file

@ -1,5 +1,4 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
@ -36,7 +35,7 @@ namespace Ryujinx.Ava.UI.Helpers
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
internal delegate nint WindowProc(nint hWnd, WindowsMessages msg, nint wParam, nint lParam);
[StructLayout(LayoutKind.Sequential)]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct WndClassEx
{
public int cbSize;

View file

@ -257,7 +257,7 @@ namespace Ryujinx.Ava.UI.Models.Input
Led = new LedConfigController
{
EnableLed = EnableLedChanging,
TurnOffLed = this.TurnOffLed,
TurnOffLed = TurnOffLed,
UseRainbow = UseRainbowLed,
LedColor = LedColor.ToUInt32()
},

View file

@ -2,7 +2,6 @@ using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Keyboard;
using System.Xml.Linq;
namespace Ryujinx.Ava.UI.Models.Input
{

View file

@ -37,7 +37,6 @@ namespace Ryujinx.Ava.UI.Renderer
_ => throw new NotImplementedException()
};
private void Initialize()
{
EmbeddedWindow.WindowCreated += CurrentWindow_WindowCreated;

View file

@ -1,10 +1,10 @@
using Gommon;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems;
using Ryujinx.Ava.Systems.AppLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using Ryujinx.Ava.Common.Locale;
namespace Ryujinx.Ava.UI.ViewModels
{
@ -30,19 +30,18 @@ namespace Ryujinx.Ava.UI.ViewModels
public string BootsInfoText { get; set; }
public string NothingInfoText { get; set; }
private IEnumerable<CompatibilityEntry> _currentEntries = CompatibilityDatabase.Entries;
private string[] _ownedGameTitleIds = [];
private Func<CompatibilityEntry, object> _sortKeySelector = x => x.GameName; // Default sort by GameName
private readonly Func<CompatibilityEntry, object> _sortKeySelector = x => x.GameName; // Default sort by GameName
public IEnumerable<CompatibilityEntry> CurrentEntries => OnlyShowOwnedGames
? _currentEntries.Where(x =>
x.TitleId.Check(tid => _ownedGameTitleIds.ContainsIgnoreCase(tid)))
: _currentEntries;
public CompatibilityViewModel() {}
public CompatibilityViewModel() { }
private void AppCountUpdated(object _, ApplicationCountUpdatedEventArgs __)
=> _ownedGameTitleIds = _appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray();
@ -57,11 +56,11 @@ namespace Ryujinx.Ava.UI.ViewModels
public void CountByStatus()
{
PlayableInfoText = LocaleManager.Instance[LocaleKeys.CompatibilityListPlayable] + ": " + CurrentEntries.Count(x => x.Status == LocaleKeys.CompatibilityListPlayable);
InGameInfoText = LocaleManager.Instance[LocaleKeys.CompatibilityListIngame] + ": " + CurrentEntries.Count(x => x.Status == LocaleKeys.CompatibilityListIngame);
MenusInfoText = LocaleManager.Instance[LocaleKeys.CompatibilityListMenus] + ": " + CurrentEntries.Count(x => x.Status == LocaleKeys.CompatibilityListMenus);
BootsInfoText = LocaleManager.Instance[LocaleKeys.CompatibilityListBoots] + ": " + CurrentEntries.Count(x => x.Status == LocaleKeys.CompatibilityListBoots);
NothingInfoText = LocaleManager.Instance[LocaleKeys.CompatibilityListNothing] + ": " + CurrentEntries.Count(x => x.Status == LocaleKeys.CompatibilityListNothing);
PlayableInfoText = LocaleManager.Instance[LocaleKeys.CompatibilityListPlayable] + ": " + CurrentEntries.Count(x => x.Status == LocaleKeys.CompatibilityListPlayable);
InGameInfoText = LocaleManager.Instance[LocaleKeys.CompatibilityListIngame] + ": " + CurrentEntries.Count(x => x.Status == LocaleKeys.CompatibilityListIngame);
MenusInfoText = LocaleManager.Instance[LocaleKeys.CompatibilityListMenus] + ": " + CurrentEntries.Count(x => x.Status == LocaleKeys.CompatibilityListMenus);
BootsInfoText = LocaleManager.Instance[LocaleKeys.CompatibilityListBoots] + ": " + CurrentEntries.Count(x => x.Status == LocaleKeys.CompatibilityListBoots);
NothingInfoText = LocaleManager.Instance[LocaleKeys.CompatibilityListNothing] + ": " + CurrentEntries.Count(x => x.Status == LocaleKeys.CompatibilityListNothing);
_onlyShowOwnedGames = true;
}
@ -87,7 +86,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public void NameSorting(int nameSort = 0)
{
_sorting.Name = nameSort;
@ -162,6 +160,5 @@ namespace Ryujinx.Ava.UI.ViewModels
};
}
}
}
}

View file

@ -1,7 +1,6 @@
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Svg.Skia;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using Gommon;
using Ryujinx.Ava.Common.Locale;
@ -100,7 +99,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public bool CanClearLed => SelectedGamepad.Name.ContainsIgnoreCase("DualSense");
public event Action NotifyChangesEvent;
public string ChosenProfile
{
get => _chosenProfile;
@ -327,13 +326,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
PlayerIndexes.Add(new(PlayerIndex.Handheld, LocaleManager.Instance[LocaleKeys.ControllerSettingsHandheld]));
}
private void LoadConfiguration(InputConfig inputConfig = null)
{
if (UseGlobalConfig && Program.UseExtraConfig)
{
Config = inputConfig ?? ConfigurationState.InstanceExtra.Hid.InputConfig.Value.FirstOrDefault(inputConfig => inputConfig.PlayerIndex == _playerId);
Config = inputConfig ?? ConfigurationState.InstanceExtra.Hid.InputConfig.Value.FirstOrDefault(inputConfig => inputConfig.PlayerIndex == _playerId);
}
else
{
@ -980,7 +977,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
if (Device == 0)
{
newConfig.Remove(newConfig.FirstOrDefault(x => x.PlayerIndex == this.PlayerId));
newConfig.Remove(newConfig.FirstOrDefault(x => x.PlayerIndex == PlayerId));
}
else
{

View file

@ -57,7 +57,6 @@ using Key = Ryujinx.Input.Key;
using MissingKeyException = LibHac.Common.Keys.MissingKeyException;
using Path = System.IO.Path;
using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState;
using UserId = Ryujinx.HLE.HOS.Services.Account.Acc.UserId;
namespace Ryujinx.Ava.UI.ViewModels
{
@ -1595,9 +1594,9 @@ namespace Ryujinx.Ava.UI.ViewModels
// Code where conditions will be executed after loading user configuration
if (ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() != backendThreadingInit)
{
Rebooter.RebootAppWithGame(application.Path,
Rebooter.RebootAppWithGame(application.Path,
[
"--bt",
"--bt",
ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString()
]);

View file

@ -86,7 +86,6 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool IsGameTitleNotNull => !string.IsNullOrEmpty(GameTitle);
public double PanelOpacity => IsGameTitleNotNull ? 0.5 : 1;
public int ResolutionScale
{
get => _resolutionScale;
@ -144,11 +143,11 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnableDockedMode { get; set; }
public bool EnableKeyboard { get; set; }
public bool EnableMouse { get; set; }
public bool DisableInputWhenOutOfFocus { get; set; }
public bool DisableInputWhenOutOfFocus { get; set; }
public int FocusLostActionType { get; set; }
public bool UseGlobalInputConfig
{
{
get => _useInputGlobalConfig;
set
{
@ -163,7 +162,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public VSyncMode VSyncMode
{
get => _vSyncMode;
get => _vSyncMode;
set
{
if (value is VSyncMode.Custom or VSyncMode.Switch or VSyncMode.Unbounded)
@ -226,7 +225,6 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnablePptc { get; set; }
public bool EnableLowPowerPptc { get; set; }
public long TurboMultiplier
{
get => _turboModeMultiplier;
@ -577,7 +575,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public void LoadCurrentConfiguration(bool global = false)
{
ConfigurationState config = global ? ConfigurationState.InstanceExtra: ConfigurationState.Instance;
ConfigurationState config = global ? ConfigurationState.InstanceExtra : ConfigurationState.Instance;
// User Interface
EnableDiscordIntegration = config.EnableDiscordIntegration;
@ -688,7 +686,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public void SaveSettings(bool global = false)
{
ConfigurationState config = global ? ConfigurationState.InstanceExtra: ConfigurationState.Instance;
ConfigurationState config = global ? ConfigurationState.InstanceExtra : ConfigurationState.Instance;
// User Interface
config.EnableDiscordIntegration.Value = EnableDiscordIntegration;

View file

@ -100,7 +100,7 @@ namespace Ryujinx.Ava.UI.Views.Input
{
_currentAssigner = new ButtonKeyAssigner(button);
this.Focus(NavigationMethod.Pointer);
Focus(NavigationMethod.Pointer);
PointerPressed += MouseClick;

View file

@ -107,7 +107,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
{
_currentAssigner = new ButtonKeyAssigner(button);
this.Focus(NavigationMethod.Pointer);
Focus(NavigationMethod.Pointer);
PointerPressed += MouseClick;

View file

@ -1,6 +1,6 @@
using Avalonia.Controls;
using Ryujinx.Ava.Common.Locale;
using Avalonia.Interactivity;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.ViewModels;
using System.Threading.Tasks;
@ -51,7 +51,7 @@ namespace Ryujinx.Ava.UI.Windows
if (DataContext is not CompatibilityViewModel cvm)
return;
cvm.NameSorting(int.Parse(sortStrategy));
cvm.NameSorting(int.Parse(sortStrategy));
}
}
@ -65,6 +65,5 @@ namespace Ryujinx.Ava.UI.Windows
cvm.StatusSorting(int.Parse(sortStrategy));
}
}
}
}

View file

@ -108,7 +108,7 @@ namespace Ryujinx.Ava.UI.Windows
InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
_ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it);
this.ScalingChanged += OnScalingChanged;
ScalingChanged += OnScalingChanged;
}
}
@ -157,7 +157,7 @@ namespace Ryujinx.Ava.UI.Windows
private void OnScalingChanged(object sender, EventArgs e)
{
Program.DesktopScaleFactor = this.RenderScaling;
Program.DesktopScaleFactor = RenderScaling;
}
private void ApplicationLibrary_ApplicationCountUpdated(object sender, ApplicationCountUpdatedEventArgs e)
@ -563,16 +563,16 @@ namespace Ryujinx.Ava.UI.Windows
public static void UpdateGraphicsConfig()
{
#pragma warning disable IDE0055 // Disable formatting
GraphicsConfig.ResScale = ConfigurationState.Instance.Graphics.ResScale == -1
? ConfigurationState.Instance.Graphics.ResScaleCustom
GraphicsConfig.ResScale = ConfigurationState.Instance.Graphics.ResScale == -1
? ConfigurationState.Instance.Graphics.ResScaleCustom
: ConfigurationState.Instance.Graphics.ResScale;
GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy;
GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy;
GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression;
GraphicsConfig.EnableMacroHLE = ConfigurationState.Instance.Graphics.EnableMacroHLE;
#pragma warning restore IDE0055
GraphicsConfig.EnableMacroHLE = ConfigurationState.Instance.Graphics.EnableMacroHLE;
}
private void VolumeStatus_CheckedChanged(object sender, RoutedEventArgs e)

View file

@ -43,7 +43,7 @@ namespace Ryujinx.Ava.Utilities.SystemInfo
return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER")?.Trim();
}
[StructLayout(LayoutKind.Sequential)]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct MemoryStatusEx
{
public uint Length;