Compare commits

..

2 Commits

Author SHA1 Message Date
Evan Husted 1db417d652 Merge branch 'master' into patch-13 2024-12-30 21:04:44 -06:00
Hack茶ん ae1fea3597 Korean translation update
......
2024-12-29 23:08:14 +09:00
22 changed files with 688 additions and 356 deletions
+35
View File
@@ -0,0 +1,35 @@
namespace Ryujinx.Common
{
public class BitTricks
{
// Never actually written bit packing logic before, so I looked it up.
// This code is from https://gist.github.com/Alan-FGR/04938e93e2bffdf5802ceb218a37c195
public static ulong PackBitFields(uint[] values, byte[] bitFields)
{
ulong retVal = values[0]; //we set the first value right away
for (int f = 1; f < values.Length; f++)
{
retVal <<= bitFields[f]; // we shift the previous value
retVal += values[f];// and add our current value
}
return retVal;
}
public static uint[] UnpackBitFields(ulong packed, byte[] bitFields)
{
int fields = bitFields.Length - 1; // number of fields to unpack
uint[] retArr = new uint[fields + 1]; // init return array
int curPos = 0; // current field bit position (start)
int lastEnd; // position where last field ended
for (int f = fields; f >= 0; f--) // loop from last
{
lastEnd = curPos; // we store where the last value ended
curPos += bitFields[f]; // we get where the current value starts
int leftShift = 64 - curPos; // we figure how much left shift we gotta apply for the other numbers to overflow into oblivion
retArr[f] = (uint)((packed << leftShift) >> leftShift + lastEnd); // we do magic
}
return retArr;
}
}
}
@@ -1,60 +0,0 @@
using Gommon;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.Common.Configuration
{
[Flags]
public enum DirtyHack : byte
{
Xc2MenuSoftlockFix = 1,
ShaderTranslationDelay = 2
}
public readonly struct EnabledDirtyHack(DirtyHack hack, int value)
{
public DirtyHack Hack => hack;
public int Value => value;
public ulong Pack() => Raw.PackBitFields(PackedFormat);
public static EnabledDirtyHack Unpack(ulong packedHack)
{
var unpackedFields = packedHack.UnpackBitFields(PackedFormat);
if (unpackedFields is not [var hack, var value])
throw new ArgumentException(nameof(packedHack));
return new EnabledDirtyHack((DirtyHack)hack, (int)value);
}
private uint[] Raw => [(uint)Hack, (uint)Value.CoerceAtLeast(0)];
public static readonly byte[] PackedFormat = [8, 32];
}
public class DirtyHacks : Dictionary<DirtyHack, int>
{
public DirtyHacks(IEnumerable<EnabledDirtyHack> hacks)
=> hacks.ForEach(edh => Add(edh.Hack, edh.Value));
public DirtyHacks(ulong[] packedHacks) : this(packedHacks.Select(EnabledDirtyHack.Unpack)) {}
public ulong[] PackEntries()
=> Entries.Select(it => it.Pack()).ToArray();
public EnabledDirtyHack[] Entries
=> this
.Select(it => new EnabledDirtyHack(it.Key, it.Value))
.ToArray();
public static implicit operator DirtyHacks(EnabledDirtyHack[] hacks) => new(hacks);
public static implicit operator DirtyHacks(ulong[] packedHacks) => new(packedHacks);
public new int this[DirtyHack hack] => TryGetValue(hack, out var value) ? value : -1;
public bool IsEnabled(DirtyHack hack) => ContainsKey(hack);
}
}
@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.Common.Configuration
{
[Flags]
public enum DirtyHacks : byte
{
Xc2MenuSoftlockFix = 1,
ShaderCompilationThreadSleep = 2
}
public record EnabledDirtyHack(DirtyHacks Hack, int Value)
{
public static readonly byte[] PackedFormat = [8, 32];
public ulong Pack() => BitTricks.PackBitFields([(uint)Hack, (uint)Value], PackedFormat);
public static EnabledDirtyHack Unpack(ulong packedHack)
{
var unpackedFields = BitTricks.UnpackBitFields(packedHack, PackedFormat);
if (unpackedFields is not [var hack, var value])
throw new ArgumentException(nameof(packedHack));
return new EnabledDirtyHack((DirtyHacks)hack, (int)value);
}
}
public class DirtyHackCollection : Dictionary<DirtyHacks, int>
{
public DirtyHackCollection(EnabledDirtyHack[] hacks)
{
foreach ((DirtyHacks dirtyHacks, int value) in hacks)
{
Add(dirtyHacks, value);
}
}
public DirtyHackCollection(ulong[] packedHacks)
{
foreach ((DirtyHacks dirtyHacks, int value) in packedHacks.Select(EnabledDirtyHack.Unpack))
{
Add(dirtyHacks, value);
}
}
public ulong[] PackEntries() =>
this
.Select(it =>
BitTricks.PackBitFields([(uint)it.Key, (uint)it.Value], EnabledDirtyHack.PackedFormat))
.ToArray();
public static implicit operator DirtyHackCollection(EnabledDirtyHack[] hacks) => new(hacks);
public static implicit operator DirtyHackCollection(ulong[] packedHacks) => new(packedHacks);
public new int this[DirtyHacks hack] => TryGetValue(hack, out var value) ? value : -1;
public bool IsEnabled(DirtyHacks hack) => ContainsKey(hack);
}
}
-30
View File
@@ -40,35 +40,5 @@ namespace Ryujinx.Common
return (value >> 32) | (value << 32); return (value >> 32) | (value << 32);
} }
// Never actually written bit packing logic before, so I looked it up.
// This code is from https://gist.github.com/Alan-FGR/04938e93e2bffdf5802ceb218a37c195
public static ulong PackBitFields(this uint[] values, byte[] bitFields)
{
ulong retVal = values[0]; //we set the first value right away
for (int f = 1; f < values.Length; f++)
{
retVal <<= bitFields[f]; // we shift the previous value
retVal += values[f];// and add our current value
}
return retVal;
}
public static uint[] UnpackBitFields(this ulong packed, byte[] bitFields)
{
int fields = bitFields.Length - 1; // number of fields to unpack
uint[] retArr = new uint[fields + 1]; // init return array
int curPos = 0; // current field bit position (start)
int lastEnd; // position where last field ended
for (int f = fields; f >= 0; f--) // loop from last
{
lastEnd = curPos; // we store where the last value ended
curPos += bitFields[f]; // we get where the current value starts
int leftShift = 64 - curPos; // we figure how much left shift we gotta apply for the other numbers to overflow into oblivion
retArr[f] = (uint)((packed << leftShift) >> leftShift + lastEnd); // we do magic
}
return retArr;
}
} }
} }
+3 -7
View File
@@ -92,11 +92,7 @@ namespace Ryujinx.Graphics.Gpu
/// </summary> /// </summary>
internal SupportBufferUpdater SupportBufferUpdater { get; } internal SupportBufferUpdater SupportBufferUpdater { get; }
/// <summary> internal DirtyHackCollection DirtyHacks { get; }
/// Enabled dirty hacks.
/// Used for workarounds to emulator bugs we can't fix/don't know how to fix yet.
/// </summary>
internal DirtyHacks DirtyHacks { get; }
/// <summary> /// <summary>
@@ -121,7 +117,7 @@ namespace Ryujinx.Graphics.Gpu
/// Creates a new instance of the GPU emulation context. /// Creates a new instance of the GPU emulation context.
/// </summary> /// </summary>
/// <param name="renderer">Host renderer</param> /// <param name="renderer">Host renderer</param>
public GpuContext(IRenderer renderer, DirtyHacks hacks) public GpuContext(IRenderer renderer, DirtyHackCollection hackCollection)
{ {
Renderer = renderer; Renderer = renderer;
@@ -144,7 +140,7 @@ namespace Ryujinx.Graphics.Gpu
SupportBufferUpdater = new SupportBufferUpdater(renderer); SupportBufferUpdater = new SupportBufferUpdater(renderer);
DirtyHacks = hacks; DirtyHacks = hackCollection;
_firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds); _firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
} }
@@ -367,8 +367,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
{ {
try try
{ {
if (_context.DirtyHacks.IsEnabled(DirtyHack.ShaderTranslationDelay)) if (_context.DirtyHacks.IsEnabled(DirtyHacks.ShaderCompilationThreadSleep))
Thread.Sleep(_context.DirtyHacks[DirtyHack.ShaderTranslationDelay]); Thread.Sleep(_context.DirtyHacks[DirtyHacks.ShaderCompilationThreadSleep]);
AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute); AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute);
_asyncTranslationQueue.Add(asyncTranslation, _cancellationToken); _asyncTranslationQueue.Add(asyncTranslation, _cancellationToken);
@@ -39,7 +39,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
using var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true); using var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true);
Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size); Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size);
if (context.Device.DirtyHacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix) && TitleIDs.CurrentApplication.Value == Xc2TitleId) if (context.Device.DirtyHacks.IsEnabled(DirtyHacks.Xc2MenuSoftlockFix) && TitleIDs.CurrentApplication.Value == Xc2TitleId)
{ {
// Add a load-bearing sleep to avoid XC2 softlock // Add a load-bearing sleep to avoid XC2 softlock
// https://web.archive.org/web/20240728045136/https://github.com/Ryujinx/Ryujinx/issues/2357 // https://web.archive.org/web/20240728045136/https://github.com/Ryujinx/Ryujinx/issues/2357
+2 -2
View File
@@ -40,7 +40,7 @@ namespace Ryujinx.HLE
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable; public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
public DirtyHacks DirtyHacks { get; } public DirtyHackCollection DirtyHacks { get; }
public Switch(HLEConfiguration configuration) public Switch(HLEConfiguration configuration)
{ {
@@ -57,7 +57,7 @@ namespace Ryujinx.HLE
: MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Mirrorable; : MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Mirrorable;
#pragma warning disable IDE0055 // Disable formatting #pragma warning disable IDE0055 // Disable formatting
DirtyHacks = new DirtyHacks(Configuration.Hacks); DirtyHacks = new DirtyHackCollection(Configuration.Hacks);
AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver); AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver);
Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags); Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags);
Gpu = new GpuContext(Configuration.GpuRenderer, DirtyHacks); Gpu = new GpuContext(Configuration.GpuRenderer, DirtyHacks);
@@ -15,6 +15,7 @@
x:DataType="viewModels:MainWindowViewModel"> x:DataType="viewModels:MainWindowViewModel">
<UserControl.Resources> <UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" /> <helpers:BitmapArrayValueConverter x:Key="ByteImage" />
<controls:ApplicationContextMenu x:Key="ApplicationContextMenu" />
</UserControl.Resources> </UserControl.Resources>
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
@@ -25,10 +26,10 @@
Padding="8" Padding="8"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
SelectedItem="{Binding GridSelectedApplication}" ContextFlyout="{StaticResource ApplicationContextMenu}"
ContextFlyout="{Binding GridAppContextMenu}"
DoubleTapped="GameList_DoubleTapped" DoubleTapped="GameList_DoubleTapped"
ItemsSource="{Binding AppsObservableList}"> ItemsSource="{Binding AppsObservableList}"
SelectionChanged="GameList_SelectionChanged">
<ListBox.ItemsPanel> <ListBox.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<WrapPanel <WrapPanel
@@ -26,5 +26,11 @@ namespace Ryujinx.Ava.UI.Controls
if (sender is ListBox { SelectedItem: ApplicationData selected }) if (sender is ListBox { SelectedItem: ApplicationData selected })
RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent)); RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent));
} }
public void GameList_SelectionChanged(object sender, SelectionChangedEventArgs args)
{
if (DataContext is MainWindowViewModel viewModel && sender is ListBox { SelectedItem: ApplicationData selected })
viewModel.GridSelectedApplication = selected;
}
} }
} }
@@ -7,6 +7,7 @@
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
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:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:converters="clr-namespace:Avalonia.Data.Converters;assembly=Avalonia.Base"
d:DesignHeight="450" d:DesignHeight="450"
d:DesignWidth="800" d:DesignWidth="800"
Focusable="True" Focusable="True"
@@ -15,6 +16,7 @@
x:DataType="viewModels:MainWindowViewModel"> x:DataType="viewModels:MainWindowViewModel">
<UserControl.Resources> <UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" /> <helpers:BitmapArrayValueConverter x:Key="ByteImage" />
<controls:ApplicationContextMenu x:Key="ApplicationContextMenu" />
</UserControl.Resources> </UserControl.Resources>
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
@@ -26,10 +28,10 @@
Padding="8" Padding="8"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
SelectedItem="{Binding ListSelectedApplication}" ContextFlyout="{StaticResource ApplicationContextMenu}"
ContextFlyout="{Binding ListAppContextMenu}"
DoubleTapped="GameList_DoubleTapped" DoubleTapped="GameList_DoubleTapped"
ItemsSource="{Binding AppsObservableList}"> ItemsSource="{Binding AppsObservableList}"
SelectionChanged="GameList_SelectionChanged">
<ListBox.ItemsPanel> <ListBox.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<StackPanel <StackPanel
@@ -30,6 +30,12 @@ namespace Ryujinx.Ava.UI.Controls
RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent)); RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent));
} }
public void GameList_SelectionChanged(object sender, SelectionChangedEventArgs args)
{
if (DataContext is MainWindowViewModel viewModel && sender is ListBox { SelectedItem: ApplicationData selected })
viewModel.ListSelectedApplication = selected;
}
private async void IdString_OnClick(object sender, RoutedEventArgs e) private async void IdString_OnClick(object sender, RoutedEventArgs e)
{ {
if (DataContext is not MainWindowViewModel mwvm) if (DataContext is not MainWindowViewModel mwvm)
@@ -93,7 +93,10 @@ namespace Ryujinx.Ava.UI.ViewModels
_applicationData = applicationData; _applicationData = applicationData;
_storageProvider = RyujinxApp.MainWindow.StorageProvider; if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
_storageProvider = desktop.MainWindow.StorageProvider;
}
LoadDownloadableContents(); LoadDownloadableContents();
} }
@@ -245,7 +245,9 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
{ {
if (Program.PreviewerDetached) if (Program.PreviewerDetached)
{ {
_mainWindow = RyujinxApp.MainWindow; _mainWindow =
(MainWindow)((IClassicDesktopStyleApplicationLifetime)Application.Current
.ApplicationLifetime).MainWindow;
AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner); AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner);
@@ -123,42 +123,8 @@ namespace Ryujinx.Ava.UI.ViewModels
private bool _isActive; private bool _isActive;
private bool _isSubMenuOpen; private bool _isSubMenuOpen;
private ApplicationData _listSelectedApplication; public ApplicationData ListSelectedApplication;
private ApplicationData _gridSelectedApplication; public ApplicationData GridSelectedApplication;
private ApplicationContextMenu _listAppContextMenu;
private ApplicationContextMenu _gridAppContextMenu;
public ApplicationData ListSelectedApplication
{
get => _listSelectedApplication;
set
{
_listSelectedApplication = value;
if (_listSelectedApplication != null && _listAppContextMenu == null)
ListAppContextMenu = new ApplicationContextMenu();
else if (_listSelectedApplication == null && _listAppContextMenu != null)
ListAppContextMenu = null;
OnPropertyChanged();
}
}
public ApplicationData GridSelectedApplication
{
get => _gridSelectedApplication;
set
{
_gridSelectedApplication = value;
if (_gridSelectedApplication != null && _gridAppContextMenu == null)
GridAppContextMenu = new ApplicationContextMenu();
else if (_gridSelectedApplication == null && _gridAppContextMenu != null)
GridAppContextMenu = null;
OnPropertyChanged();
}
}
// Key is Title ID // Key is Title ID
public SafeDictionary<string, LdnGameData.Array> LdnData = []; public SafeDictionary<string, LdnGameData.Array> LdnData = [];
@@ -252,7 +218,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool CanUpdate public bool CanUpdate
{ {
get => _canUpdate && EnableNonGameRunningControls && Updater.CanUpdate(); get => _canUpdate && EnableNonGameRunningControls && Updater.CanUpdate(false);
set set
{ {
_canUpdate = value; _canUpdate = value;
@@ -281,28 +247,6 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public ApplicationContextMenu ListAppContextMenu
{
get => _listAppContextMenu;
set
{
_listAppContextMenu = value;
OnPropertyChanged();
}
}
public ApplicationContextMenu GridAppContextMenu
{
get => _gridAppContextMenu;
set
{
_gridAppContextMenu = value;
OnPropertyChanged();
}
}
public bool IsPaused public bool IsPaused
{ {
get => _isPaused; get => _isPaused;
@@ -474,13 +418,13 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public bool OpenUserSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0; public bool OpenUserSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0;
public bool OpenDeviceSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0; public bool OpenDeviceSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0;
public bool TrimXCIEnabled => XCIFileTrimmer.CanTrim(SelectedApplication.Path, new XCITrimmerLog.MainWindow(this)); public bool TrimXCIEnabled => XCIFileTrimmer.CanTrim(SelectedApplication.Path, new XCITrimmerLog.MainWindow(this));
public bool OpenBcatSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0; public bool OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
public string LoadHeading public string LoadHeading
{ {
@@ -86,7 +86,10 @@ namespace Ryujinx.Ava.UI.ViewModels
_modJsonPath = Path.Combine(AppDataManager.GamesDirPath, applicationId.ToString("x16"), "mods.json"); _modJsonPath = Path.Combine(AppDataManager.GamesDirPath, applicationId.ToString("x16"), "mods.json");
_storageProvider = RyujinxApp.MainWindow.StorageProvider; if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
_storageProvider = desktop.MainWindow.StorageProvider;
}
LoadMods(applicationId); LoadMods(applicationId);
} }
@@ -76,7 +76,10 @@ namespace Ryujinx.Ava.UI.ViewModels
ApplicationData = applicationData; ApplicationData = applicationData;
StorageProvider = RyujinxApp.MainWindow.StorageProvider; if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
StorageProvider = desktop.MainWindow.StorageProvider;
}
LoadUpdates(); LoadUpdates();
} }
@@ -41,7 +41,7 @@ namespace Ryujinx.Ava.UI.Views.Main
private void VSyncMode_PointerReleased(object sender, PointerReleasedEventArgs e) private void VSyncMode_PointerReleased(object sender, PointerReleasedEventArgs e)
{ {
Window.ViewModel.ToggleVSyncMode(); Window.ViewModel.ToggleVSyncMode();
Logger.Info?.PrintMsg(LogClass.Application, $"VSync Mode toggled to: {Window.ViewModel.AppHost.Device.VSyncMode}"); Logger.Info?.Print(LogClass.Application, $"VSync Mode toggled to: {Window.ViewModel.AppHost.Device.VSyncMode}");
} }
private void DockedStatus_PointerReleased(object sender, PointerReleasedEventArgs e) private void DockedStatus_PointerReleased(object sender, PointerReleasedEventArgs e)
@@ -33,7 +33,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
public string Path { get; set; } public string Path { get; set; }
public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; } public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; }
public bool HasControlHolder => ControlHolder.ByteSpan.Length > 0 && !ControlHolder.ByteSpan.IsZeros(); public bool HasControlHolder => ControlHolder.ByteSpan.Length > 0;
public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed); public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed);
@@ -272,7 +272,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
public MemoryManagerMode MemoryManagerMode { get; set; } public MemoryManagerMode MemoryManagerMode { get; set; }
/// <summary> /// <summary>
/// Expands the RAM amount on the emulated system /// Expands the RAM amount on the emulated system from 4GiB to 8GiB
/// </summary> /// </summary>
public MemoryConfiguration DramSize { get; set; } public MemoryConfiguration DramSize { get; set; }
@@ -1,4 +1,3 @@
using Gommon;
using Ryujinx.Ava.Utilities.Configuration.System; using Ryujinx.Ava.Utilities.Configuration.System;
using Ryujinx.Ava.Utilities.Configuration.UI; using Ryujinx.Ava.Utilities.Configuration.UI;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
@@ -9,6 +8,7 @@ using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE; using Ryujinx.HLE;
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace Ryujinx.Ava.Utilities.Configuration namespace Ryujinx.Ava.Utilities.Configuration
@@ -17,7 +17,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
{ {
public void Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath) public void Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath)
{ {
// referenced by Migrate
bool configurationFileUpdated = false; bool configurationFileUpdated = false;
if (configurationFileFormat.Version is < 0 or > ConfigurationFileFormat.CurrentVersion) if (configurationFileFormat.Version is < 0 or > ConfigurationFileFormat.CurrentVersion)
@@ -26,48 +25,174 @@ namespace Ryujinx.Ava.Utilities.Configuration
LoadDefault(); LoadDefault();
} }
Migrate(2, static cff => cff.SystemRegion = Region.USA); if (configurationFileFormat.Version < 2)
Migrate(3, static cff => cff.SystemTimeZone = "UTC");
Migrate(4, static cff => cff.MaxAnisotropy = -1);
Migrate(5, static cff => cff.SystemTimeOffset = 0);
Migrate(8, static cff => cff.EnablePtc = true);
Migrate(9, static cff =>
{ {
cff.ColumnSort = new ColumnSort Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 2.");
configurationFileFormat.SystemRegion = Region.USA;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 3)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 3.");
configurationFileFormat.SystemTimeZone = "UTC";
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 4)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 4.");
configurationFileFormat.MaxAnisotropy = -1;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 5)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 5.");
configurationFileFormat.SystemTimeOffset = 0;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 8)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 8.");
configurationFileFormat.EnablePtc = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 9)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 9.");
configurationFileFormat.ColumnSort = new ColumnSort
{ {
SortColumnId = 0, SortColumnId = 0,
SortAscending = false SortAscending = false,
}; };
cff.Hotkeys = new KeyboardHotkeys { ToggleVSyncMode = Key.F1 }; configurationFileFormat.Hotkeys = new KeyboardHotkeys
}); {
Migrate(10, static cff => cff.AudioBackend = AudioBackend.OpenAl); ToggleVSyncMode = Key.F1,
Migrate(11, static cff => };
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 10)
{ {
cff.ResScale = 1; Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 10.");
cff.ResScaleCustom = 1.0f;
}); configurationFileFormat.AudioBackend = AudioBackend.OpenAl;
Migrate(12, static cff => cff.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None);
// 13 -> LDN1 configurationFileUpdated = true;
Migrate(14, static cff => cff.CheckUpdatesOnStart = true); }
Migrate(16, static cff => cff.EnableShaderCache = true);
Migrate(17, static cff => cff.StartFullscreen = false); if (configurationFileFormat.Version < 11)
Migrate(18, static cff => cff.AspectRatio = AspectRatio.Fixed16x9);
// 19 -> LDN2
Migrate(20, static cff => cff.ShowConfirmExit = true);
Migrate(21, static cff =>
{ {
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 11.");
configurationFileFormat.ResScale = 1;
configurationFileFormat.ResScaleCustom = 1.0f;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 12)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 12.");
configurationFileFormat.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None;
configurationFileUpdated = true;
}
// configurationFileFormat.Version == 13 -> LDN1
if (configurationFileFormat.Version < 14)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 14.");
configurationFileFormat.CheckUpdatesOnStart = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 16)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 16.");
configurationFileFormat.EnableShaderCache = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 17)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 17.");
configurationFileFormat.StartFullscreen = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 18)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 18.");
configurationFileFormat.AspectRatio = AspectRatio.Fixed16x9;
configurationFileUpdated = true;
}
// configurationFileFormat.Version == 19 -> LDN2
if (configurationFileFormat.Version < 20)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 20.");
configurationFileFormat.ShowConfirmExit = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 21)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 21.");
// Initialize network config. // Initialize network config.
cff.MultiplayerMode = MultiplayerMode.Disabled; configurationFileFormat.MultiplayerMode = MultiplayerMode.Disabled;
cff.MultiplayerLanInterfaceId = "0"; configurationFileFormat.MultiplayerLanInterfaceId = "0";
});
Migrate(22, static cff => cff.HideCursor = HideCursorMode.Never); configurationFileUpdated = true;
Migrate(24, static cff => }
if (configurationFileFormat.Version < 22)
{ {
cff.InputConfig = Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22.");
[
configurationFileFormat.HideCursor = HideCursorMode.Never;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 24)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 24.");
configurationFileFormat.InputConfig = new List<InputConfig>
{
new StandardKeyboardInputConfig new StandardKeyboardInputConfig
{ {
Version = InputConfig.CurrentVersion, Version = InputConfig.CurrentVersion,
@@ -115,21 +240,69 @@ namespace Ryujinx.Ava.Utilities.Configuration
StickRight = Key.L, StickRight = Key.L,
StickButton = Key.H, StickButton = Key.H,
}, },
} },
};
]; configurationFileUpdated = true;
}); }
Migrate(26, static cff => cff.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe);
Migrate(27, static cff => cff.EnableMouse = false); if (configurationFileFormat.Version < 25)
Migrate(29, static cff => cff.Hotkeys = new KeyboardHotkeys
{ {
ToggleVSyncMode = Key.F1, Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 25.");
Screenshot = Key.F8,
ShowUI = Key.F4 configurationFileUpdated = true;
}); }
Migrate(30, static cff =>
if (configurationFileFormat.Version < 26)
{ {
foreach (InputConfig config in cff.InputConfig) Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 26.");
configurationFileFormat.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 27)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 27.");
configurationFileFormat.EnableMouse = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 28)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 28.");
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = Key.F1,
Screenshot = Key.F8,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 29)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 29.");
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = Key.F1,
Screenshot = Key.F8,
ShowUI = Key.F4,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 30)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 30.");
foreach (InputConfig config in configurationFileFormat.InputConfig)
{ {
if (config is StandardControllerInputConfig controllerConfig) if (config is StandardControllerInputConfig controllerConfig)
{ {
@@ -141,144 +314,342 @@ namespace Ryujinx.Ava.Utilities.Configuration
}; };
} }
} }
});
Migrate(31, static cff => cff.BackendThreading = BackendThreading.Auto); configurationFileUpdated = true;
Migrate(32, static cff => cff.Hotkeys = new KeyboardHotkeys }
if (configurationFileFormat.Version < 31)
{ {
ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode, Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 31.");
Screenshot = cff.Hotkeys.Screenshot,
ShowUI = cff.Hotkeys.ShowUI, configurationFileFormat.BackendThreading = BackendThreading.Auto;
Pause = Key.F5,
}); configurationFileUpdated = true;
Migrate(33, static cff => }
if (configurationFileFormat.Version < 32)
{ {
cff.Hotkeys = new KeyboardHotkeys Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 32.");
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode, ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
Screenshot = cff.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = cff.Hotkeys.ShowUI, ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = cff.Hotkeys.Pause, Pause = Key.F5,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 33)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 33.");
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = Key.F2, ToggleMute = Key.F2,
}; };
cff.AudioVolume = 1; configurationFileFormat.AudioVolume = 1;
});
Migrate(34, static cff => cff.EnableInternetAccess = false); configurationFileUpdated = true;
Migrate(35, static cff => }
if (configurationFileFormat.Version < 34)
{ {
foreach (StandardControllerInputConfig config in cff.InputConfig.OfType<StandardControllerInputConfig>()) Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 34.");
configurationFileFormat.EnableInternetAccess = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 35)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 35.");
foreach (InputConfig config in configurationFileFormat.InputConfig)
{ {
config.RangeLeft = 1.0f; if (config is StandardControllerInputConfig controllerConfig)
config.RangeRight = 1.0f; {
controllerConfig.RangeLeft = 1.0f;
controllerConfig.RangeRight = 1.0f;
}
} }
});
configurationFileUpdated = true;
Migrate(36, static cff => cff.LoggingEnableTrace = false); }
Migrate(37, static cff => cff.ShowConsole = true);
Migrate(38, static cff => if (configurationFileFormat.Version < 36)
{ {
cff.BaseStyle = "Dark"; Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 36.");
cff.GameListViewMode = 0;
cff.ShowNames = true; configurationFileFormat.LoggingEnableTrace = false;
cff.GridSize = 2;
cff.LanguageCode = "en_US"; configurationFileUpdated = true;
}); }
Migrate(39, static cff => cff.Hotkeys = new KeyboardHotkeys
if (configurationFileFormat.Version < 37)
{ {
ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode, Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 37.");
Screenshot = cff.Hotkeys.Screenshot,
ShowUI = cff.Hotkeys.ShowUI, configurationFileFormat.ShowConsole = true;
Pause = cff.Hotkeys.Pause,
ToggleMute = cff.Hotkeys.ToggleMute, configurationFileUpdated = true;
ResScaleUp = Key.Unbound, }
ResScaleDown = Key.Unbound
}); if (configurationFileFormat.Version < 38)
Migrate(40, static cff => cff.GraphicsBackend = GraphicsBackend.OpenGl);
Migrate(41, static cff => cff.Hotkeys = new KeyboardHotkeys
{ {
ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode, Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 38.");
Screenshot = cff.Hotkeys.Screenshot,
ShowUI = cff.Hotkeys.ShowUI, configurationFileFormat.BaseStyle = "Dark";
Pause = cff.Hotkeys.Pause, configurationFileFormat.GameListViewMode = 0;
ToggleMute = cff.Hotkeys.ToggleMute, configurationFileFormat.ShowNames = true;
ResScaleUp = cff.Hotkeys.ResScaleUp, configurationFileFormat.GridSize = 2;
ResScaleDown = cff.Hotkeys.ResScaleDown, configurationFileFormat.LanguageCode = "en_US";
VolumeUp = Key.Unbound,
VolumeDown = Key.Unbound configurationFileUpdated = true;
}); }
Migrate(42, static cff => cff.EnableMacroHLE = true);
Migrate(43, static cff => cff.UseHypervisor = true); if (configurationFileFormat.Version < 39)
Migrate(44, static cff =>
{ {
cff.AntiAliasing = AntiAliasing.None; Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 39.");
cff.ScalingFilter = ScalingFilter.Bilinear;
cff.ScalingFilterLevel = 80; configurationFileFormat.Hotkeys = new KeyboardHotkeys
}); {
Migrate(45, static cff => cff.ShownFileTypes = new ShownFileTypes ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
ResScaleUp = Key.Unbound,
ResScaleDown = Key.Unbound,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 40)
{ {
NSP = true, Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 40.");
PFS0 = true,
XCI = true, configurationFileFormat.GraphicsBackend = GraphicsBackend.OpenGl;
NCA = true,
NRO = true, configurationFileUpdated = true;
NSO = true }
});
Migrate(46, static cff => cff.UseHypervisor = OperatingSystem.IsMacOS()); if (configurationFileFormat.Version < 41)
Migrate(47, static cff => cff.WindowStartup = new WindowStartup
{ {
WindowPositionX = 0, Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 41.");
WindowPositionY = 0,
WindowSizeHeight = 760, configurationFileFormat.Hotkeys = new KeyboardHotkeys
WindowSizeWidth = 1280, {
WindowMaximized = false ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
}); Screenshot = configurationFileFormat.Hotkeys.Screenshot,
Migrate(48, static cff => cff.EnableColorSpacePassthrough = false); ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Migrate(49, static _ => Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
VolumeUp = Key.Unbound,
VolumeDown = Key.Unbound,
};
}
if (configurationFileFormat.Version < 42)
{ {
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 42.");
configurationFileFormat.EnableMacroHLE = true;
}
if (configurationFileFormat.Version < 43)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 43.");
configurationFileFormat.UseHypervisor = true;
}
if (configurationFileFormat.Version < 44)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 44.");
configurationFileFormat.AntiAliasing = AntiAliasing.None;
configurationFileFormat.ScalingFilter = ScalingFilter.Bilinear;
configurationFileFormat.ScalingFilterLevel = 80;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 45)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 45.");
configurationFileFormat.ShownFileTypes = new ShownFileTypes
{
NSP = true,
PFS0 = true,
XCI = true,
NCA = true,
NRO = true,
NSO = true,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 46)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 46.");
configurationFileFormat.MultiplayerLanInterfaceId = "0";
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 47)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 47.");
configurationFileFormat.WindowStartup = new WindowStartup
{
WindowPositionX = 0,
WindowPositionY = 0,
WindowSizeHeight = 760,
WindowSizeWidth = 1280,
WindowMaximized = false,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 48)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 48.");
configurationFileFormat.EnableColorSpacePassthrough = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 49)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 49.");
if (OperatingSystem.IsMacOS()) if (OperatingSystem.IsMacOS())
{ {
AppDataManager.FixMacOSConfigurationFolders(); AppDataManager.FixMacOSConfigurationFolders();
} }
});
Migrate(50, static cff => cff.EnableHardwareAcceleration = true);
Migrate(51, static cff => cff.RememberWindowState = true);
Migrate(52, static cff => cff.AutoloadDirs = []);
Migrate(53, static cff => cff.EnableLowPowerPtc = false);
Migrate(54, static cff => cff.DramSize = MemoryConfiguration.MemoryConfiguration4GiB);
Migrate(55, static cff => cff.IgnoreApplet = false);
Migrate(56, static cff => cff.ShowTitleBar = !OperatingSystem.IsWindows());
Migrate(57, static cff =>
{
cff.VSyncMode = VSyncMode.Switch;
cff.EnableCustomVSyncInterval = false;
cff.Hotkeys = new KeyboardHotkeys configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 50)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 50.");
configurationFileFormat.EnableHardwareAcceleration = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 51)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 51.");
configurationFileFormat.RememberWindowState = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 52)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 52.");
configurationFileFormat.AutoloadDirs = [];
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 53)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 53.");
configurationFileFormat.EnableLowPowerPtc = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 54)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 54.");
configurationFileFormat.DramSize = MemoryConfiguration.MemoryConfiguration4GiB;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 55)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 55.");
configurationFileFormat.IgnoreApplet = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 56)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 56.");
configurationFileFormat.ShowTitleBar = !OperatingSystem.IsWindows();
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 57)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 57.");
configurationFileFormat.VSyncMode = VSyncMode.Switch;
configurationFileFormat.EnableCustomVSyncInterval = false;
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVSyncMode = Key.F1, ToggleVSyncMode = Key.F1,
Screenshot = cff.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = cff.Hotkeys.ShowUI, ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = cff.Hotkeys.Pause, Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = cff.Hotkeys.ToggleMute, ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
ResScaleUp = cff.Hotkeys.ResScaleUp, ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
ResScaleDown = cff.Hotkeys.ResScaleDown, ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
VolumeUp = cff.Hotkeys.VolumeUp, VolumeUp = configurationFileFormat.Hotkeys.VolumeUp,
VolumeDown = cff.Hotkeys.VolumeDown, VolumeDown = configurationFileFormat.Hotkeys.VolumeDown,
CustomVSyncIntervalIncrement = Key.Unbound, CustomVSyncIntervalIncrement = Key.Unbound,
CustomVSyncIntervalDecrement = Key.Unbound, CustomVSyncIntervalDecrement = Key.Unbound,
}; };
cff.CustomVSyncInterval = 120; configurationFileFormat.CustomVSyncInterval = 120;
});
// 58 migration accidentally got skipped but it worked with no issues somehow lol
Migrate(59, static cff =>
{
cff.ShowDirtyHacks = false;
cff.DirtyHacks = [];
// This was accidentally enabled by default when it was PRed. That is not what we want, configurationFileUpdated = true;
// so as a compromise users who want to use it will simply need to re-enable it once after updating. }
cff.IgnoreApplet = false;
}); // 58 migration accidentally got skipped but it worked with no issues somehow lol
if (configurationFileFormat.Version < 59)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 59.");
configurationFileFormat.ShowDirtyHacks = false;
configurationFileFormat.DirtyHacks = [];
configurationFileUpdated = true;
}
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.ResScale.Value = configurationFileFormat.ResScale; Graphics.ResScale.Value = configurationFileFormat.ResScale;
@@ -381,12 +752,14 @@ namespace Ryujinx.Ava.Utilities.Configuration
Hacks.ShowDirtyHacks.Value = configurationFileFormat.ShowDirtyHacks; Hacks.ShowDirtyHacks.Value = configurationFileFormat.ShowDirtyHacks;
{ {
DirtyHacks hacks = new (configurationFileFormat.DirtyHacks ?? []); EnabledDirtyHack[] hacks = (configurationFileFormat.DirtyHacks ?? []).Select(EnabledDirtyHack.Unpack).ToArray();
Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix); Hacks.Xc2MenuSoftlockFix.Value = hacks.Any(it => it.Hack == DirtyHacks.Xc2MenuSoftlockFix);
Hacks.EnableShaderTranslationDelay.Value = hacks.IsEnabled(DirtyHack.ShaderTranslationDelay); var shaderCompilationThreadSleep = hacks.FirstOrDefault(it =>
Hacks.ShaderTranslationDelay.Value = hacks[DirtyHack.ShaderTranslationDelay].CoerceAtLeast(0); it.Hack == DirtyHacks.ShaderCompilationThreadSleep);
Hacks.EnableShaderTranslationDelay.Value = shaderCompilationThreadSleep != null;
Hacks.ShaderTranslationDelay.Value = shaderCompilationThreadSleep?.Value ?? 0;
} }
if (configurationFileUpdated) if (configurationFileUpdated)
@@ -395,19 +768,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
Ryujinx.Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}"); Ryujinx.Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}");
} }
return;
void Migrate(int newVer, Action<ConfigurationFileFormat> migrator)
{
if (configurationFileFormat.Version >= newVer) return;
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version {newVer}.");
migrator(configurationFileFormat);
configurationFileUpdated = true;
}
} }
} }
} }
@@ -666,14 +666,14 @@ namespace Ryujinx.Ava.Utilities.Configuration
List<EnabledDirtyHack> enabledHacks = []; List<EnabledDirtyHack> enabledHacks = [];
if (Xc2MenuSoftlockFix) if (Xc2MenuSoftlockFix)
Apply(DirtyHack.Xc2MenuSoftlockFix); Apply(DirtyHacks.Xc2MenuSoftlockFix);
if (EnableShaderTranslationDelay) if (EnableShaderTranslationDelay)
Apply(DirtyHack.ShaderTranslationDelay, ShaderTranslationDelay); Apply(DirtyHacks.ShaderCompilationThreadSleep, ShaderTranslationDelay);
return enabledHacks.ToArray(); return enabledHacks.ToArray();
void Apply(DirtyHack hack, int value = 0) void Apply(DirtyHacks hack, int value = 0)
{ {
enabledHacks.Add(new EnabledDirtyHack(hack, value)); enabledHacks.Add(new EnabledDirtyHack(hack, value));
} }