From 47559cd3115e243fcb2e66383dd2930c2c22bab4 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 14 Oct 2025 15:59:02 -0500 Subject: [PATCH 1/6] Revert game list rounding The selected highlight was bugged https://fs.ryujinx.app/40cl4Ih9RiOWLVi7e4lJsw.png --- src/Ryujinx/UI/Views/Misc/ApplicationGridView.axaml | 4 ++-- src/Ryujinx/UI/Views/Misc/ApplicationListView.axaml | 10 ++-------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Ryujinx/UI/Views/Misc/ApplicationGridView.axaml b/src/Ryujinx/UI/Views/Misc/ApplicationGridView.axaml index 39db76031..b572d04e6 100644 --- a/src/Ryujinx/UI/Views/Misc/ApplicationGridView.axaml +++ b/src/Ryujinx/UI/Views/Misc/ApplicationGridView.axaml @@ -35,7 +35,7 @@ @@ -49,11 +46,9 @@ Padding="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" - ClipToBounds="True"> + ClipToBounds="True" + CornerRadius="5"> - - Date: Tue, 14 Oct 2025 16:09:51 -0500 Subject: [PATCH 2/6] chore: move HasPtcCacheFiles & HasShaderCacheFiles into ApplicationData, instead of having the weird static dependency helpers --- .../Systems/AppLibrary/ApplicationData.cs | 28 ++++++++++++++++ .../UI/Controls/ApplicationContextMenu.axaml | 4 +-- .../UI/ViewModels/MainWindowViewModel.cs | 32 ++----------------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs index 5656d6e73..c10ec69bd 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs @@ -11,11 +11,13 @@ using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Systems.PlayReport; using Ryujinx.Ava.Utilities; +using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.Loaders.Processes.Extensions; using System; using System.IO; +using System.Linq; using System.Text.Json.Serialization; namespace Ryujinx.Ava.Systems.AppLibrary @@ -84,6 +86,32 @@ namespace Ryujinx.Ava.Systems.AppLibrary public LocaleKeys? PlayabilityStatus => Compatibility.Convert(x => x.Status).OrElse(null); + public bool HasPtcCacheFiles + { + get + { + DirectoryInfo mainDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, IdString, "cache", "cpu", "0")); + DirectoryInfo backupDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, IdString, "cache", "cpu", "1")); + + return (mainDir.Exists && (mainDir.EnumerateFiles("*.cache").Any() || mainDir.EnumerateFiles("*.info").Any())) || + (backupDir.Exists && (backupDir.EnumerateFiles("*.cache").Any() || backupDir.EnumerateFiles("*.info").Any())); + } + } + + public bool HasShaderCacheFiles + { + get + { + DirectoryInfo shaderCacheDir = new(System.IO.Path.Combine(AppDataManager.GamesDirPath, IdString, "cache", "shader")); + + if (!shaderCacheDir.Exists) return false; + + return shaderCacheDir.EnumerateDirectories("*").Any() || + shaderCacheDir.GetFiles("*.toc").Length != 0 || + shaderCacheDir.GetFiles("*.data").Length != 0; + } + } + public string LocalizedStatusTooltip => Compatibility.Convert(x => #pragma warning disable CS8509 // It is exhaustive for all possible values this can contain. diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml index 909154540..9f2999a4c 100755 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml @@ -120,13 +120,13 @@ CommandParameter="{Binding}" Header="{ext:Locale GameListContextMenuCacheManagementNukePptc}" Icon="{ext:Icon fa-solid fa-trash-can}" - IsEnabled="{Binding HasPtcCacheFiles}" /> + IsEnabled="{Binding SelectedApplication.HasPtcCacheFiles, FallbackValue=False}" /> + IsEnabled="{Binding SelectedApplication.HasShaderCacheFiles, FallbackValue=False}" /> NukePtcCache { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null && - vm.HasPtcCacheFiles(), + Commands.CreateConditional(vm => vm?.SelectedApplication?.HasPtcCacheFiles ?? false, async viewModel => { UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( @@ -2171,22 +2170,9 @@ namespace Ryujinx.Ava.UI.ViewModels } }); - private bool HasPtcCacheFiles() - { - if (this.SelectedApplication == null) return false; - - DirectoryInfo mainDir = new DirectoryInfo(Path.Combine(AppDataManager.GamesDirPath, - this.SelectedApplication.IdString, "cache", "cpu", "0")); - DirectoryInfo backupDir = new DirectoryInfo(Path.Combine(AppDataManager.GamesDirPath, - this.SelectedApplication.IdString, "cache", "cpu", "1")); - - return (mainDir.Exists && (mainDir.EnumerateFiles("*.cache").Any() || mainDir.EnumerateFiles("*.info").Any())) || - (backupDir.Exists && (backupDir.EnumerateFiles("*.cache").Any() || backupDir.EnumerateFiles("*.info").Any())); - } - public static AsyncRelayCommand PurgeShaderCache { get; } = Commands.CreateConditional( - vm => vm?.SelectedApplication != null && vm.HasShaderCacheFiles(), + vm => vm?.SelectedApplication?.HasShaderCacheFiles ?? false, async viewModel => { UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( @@ -2243,20 +2229,6 @@ namespace Ryujinx.Ava.UI.ViewModels } }); - private bool HasShaderCacheFiles() - { - if (this.SelectedApplication == null) return false; - - DirectoryInfo shaderCacheDir = new(Path.Combine(AppDataManager.GamesDirPath, - this.SelectedApplication.IdString, "cache", "shader")); - - if (!shaderCacheDir.Exists) return false; - - return shaderCacheDir.EnumerateDirectories("*").Any() || - shaderCacheDir.GetFiles("*.toc").Any() || - shaderCacheDir.GetFiles("*.data").Any(); - } - public static RelayCommand OpenPtcDirectory { get; } = Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => From 99126603bae923dac49d729c0613fba483670c22 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 14 Oct 2025 16:12:11 -0500 Subject: [PATCH 3/6] UI: swap the UI reset checkbox text back to a sentence instead of title cased --- assets/locales.json | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/assets/locales.json b/assets/locales.json index 327c3994e..3a5b45f5f 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -6445,26 +6445,27 @@ { "ID": "SettingsButtonResetConfirm", "Translations": { - "ar_SA": "أريد إعادة تعيين إعداداتي", - "de_DE": "Ich möchte meine Einstellungen zurücksetzen", - "el_GR": "Θέλω να επαναφέρω τις ρυθμίσεις μου", - "en_US": "I Want To Reset My Settings", - "es_ES": "Quiero Restablecer Mi Configuración", - "fr_FR": "Je Veux Réinitialiser Mes Paramètres", - "he_IL": "אני רוצה לאפס את ההגדרות שלי", - "it_IT": "Voglio reimpostare le mie impostazioni", - "ja_JP": "設定をリセットしたいです", - "ko_KR": "설정을 초기화하고 싶습니다", - "no_NO": "Jeg vil tilbakestille innstillingene mine", - "pl_PL": "Chcę zresetować moje ustawienia", - "pt_BR": "Quero redefinir minhas configurações", - "ru_RU": "Я хочу сбросить свои настройки", - "sv_SE": "Jag vill nollställa mina inställningar", - "th_TH": "ฉันต้องการรีเซ็ตการตั้งค่าของฉัน", - "tr_TR": "Ayarlarımı sıfırlamak istiyorum", - "uk_UA": "Я хочу скинути налаштування", - "zh_CN": "我要重置我的设置", - "zh_TW": "我想重設我的設定" + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "I want to reset my settings.", + "es_ES": "Quiero restablecer mi Configuración.", + "fr_FR": "Je veux réinitialiser mes paramètres.", + "he_IL": "", + "it_IT": "Voglio ripristinare le mie impostazioni.", + "ja_JP": "", + "ko_KR": "설정을 초기화하고 싶습니다.", + "no_NO": "Jeg vil tilbakestille innstillingene mine.", + "pl_PL": "", + "pt_BR": "Quero redefinir minhas configurações.", + "ru_RU": "Я хочу сбросить свои настройки.", + "sv_SE": "Jag vill nollställa mina inställningar.", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Я хочу скинути налаштування.", + "zh_CN": "我要重置我的设置。", + "zh_TW": "我想重設我的設定。" + } }, { From 2434c55266587b26a6189dcc2c194a92d5790e0f Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 14 Oct 2025 18:38:56 -0500 Subject: [PATCH 4/6] UI: Updater: Fix "No" opening the changelog and "Show Changelog" doing nothing (aka doing what "No" should be doing) --- src/Ryujinx/UI/Helpers/ContentDialogHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs b/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs index fd42c6a45..e8730913c 100644 --- a/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs +++ b/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs @@ -354,8 +354,8 @@ namespace Ryujinx.Ava.UI.Helpers primary, secondaryText, LocaleManager.Instance[LocaleKeys.InputDialogYes], - LocaleManager.Instance[LocaleKeys.InputDialogNo], LocaleManager.Instance[LocaleKeys.DialogUpdaterShowChangelogMessage], + LocaleManager.Instance[LocaleKeys.InputDialogNo], (int)Symbol.Help, UserResult.Yes); From 1d409f712721b38327ff80ee0786465952a746d8 Mon Sep 17 00:00:00 2001 From: LotP <22-lotp@users.noreply.git.ryujinx.app> Date: Wed, 15 Oct 2025 15:37:13 -0500 Subject: [PATCH 5/6] 12 GiB heap support (ryubing/ryujinx!166) See merge request ryubing/ryujinx!166 --- src/Ryujinx.HLE/HOS/Kernel/KernelStatic.cs | 1 + src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs | 9 ++++++--- src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs | 4 ++++ src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs | 3 ++- src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs | 3 ++- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Kernel/KernelStatic.cs b/src/Ryujinx.HLE/HOS/Kernel/KernelStatic.cs index e05fc8397..e3c5865ae 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/KernelStatic.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/KernelStatic.cs @@ -29,6 +29,7 @@ namespace Ryujinx.HLE.HOS.Kernel capabilities, context.ResourceLimit, MemoryRegion.Service, + context.Device.Configuration.MemoryConfiguration, null, customThreadStart); diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs index ee1b4a7be..bc59b0b4d 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs @@ -102,6 +102,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory ProcessCreationFlags flags, bool fromBack, MemoryRegion memRegion, + MemoryConfiguration memConfig, ulong address, ulong size, KMemoryBlockSlabManager slabManager) @@ -117,6 +118,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory addrSpaceBase, addrSpaceSize, memRegion, + memConfig, address, size, slabManager); @@ -159,6 +161,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory ulong addrSpaceStart, ulong addrSpaceEnd, MemoryRegion memRegion, + MemoryConfiguration memConfig, ulong address, ulong size, KMemoryBlockSlabManager slabManager) @@ -193,7 +196,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory case ProcessCreationFlags.AddressSpace64BitDeprecated: aliasRegion.Size = 0x180000000; - heapRegion.Size = 0x180000000; + heapRegion.Size = memConfig == MemoryConfiguration.MemoryConfiguration12GiB ? 0x300000000u : 0x180000000u; stackRegion.Size = 0; tlsIoRegion.Size = 0; CodeRegionStart = 0x8000000; @@ -223,7 +226,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory int addressSpaceWidth = (int)ulong.Log2(_reservedAddressSpaceSize); aliasRegion.Size = 1UL << (addressSpaceWidth - 3); - heapRegion.Size = 0x180000000; + heapRegion.Size = memConfig == MemoryConfiguration.MemoryConfiguration12GiB ? 0x300000000u : 0x180000000u; stackRegion.Size = 1UL << (addressSpaceWidth - 8); tlsIoRegion.Size = 1UL << (addressSpaceWidth - 3); CodeRegionStart = BitUtils.AlignDown(address, RegionAlignment); @@ -237,7 +240,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory else { aliasRegion.Size = 0x1000000000; - heapRegion.Size = 0x180000000; + heapRegion.Size = memConfig == MemoryConfiguration.MemoryConfiguration12GiB ? 0x300000000u : 0x180000000u; stackRegion.Size = 0x80000000; tlsIoRegion.Size = 0x1000000000; CodeRegionStart = BitUtils.AlignDown(address, RegionAlignment); diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index bea1f0ef3..b823d14f7 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -124,6 +124,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process KPageList pageList, KResourceLimit resourceLimit, MemoryRegion memRegion, + MemoryConfiguration memConfig, IProcessContextFactory contextFactory, ThreadStart customThreadStart = null) { @@ -153,6 +154,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process creationInfo.Flags, !creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr), memRegion, + memConfig, codeAddress, codeSize, slabManager); @@ -189,6 +191,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process ReadOnlySpan capabilities, KResourceLimit resourceLimit, MemoryRegion memRegion, + MemoryConfiguration memConfig, IProcessContextFactory contextFactory, ThreadStart customThreadStart = null) { @@ -252,6 +255,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process creationInfo.Flags, !creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr), memRegion, + memConfig, codeAddress, codeSize, slabManager); diff --git a/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs index 005ac1452..260ff8af3 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -137,6 +137,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall capabilities, resourceLimit, memRegion, + _context.Device.Configuration.MemoryConfiguration, contextFactory, customThreadStart); @@ -888,7 +889,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [Svc(1)] public Result SetHeapSize([PointerSized] out ulong address, [PointerSized] ulong size) { - if ((size & 0xfffffffe001fffff) != 0) + if ((size & 0xfffffffd001fffff) != 0) { address = 0; diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs index 5729052e8..7f0c6b3f5 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs @@ -189,7 +189,7 @@ namespace Ryujinx.HLE.Loaders.Processes codeAddress, codeSize); - result = process.InitializeKip(creationInfo, kip.Capabilities, pageList, context.ResourceLimit, memoryRegion, processContextFactory); + result = process.InitializeKip(creationInfo, kip.Capabilities, pageList, context.ResourceLimit, memoryRegion, context.Device.Configuration.MemoryConfiguration, processContextFactory); if (result != Result.Success) { Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\"."); @@ -389,6 +389,7 @@ namespace Ryujinx.HLE.Loaders.Processes MemoryMarshal.Cast(npdm.KernelCapabilityData), resourceLimit, memoryRegion, + context.Device.Configuration.MemoryConfiguration, processContextFactory); if (result != Result.Success) From d4107ac05f696827c51ff1d120560ca3536cd8be Mon Sep 17 00:00:00 2001 From: GreemDev Date: Wed, 15 Oct 2025 21:51:13 -0500 Subject: [PATCH 6/6] UI: Add a startup flag to ignore new Amiibo file updates, useful for testing changes you intend on committing to Ryubing/Nfc. Flag is `--local-only-amiibo` --- .../UI/ViewModels/AmiiboWindowViewModel.cs | 54 ++++++++++++++++++- src/Ryujinx/Utilities/CommandLineState.cs | 5 ++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx/UI/ViewModels/AmiiboWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/AmiiboWindowViewModel.cs index 51541b615..0ba071475 100644 --- a/src/Ryujinx/UI/ViewModels/AmiiboWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/AmiiboWindowViewModel.cs @@ -6,6 +6,7 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models.Amiibo; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Windows; +using Ryujinx.Ava.Utilities; using Ryujinx.Common; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; @@ -250,6 +251,7 @@ namespace Ryujinx.Ava.UI.ViewModels catch (Exception exception) { Logger.Warning?.Print(LogClass.Application, $"Unable to read data from '{_amiiboJsonPath}': {exception}"); + localIsValid = false; } if (!localIsValid || await NeedsUpdate(amiiboJson.LastUpdated)) @@ -280,11 +282,59 @@ namespace Ryujinx.Ava.UI.ViewModels return amiiboJson; } + private async Task ReadLocalJsonFileAsync() + { + bool isValid = false; + AmiiboJson amiiboJson = new(); + + try + { + try + { + if (File.Exists(_amiiboJsonPath)) + { + isValid = TryGetAmiiboJson(await File.ReadAllTextAsync(_amiiboJsonPath), out amiiboJson); + } + } + catch (Exception exception) + { + Logger.Warning?.Print(LogClass.Application, $"Unable to read data from '{_amiiboJsonPath}': {exception}"); + isValid = false; + } + + if (!isValid) + { + return null; + } + } + catch (Exception exception) + { + if (!isValid) + { + Logger.Error?.Print(LogClass.Application, $"Couldn't get valid amiibo data: {exception}"); + + // Neither local file is not valid JSON, close window. + await ShowInfoDialog(); + Close(); + } + } + + return amiiboJson; + } + private async Task LoadContentAsync() { - AmiiboJson amiiboJson = await GetMostRecentAmiiboListOrDefaultJson(); + AmiiboJson? amiiboJson; - _amiiboList = amiiboJson.Amiibo.OrderBy(amiibo => amiibo.AmiiboSeries).ToList(); + if (CommandLineState.OnlyLocalAmiibo) + amiiboJson = await ReadLocalJsonFileAsync(); + else + amiiboJson = await GetMostRecentAmiiboListOrDefaultJson(); + + if (!amiiboJson.HasValue) + return; + + _amiiboList = amiiboJson.Value.Amiibo.OrderBy(amiibo => amiibo.AmiiboSeries).ToList(); ParseAmiiboData(); } diff --git a/src/Ryujinx/Utilities/CommandLineState.cs b/src/Ryujinx/Utilities/CommandLineState.cs index d7d113ebe..f156792a1 100644 --- a/src/Ryujinx/Utilities/CommandLineState.cs +++ b/src/Ryujinx/Utilities/CommandLineState.cs @@ -25,6 +25,7 @@ namespace Ryujinx.Ava.Utilities public static string LaunchApplicationId { get; private set; } public static bool StartFullscreenArg { get; private set; } public static bool HideAvailableUpdates { get; private set; } + public static bool OnlyLocalAmiibo { get; private set; } public static void ParseArguments(string[] args) { @@ -130,6 +131,10 @@ namespace Ryujinx.Ava.Utilities OverridePPTC = args[++i]; break; + case "-la": + case "--local-only-amiibo": + OnlyLocalAmiibo = true; + break; case "-m": case "--memory-manager-mode": if (i + 1 >= args.Length)