Revert the Metal Experiment #701

Merged
GreemDev merged 4 commits from revert/new-metal into master 2025-02-23 03:26:46 +00:00
11 changed files with 126 additions and 236 deletions
Showing only changes of commit 9dc14d43cf - Show all commits

View File

@ -10,54 +10,6 @@ namespace Ryujinx.Common
{ {
public static ReactiveObject<Optional<string>> CurrentApplication { get; } = new(); public static ReactiveObject<Optional<string>> CurrentApplication { get; } = new();
public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend)
{
switch (currentBackend)
{
case GraphicsBackend.Metal when !OperatingSystem.IsMacOS():
case GraphicsBackend.OpenGl when OperatingSystem.IsMacOS():
return GraphicsBackend.Vulkan;
case GraphicsBackend.Vulkan or GraphicsBackend.OpenGl or GraphicsBackend.Metal:
return currentBackend;
}
if (!RunningPlatform.IsArmMac)
return GraphicsBackend.Vulkan;
return GreatMetalTitles.ContainsIgnoreCase(titleId) ? GraphicsBackend.Metal : GraphicsBackend.Vulkan;
}
public static readonly string[] GreatMetalTitles =
[
"01009b500007c000", // ARMS
"0100a5c00d162000", // Cuphead
"010023800d64a000", // Deltarune
"01003a30012c0000", // LEGO City Undercover
"010048701995e000", // Luigi's Manion 2 HD
"010028600EBDA000", // Mario 3D World
"0100152000022000", // Mario Kart 8 Deluxe
"010075a016a3a000", // Persona 4 Arena Ultimax
"0100187003A36000", // Pokémon: Let's Go, Eevee!
"010003f003a34000", // Pokémon: Let's Go, Pikachu!
"01008C0016544000", // Sea of Stars
"01006A800016E000", // Smash Ultimate
"01006bb00c6f0000", // The Legend of Zelda: Link's Awakening
// These ones have small issues, but those happen on Vulkan as well:
"01006f8002326000", // Animal Crossings: New Horizons
"01009bf0072d4000", // Captain Toad: Treasure Tracker
"01009510001ca000", // Fast RMX
"01005CA01580E000", // Persona 5 Royal
"0100b880154fc000", // Persona 5 The Royal (Japan)
"010015100b514000", // Super Mario Bros. Wonder
"0100000000010000", // Super Mario Odyssey
// Further testing is appreciated, I did not test the entire game:
//"010076f0049a2000", // Bayonetta
//"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
//"0100f4300bf2c000", // New Pokemon Snap
];
public static string GetDiscordGameAsset(string titleId) public static string GetDiscordGameAsset(string titleId)
=> DiscordGameAssetKeys.Contains(titleId) ? titleId : "game"; => DiscordGameAssetKeys.Contains(titleId) ? titleId : "game";

View File

@ -1,4 +1,3 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
@ -367,9 +366,6 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
{ {
try try
{ {
if (_context.Capabilities.Api == TargetApi.Metal && _context.DirtyHacks.IsEnabled(DirtyHack.ShaderTranslationDelay))
Thread.Sleep(_context.DirtyHacks[DirtyHack.ShaderTranslationDelay]);
AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute); AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute);
_asyncTranslationQueue.Add(asyncTranslation, _cancellationToken); _asyncTranslationQueue.Add(asyncTranslation, _cancellationToken);
} }

View File

@ -891,7 +891,7 @@ namespace Ryujinx.Ava
VirtualFileSystem.ReloadKeySet(); VirtualFileSystem.ReloadKeySet();
// Initialize Renderer. // Initialize Renderer.
GraphicsBackend backend = TitleIDs.SelectGraphicsBackend(ApplicationId.ToString("X16"), ConfigurationState.Instance.Graphics.GraphicsBackend); GraphicsBackend backend = ConfigurationState.Instance.Graphics.GraphicsBackend;
IRenderer renderer = backend switch IRenderer renderer = backend switch
{ {

View File

@ -130,12 +130,36 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="..\..\distribution\linux\shortcut-template.desktop">
<Link>Assets\ShortcutFiles\shortcut-template.desktop</Link>
</EmbeddedResource>
<EmbeddedResource Include="..\..\distribution\macos\shortcut-launch-script.sh">
<Link>Assets\ShortcutFiles\shortcut-launch-script.sh</Link>
</EmbeddedResource>
<EmbeddedResource Include="..\..\distribution\macos\shortcut-template.plist">
<Link>Assets\ShortcutFiles\shortcut-template.plist</Link>
</EmbeddedResource>
<EmbeddedResource Include="..\..\docs\compatibility.csv" LogicalName="RyujinxGameCompatibilityList">
<Link>Assets\RyujinxGameCompatibility.csv</Link>
</EmbeddedResource>
<EmbeddedResource Include="Assets\locales.json" /> <EmbeddedResource Include="Assets\locales.json" />
<EmbeddedResource Include="Assets\Styles\Styles.xaml" /> <EmbeddedResource Include="Assets\Styles\Styles.xaml" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConLeft.svg" /> <EmbeddedResource Include="Assets\Icons\Controller_JoyConLeft.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConPair.svg" /> <EmbeddedResource Include="Assets\Icons\Controller_JoyConPair.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConRight.svg" /> <EmbeddedResource Include="Assets\Icons\Controller_JoyConRight.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_ProCon.svg" /> <EmbeddedResource Include="Assets\Icons\Controller_ProCon.svg" />
<EmbeddedResource Include="Assets\UIImages\Icon_NCA.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_NRO.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_NSO.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_NSP.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_XCI.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Amiibo.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Discord_Dark.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Discord_Light.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_GitHub_Dark.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_GitHub_Light.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx_AntiAlias.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AdditionalFiles Include="Assets\locales.json" /> <AdditionalFiles Include="Assets\locales.json" />

View File

@ -45,9 +45,9 @@ namespace Ryujinx.Ava.UI.Renderer
FlowDirection = FlowDirection.LeftToRight; FlowDirection = FlowDirection.LeftToRight;
EmbeddedWindow = EmbeddedWindow =
#pragma warning disable CS8509 #pragma warning disable CS8524
TitleIDs.SelectGraphicsBackend(titleId, ConfigurationState.Instance.Graphics.GraphicsBackend) switch ConfigurationState.Instance.Graphics.GraphicsBackend.Value switch
#pragma warning restore CS8509 #pragma warning restore CS8524
{ {
GraphicsBackend.OpenGl => new EmbeddedWindowOpenGL(), GraphicsBackend.OpenGl => new EmbeddedWindowOpenGL(),
GraphicsBackend.Vulkan => new EmbeddedWindowVulkan(), GraphicsBackend.Vulkan => new EmbeddedWindowVulkan(),

View File

@ -141,7 +141,8 @@ namespace Ryujinx.Ava.UI.ViewModels
// For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left. // For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left.
// The border gets reduced to colored pixels in the 4 corners. // The border gets reduced to colored pixels in the 4 corners.
public static readonly Bitmap IconBitmap = public static readonly Bitmap IconBitmap =
new(Assembly.GetAssembly(typeof(MainWindowViewModel))!.GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!); new(Assembly.GetAssembly(typeof(MainWindowViewModel))!
.GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!);
public MainWindow Window { get; init; } public MainWindow Window { get; init; }

View File

@ -16,21 +16,6 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
[ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix; [ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
[ObservableProperty] private bool _shaderTranslationDelayEnabled = ConfigurationState.Instance.Hacks.EnableShaderTranslationDelay;
private int _shaderTranslationSleepDelay = ConfigurationState.Instance.Hacks.ShaderTranslationDelay;
public string ShaderTranslationDelayValueText => $"{ShaderTranslationDelay}ms";
public int ShaderTranslationDelay
{
get => _shaderTranslationSleepDelay;
set
{
_shaderTranslationSleepDelay = value;
OnPropertiesChanged(nameof(ShaderTranslationDelay), nameof(ShaderTranslationDelayValueText));
}
}
public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb => public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb =>
{ {
@ -44,13 +29,5 @@ namespace Ryujinx.Ava.UI.ViewModels
"there is a low chance that the game will softlock, " + "there is a low chance that the game will softlock, " +
"the submenu won't show up, while background music is still there."); "the submenu won't show up, while background music is still there.");
}); });
public static string ShaderTranslationDelayTooltip { get; } = Lambda.String(sb =>
{
sb.AppendLine("This hack applies the delay you specify every time shaders are attempted to be translated.")
.AppendLine();
sb.Append("Configurable via slider, only when this option is enabled.");
});
} }
} }

View File

@ -1,6 +1,8 @@
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SDL2;
@ -9,23 +11,24 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Ava.Utilities.Configuration.System;
using Ryujinx.Ava.Utilities.Configuration.UI;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.GraphicsDriver; using Ryujinx.Common.GraphicsDriver;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Vulkan; using Ryujinx.Graphics.Vulkan;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Services.Time.TimeZone; using Ryujinx.HLE.HOS.Services.Time.TimeZone;
using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Configuration.System;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using TimeZone = Ryujinx.Ava.UI.Models.TimeZone; using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
@ -45,10 +48,9 @@ namespace Ryujinx.Ava.UI.ViewModels
private int _resolutionScale; private int _resolutionScale;
private int _graphicsBackendMultithreadingIndex; private int _graphicsBackendMultithreadingIndex;
private float _volume; private float _volume;
private bool _isVulkanAvailable = true; [ObservableProperty] private bool _isVulkanAvailable = true;
private bool _gameDirectoryChanged; [ObservableProperty] private bool _gameListNeedsRefresh;
private bool _autoloadDirectoryChanged; private readonly List<string> _gpuIds = [];
private readonly List<string> _gpuIds = new();
private int _graphicsBackendIndex; private int _graphicsBackendIndex;
private int _scalingFilter; private int _scalingFilter;
private int _scalingFilterLevel; private int _scalingFilterLevel;
@ -62,7 +64,9 @@ namespace Ryujinx.Ava.UI.ViewModels
private int _networkInterfaceIndex; private int _networkInterfaceIndex;
private int _multiplayerModeIndex; private int _multiplayerModeIndex;
private string _ldnPassphrase; private string _ldnPassphrase;
private string _LdnServer; [ObservableProperty] private string _ldnServer;
public SettingsHacksViewModel DirtyHacks { get; }
public int ResolutionScale public int ResolutionScale
{ {
@ -71,8 +75,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
_resolutionScale = value; _resolutionScale = value;
OnPropertyChanged(nameof(CustomResolutionScale)); OnPropertiesChanged(nameof(CustomResolutionScale), nameof(IsCustomResolutionScaleActive));
OnPropertyChanged(nameof(IsCustomResolutionScaleActive));
} }
} }
@ -109,45 +112,8 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public bool IsVulkanAvailable
{
get => _isVulkanAvailable;
set
{
_isVulkanAvailable = value;
OnPropertyChanged();
}
}
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS(); public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
public bool IsHypervisorAvailable => OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
public bool GameDirectoryChanged
{
get => _gameDirectoryChanged;
set
{
_gameDirectoryChanged = value;
OnPropertyChanged();
}
}
public bool AutoloadDirectoryChanged
{
get => _autoloadDirectoryChanged;
set
{
_autoloadDirectoryChanged = value;
OnPropertyChanged();
}
}
public bool IsMacOS => OperatingSystem.IsMacOS();
public bool EnableDiscordIntegration { get; set; } public bool EnableDiscordIntegration { get; set; }
public bool CheckUpdatesOnStart { get; set; } public bool CheckUpdatesOnStart { get; set; }
public bool ShowConfirmExit { get; set; } public bool ShowConfirmExit { get; set; }
@ -155,17 +121,20 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool RememberWindowState { get; set; } public bool RememberWindowState { get; set; }
public bool ShowTitleBar { get; set; } public bool ShowTitleBar { get; set; }
public int HideCursor { get; set; } public int HideCursor { get; set; }
public int UpdateCheckerType { get; set; }
public bool EnableDockedMode { get; set; } public bool EnableDockedMode { get; set; }
public bool EnableKeyboard { get; set; } public bool EnableKeyboard { get; set; }
public bool EnableMouse { get; set; } public bool EnableMouse { get; set; }
public bool DisableInputWhenOutOfFocus { get; set; }
public int FocusLostActionType { get; set; }
public VSyncMode VSyncMode public VSyncMode VSyncMode
{ {
get => _vSyncMode; get => _vSyncMode;
set set
{ {
if (value == VSyncMode.Custom || if (value is VSyncMode.Custom or VSyncMode.Switch or VSyncMode.Unbounded)
value == VSyncMode.Switch ||
value == VSyncMode.Unbounded)
{ {
_vSyncMode = value; _vSyncMode = value;
OnPropertyChanged(); OnPropertyChanged();
@ -181,19 +150,13 @@ namespace Ryujinx.Ava.UI.ViewModels
int newInterval = (int)((value / 100f) * 60); int newInterval = (int)((value / 100f) * 60);
_customVSyncInterval = newInterval; _customVSyncInterval = newInterval;
_customVSyncIntervalPercentageProxy = value; _customVSyncIntervalPercentageProxy = value;
OnPropertyChanged((nameof(CustomVSyncInterval))); OnPropertiesChanged(
OnPropertyChanged((nameof(CustomVSyncIntervalPercentageText))); nameof(CustomVSyncInterval),
nameof(CustomVSyncIntervalPercentageText));
} }
} }
public string CustomVSyncIntervalPercentageText public string CustomVSyncIntervalPercentageText => CustomVSyncIntervalPercentageProxy + "%";
{
get
{
string text = CustomVSyncIntervalPercentageProxy.ToString() + "%";
return text;
}
}
public bool EnableCustomVSyncInterval public bool EnableCustomVSyncInterval
{ {
@ -221,8 +184,9 @@ namespace Ryujinx.Ava.UI.ViewModels
_customVSyncInterval = value; _customVSyncInterval = value;
int newPercent = (int)((value / 60f) * 100); int newPercent = (int)((value / 60f) * 100);
_customVSyncIntervalPercentageProxy = newPercent; _customVSyncIntervalPercentageProxy = newPercent;
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy)); OnPropertiesChanged(
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText)); nameof(CustomVSyncIntervalPercentageProxy),
nameof(CustomVSyncIntervalPercentageText));
OnPropertyChanged(); OnPropertyChanged();
} }
} }
@ -236,7 +200,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnableTextureRecompression { get; set; } public bool EnableTextureRecompression { get; set; }
public bool EnableMacroHLE { get; set; } public bool EnableMacroHLE { get; set; }
public bool EnableColorSpacePassthrough { get; set; } public bool EnableColorSpacePassthrough { get; set; }
public bool ColorSpacePassthroughAvailable => IsMacOS; public bool ColorSpacePassthroughAvailable => RunningPlatform.IsMacOS;
public bool EnableFileLog { get; set; } public bool EnableFileLog { get; set; }
public bool EnableStub { get; set; } public bool EnableStub { get; set; }
public bool EnableInfo { get; set; } public bool EnableInfo { get; set; }
@ -245,6 +209,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnableTrace { get; set; } public bool EnableTrace { get; set; }
public bool EnableGuest { get; set; } public bool EnableGuest { get; set; }
public bool EnableFsAccessLog { get; set; } public bool EnableFsAccessLog { get; set; }
public bool EnableAvaloniaLog { get; set; }
public bool EnableDebug { get; set; } public bool EnableDebug { get; set; }
public bool IsOpenAlEnabled { get; set; } public bool IsOpenAlEnabled { get; set; }
public bool IsSoundIoEnabled { get; set; } public bool IsSoundIoEnabled { get; set; }
@ -252,10 +217,13 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool IsCustomResolutionScaleActive => _resolutionScale == 4; public bool IsCustomResolutionScaleActive => _resolutionScale == 4;
public bool IsScalingFilterActive => _scalingFilter == (int)Ryujinx.Common.Configuration.ScalingFilter.Fsr; public bool IsScalingFilterActive => _scalingFilter == (int)Ryujinx.Common.Configuration.ScalingFilter.Fsr;
public bool IsVulkanSelected => GraphicsBackendIndex == 0; public bool IsVulkanSelected =>
GraphicsBackendIndex == 1 || (GraphicsBackendIndex == 0 && !OperatingSystem.IsMacOS());
public bool UseHypervisor { get; set; } public bool UseHypervisor { get; set; }
public bool DisableP2P { get; set; } public bool DisableP2P { get; set; }
public bool ShowDirtyHacks => ConfigurationState.Instance.Hacks.ShowDirtyHacks;
public string TimeZone { get; set; } public string TimeZone { get; set; }
public string ShaderDumpPath { get; set; } public string ShaderDumpPath { get; set; }
@ -329,6 +297,8 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
[ObservableProperty] private bool _matchSystemTime;
public DateTimeOffset CurrentDate { get; set; } public DateTimeOffset CurrentDate { get; set; }
public TimeSpan CurrentTime { get; set; } public TimeSpan CurrentTime { get; set; }
@ -351,7 +321,6 @@ namespace Ryujinx.Ava.UI.ViewModels
set set
{ {
_networkInterfaceIndex = value != -1 ? value : 0; _networkInterfaceIndex = value != -1 ? value : 0;
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value = _networkInterfaces[NetworkInterfaceList[_networkInterfaceIndex]];
} }
} }
@ -361,32 +330,21 @@ namespace Ryujinx.Ava.UI.ViewModels
set set
{ {
_multiplayerModeIndex = value; _multiplayerModeIndex = value;
ConfigurationState.Instance.Multiplayer.Mode.Value = (MultiplayerMode)_multiplayerModeIndex;
} }
} }
[GeneratedRegex("Ryujinx-[0-9a-f]{8}")]
private static partial Regex LdnPassphraseRegex();
public bool IsInvalidLdnPassphraseVisible { get; set; } public bool IsInvalidLdnPassphraseVisible { get; set; }
public string LdnServer
{
get => _LdnServer;
set
{
_LdnServer = value;
OnPropertyChanged();
}
}
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this() public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
{ {
_virtualFileSystem = virtualFileSystem; _virtualFileSystem = virtualFileSystem;
_contentManager = contentManager; _contentManager = contentManager;
if (Program.PreviewerDetached) if (Program.PreviewerDetached)
{ {
Task.Run(LoadTimeZones); Task.Run(LoadTimeZones);
DirtyHacks = new SettingsHacksViewModel(this);
} }
} }
@ -406,6 +364,8 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
Task.Run(LoadAvailableGpus); Task.Run(LoadAvailableGpus);
LoadCurrentConfiguration(); LoadCurrentConfiguration();
DirtyHacks = new SettingsHacksViewModel(this);
} }
} }
@ -427,16 +387,16 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
AvailableGpus.Clear(); AvailableGpus.Clear();
var devices = VulkanRenderer.GetPhysicalDevices(); DeviceInfo[] devices = VulkanRenderer.GetPhysicalDevices();
if (devices.Length == 0) if (devices.Length == 0)
{ {
IsVulkanAvailable = false; IsVulkanAvailable = false;
GraphicsBackendIndex = 1; GraphicsBackendIndex = 2;
} }
else else
{ {
foreach (var device in devices) foreach (DeviceInfo device in devices)
{ {
await Dispatcher.UIThread.InvokeAsync(() => await Dispatcher.UIThread.InvokeAsync(() =>
{ {
@ -454,18 +414,6 @@ namespace Ryujinx.Ava.UI.ViewModels
Dispatcher.UIThread.Post(() => OnPropertyChanged(nameof(PreferredGpuIndex))); Dispatcher.UIThread.Post(() => OnPropertyChanged(nameof(PreferredGpuIndex)));
} }
public void MatchSystemTime()
{
var dto = DateTimeOffset.Now;
CurrentDate = new DateTimeOffset(dto.Year, dto.Month, dto.Day, 0, 0, 0, dto.Offset);
CurrentTime = dto.TimeOfDay;
OnPropertyChanged(nameof(CurrentDate));
OnPropertyChanged(nameof(CurrentTime));
}
public async Task LoadTimeZones() public async Task LoadTimeZones()
{ {
_timeZoneContentManager = new TimeZoneContentManager(); _timeZoneContentManager = new TimeZoneContentManager();
@ -511,7 +459,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private bool ValidateLdnPassphrase(string passphrase) private bool ValidateLdnPassphrase(string passphrase)
{ {
return string.IsNullOrEmpty(passphrase) || (passphrase.Length == 16 && LdnPassphraseRegex().IsMatch(passphrase)); return string.IsNullOrEmpty(passphrase) || (passphrase.Length == 16 && Patterns.LdnPassphrase.IsMatch(passphrase));
} }
public void ValidateAndSetTimeZone(string location) public void ValidateAndSetTimeZone(string location)
@ -530,10 +478,11 @@ 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;
UpdateCheckerType = (int)config.UpdateCheckerType.Value;
FocusLostActionType = (int)config.FocusLostActionType.Value;
GameDirectories.Clear(); GameDirectories.Clear();
GameDirectories.AddRange(config.UI.GameDirs.Value); GameDirectories.AddRange(config.UI.GameDirs.Value);
@ -553,6 +502,7 @@ namespace Ryujinx.Ava.UI.ViewModels
EnableDockedMode = config.System.EnableDockedMode; EnableDockedMode = config.System.EnableDockedMode;
EnableKeyboard = config.Hid.EnableKeyboard; EnableKeyboard = config.Hid.EnableKeyboard;
EnableMouse = config.Hid.EnableMouse; EnableMouse = config.Hid.EnableMouse;
DisableInputWhenOutOfFocus = config.Hid.DisableInputWhenOutOfFocus;
// Keyboard Hotkeys // Keyboard Hotkeys
KeyboardHotkey = new HotkeyConfig(config.Hid.Hotkeys.Value); KeyboardHotkey = new HotkeyConfig(config.Hid.Hotkeys.Value);
@ -568,12 +518,15 @@ namespace Ryujinx.Ava.UI.ViewModels
CurrentDate = currentDateTime.Date; CurrentDate = currentDateTime.Date;
CurrentTime = currentDateTime.TimeOfDay; CurrentTime = currentDateTime.TimeOfDay;
EnableCustomVSyncInterval = config.Graphics.EnableCustomVSyncInterval.Value; MatchSystemTime = config.System.MatchSystemTime;
EnableCustomVSyncInterval = config.Graphics.EnableCustomVSyncInterval;
CustomVSyncInterval = config.Graphics.CustomVSyncInterval; CustomVSyncInterval = config.Graphics.CustomVSyncInterval;
VSyncMode = config.Graphics.VSyncMode; VSyncMode = config.Graphics.VSyncMode;
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.IgnoreControllerApplet;
// CPU // CPU
EnablePptc = config.System.EnablePtc; EnablePptc = config.System.EnablePtc;
@ -616,13 +569,14 @@ namespace Ryujinx.Ava.UI.ViewModels
EnableGuest = config.Logger.EnableGuest; EnableGuest = config.Logger.EnableGuest;
EnableDebug = config.Logger.EnableDebug; EnableDebug = config.Logger.EnableDebug;
EnableFsAccessLog = config.Logger.EnableFsAccessLog; EnableFsAccessLog = config.Logger.EnableFsAccessLog;
EnableAvaloniaLog = config.Logger.EnableAvaloniaLog;
FsGlobalAccessLogMode = config.System.FsGlobalAccessLogMode; FsGlobalAccessLogMode = config.System.FsGlobalAccessLogMode;
OpenglDebugLevel = (int)config.Logger.GraphicsDebugLevel.Value; OpenglDebugLevel = (int)config.Logger.GraphicsDebugLevel.Value;
MultiplayerModeIndex = (int)config.Multiplayer.Mode.Value; MultiplayerModeIndex = (int)config.Multiplayer.Mode.Value;
DisableP2P = config.Multiplayer.DisableP2p.Value; DisableP2P = config.Multiplayer.DisableP2p;
LdnPassphrase = config.Multiplayer.LdnPassphrase.Value; LdnPassphrase = config.Multiplayer.LdnPassphrase;
LdnServer = config.Multiplayer.LdnServer.Value; LdnServer = config.Multiplayer.LdnServer;
} }
public void SaveSettings() public void SaveSettings()
@ -633,22 +587,13 @@ 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;
config.UpdateCheckerType.Value = (UpdaterType)UpdateCheckerType;
if (_gameDirectoryChanged) config.FocusLostActionType.Value = (FocusLostType)FocusLostActionType;
{ config.UI.GameDirs.Value = [..GameDirectories];
List<string> gameDirs = new(GameDirectories); config.UI.AutoloadDirs.Value = [..AutoloadDirectories];
config.UI.GameDirs.Value = gameDirs;
}
if (_autoloadDirectoryChanged)
{
List<string> autoloadDirs = new(AutoloadDirectories);
config.UI.AutoloadDirs.Value = autoloadDirs;
}
config.UI.BaseStyle.Value = BaseStyleIndex switch config.UI.BaseStyle.Value = BaseStyleIndex switch
{ {
@ -662,26 +607,29 @@ namespace Ryujinx.Ava.UI.ViewModels
config.System.EnableDockedMode.Value = EnableDockedMode; config.System.EnableDockedMode.Value = EnableDockedMode;
config.Hid.EnableKeyboard.Value = EnableKeyboard; config.Hid.EnableKeyboard.Value = EnableKeyboard;
config.Hid.EnableMouse.Value = EnableMouse; config.Hid.EnableMouse.Value = EnableMouse;
config.Hid.DisableInputWhenOutOfFocus.Value = DisableInputWhenOutOfFocus;
// Keyboard Hotkeys // Keyboard Hotkeys
config.Hid.Hotkeys.Value = KeyboardHotkey.GetConfig(); config.Hid.Hotkeys.Value = KeyboardHotkey.GetConfig();
// System // System
config.System.Region.Value = (Region)Region; config.System.Region.Value = (Region)Region;
if (config.System.Language.Value != (Language)Language)
GameListNeedsRefresh = true;
config.System.Language.Value = (Language)Language; config.System.Language.Value = (Language)Language;
if (_validTzRegions.Contains(TimeZone)) if (_validTzRegions.Contains(TimeZone))
{ {
config.System.TimeZone.Value = TimeZone; config.System.TimeZone.Value = TimeZone;
} }
config.System.MatchSystemTime.Value = MatchSystemTime;
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.IgnoreControllerApplet.Value = IgnoreApplet;
// CPU // CPU
config.System.EnablePtc.Value = EnablePptc; config.System.EnablePtc.Value = EnablePptc;
@ -690,6 +638,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;
@ -736,6 +687,7 @@ namespace Ryujinx.Ava.UI.ViewModels
config.Logger.EnableGuest.Value = EnableGuest; config.Logger.EnableGuest.Value = EnableGuest;
config.Logger.EnableDebug.Value = EnableDebug; config.Logger.EnableDebug.Value = EnableDebug;
config.Logger.EnableFsAccessLog.Value = EnableFsAccessLog; config.Logger.EnableFsAccessLog.Value = EnableFsAccessLog;
config.Logger.EnableAvaloniaLog.Value = EnableAvaloniaLog;
config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode; config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode;
config.Logger.GraphicsDebugLevel.Value = (GraphicsDebugLevel)OpenglDebugLevel; config.Logger.GraphicsDebugLevel.Value = (GraphicsDebugLevel)OpenglDebugLevel;
@ -744,16 +696,18 @@ namespace Ryujinx.Ava.UI.ViewModels
config.Multiplayer.DisableP2p.Value = DisableP2P; config.Multiplayer.DisableP2p.Value = DisableP2P;
config.Multiplayer.LdnPassphrase.Value = LdnPassphrase; config.Multiplayer.LdnPassphrase.Value = LdnPassphrase;
config.Multiplayer.LdnServer.Value = LdnServer; config.Multiplayer.LdnServer.Value = LdnServer;
// Dirty Hacks
config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix;
config.ToFileFormat().SaveConfig(Program.ConfigurationPath); config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
MainWindow.UpdateGraphicsConfig(); MainWindow.UpdateGraphicsConfig();
MainWindow.MainWindowViewModel.VSyncModeSettingChanged(); RyujinxApp.MainWindow.ViewModel.VSyncModeSettingChanged();
SaveSettingsEvent?.Invoke(); SaveSettingsEvent?.Invoke();
_gameDirectoryChanged = false; GameListNeedsRefresh = false;
_autoloadDirectoryChanged = false;
} }
private static void RevertIfNotSaved() private static void RevertIfNotSaved()
@ -772,6 +726,25 @@ namespace Ryujinx.Ava.UI.ViewModels
CloseWindow?.Invoke(); CloseWindow?.Invoke();
} }
[ObservableProperty] private bool _wantsToReset;
public AsyncRelayCommand ResetButton => Commands.Create(async () =>
{
if (!WantsToReset) return;
CloseWindow?.Invoke();
ConfigurationState.Instance.LoadDefault();
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
RyujinxApp.MainWindow.LoadApplications();
await ContentDialogHelper.CreateInfoDialog(
$"Your {RyujinxApp.FullAppName} configuration has been reset.",
"",
string.Empty,
LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
"Configuration Reset");
});
public void CancelButton() public void CancelButton()
{ {
RevertIfNotSaved(); RevertIfNotSaved();

View File

@ -6,6 +6,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup" xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
mc:Ignorable="d" mc:Ignorable="d"
x:DataType="viewModels:SettingsViewModel"> x:DataType="viewModels:SettingsViewModel">
<Design.DataContext> <Design.DataContext>
@ -69,7 +70,7 @@
</ComboBox> </ComboBox>
</StackPanel> </StackPanel>
<CheckBox IsChecked="{Binding UseHypervisor}" <CheckBox IsChecked="{Binding UseHypervisor}"
IsVisible="{Binding IsHypervisorAvailable}" IsVisible="{x:Static helper:RunningPlatform.IsArmMac}"
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}"> ToolTip.Tip="{ext:Locale UseHypervisorTooltip}">
<TextBlock Text="{ext:Locale SettingsTabSystemUseHypervisor}" <TextBlock Text="{ext:Locale SettingsTabSystemUseHypervisor}"
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}" /> ToolTip.Tip="{ext:Locale UseHypervisorTooltip}" />

View File

@ -43,39 +43,6 @@
Text="Xenoblade Chronicles 2 Menu Softlock Fix" /> Text="Xenoblade Chronicles 2 Menu Softlock Fix" />
</StackPanel> </StackPanel>
<Separator/> <Separator/>
<StackPanel
Margin="0,10,0,0"
Orientation="Horizontal"
HorizontalAlignment="Center"
ToolTip.Tip="{Binding DirtyHacks.ShaderTranslationDelayTooltip}">
<CheckBox
Margin="0"
IsChecked="{Binding DirtyHacks.ShaderTranslationDelayEnabled}"/>
<TextBlock VerticalAlignment="Center"
Text="Arbitrary Delay on Shader Translation"/>
</StackPanel>
<StackPanel
IsVisible="{Binding DirtyHacks.ShaderTranslationDelayEnabled}"
Margin="0,10,0,0"
Orientation="Horizontal"
HorizontalAlignment="Center">
<Slider HorizontalAlignment="Center"
Value="{Binding DirtyHacks.ShaderTranslationDelay}"
Width="175"
Margin="0,-3,0,0"
Height="32"
Padding="0,-5"
TickFrequency="1"
IsSnapToTickEnabled="True"
LargeChange="10"
SmallChange="1"
VerticalAlignment="Center"
Minimum="1"
Maximum="1000" />
<TextBlock Margin="5,0"
Text="{Binding DirtyHacks.ShaderTranslationDelayValueText}"/>
</StackPanel>
<Separator/>
</StackPanel> </StackPanel>
</Border> </Border>
</ScrollViewer> </ScrollViewer>

View File

@ -16,7 +16,6 @@ using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.Loaders.Processes.Extensions; using Ryujinx.HLE.Loaders.Processes.Extensions;
using System; using System;
using System.IO; using System.IO;
using System.Text;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Utilities.AppLibrary namespace Ryujinx.Ava.Utilities.AppLibrary