From 72c187a4b89c3db2dfed6887f6029f12e7ea980f Mon Sep 17 00:00:00 2001 From: KeatonTheBot Date: Mon, 12 Jan 2026 16:14:39 -0600 Subject: [PATCH 01/18] Linux: Fix file picker not launching from disabling core dumps Core dumps are disabled by default on Linux, but this prevents access to the file picker due to security hardening. To work around this, core dumps are selectively enabled and disabled around the file picker tasks. --- src/Ryujinx.Common/Utilities/OsUtils.cs | 13 ++++- src/Ryujinx/Common/ApplicationHelper.cs | 15 +++++ src/Ryujinx/Program.cs | 3 + .../DownloadableContentManagerViewModel.cs | 8 +++ .../UI/ViewModels/MainWindowViewModel.cs | 56 +++++++++++++++++++ .../UI/ViewModels/ModManagerViewModel.cs | 7 +++ .../UI/ViewModels/TitleUpdateViewModel.cs | 8 +++ .../UI/Views/Settings/SettingsUIView.axaml.cs | 8 +++ .../UserProfileImageSelectorView.axaml.cs | 8 +++ 9 files changed, 124 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.Common/Utilities/OsUtils.cs b/src/Ryujinx.Common/Utilities/OsUtils.cs index 29c6e187c..79fe8b722 100644 --- a/src/Ryujinx.Common/Utilities/OsUtils.cs +++ b/src/Ryujinx.Common/Utilities/OsUtils.cs @@ -22,10 +22,11 @@ namespace Ryujinx.Common.Utilities } // "dumpable" attribute of the calling process + private const int PR_GET_DUMPABLE = 3; private const int PR_SET_DUMPABLE = 4; - [DllImport("libc", SetLastError = true)] - private static extern int prctl(int option, int arg2); + [LibraryImport("libc", SetLastError = true)] + private static partial int prctl(int option, int arg2); public static void SetCoreDumpable(bool dumpable) { @@ -36,5 +37,13 @@ namespace Ryujinx.Common.Utilities Debug.Assert(result == 0); } } + + // Use the below line to display dumpable status in the console: + // Console.WriteLine($"{OsUtils.IsCoreDumpable()}"); + public static bool IsCoreDumpable() + { + int result = prctl(PR_GET_DUMPABLE, 0); + return result == 1; + } } } diff --git a/src/Ryujinx/Common/ApplicationHelper.cs b/src/Ryujinx/Common/ApplicationHelper.cs index 3efd9ed62..f958c0159 100644 --- a/src/Ryujinx/Common/ApplicationHelper.cs +++ b/src/Ryujinx/Common/ApplicationHelper.cs @@ -18,6 +18,7 @@ using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; using Ryujinx.Common.Helper; using Ryujinx.Common.Logging; +using Ryujinx.Common.Utilities; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.Loaders.Processes.Extensions; @@ -410,6 +411,8 @@ namespace Ryujinx.Ava.Common public static async Task ExtractAoc(IStorageProvider storageProvider, string updateFilePath, string updateName) { + OsUtils.SetCoreDumpable(true); + Gommon.Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] @@ -419,10 +422,17 @@ namespace Ryujinx.Ava.Common return; ExtractAoc(result.Value.Path.LocalPath, updateFilePath, updateName); + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) { + OsUtils.SetCoreDumpable(true); + Gommon.Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] @@ -432,6 +442,11 @@ namespace Ryujinx.Ava.Common return; ExtractSection(result.Value.Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex); + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 8d03f81da..d1b85c6b0 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -42,6 +42,7 @@ namespace Ryujinx.Ava public static bool PreviewerDetached { get; private set; } public static bool UseHardwareAcceleration { get; private set; } public static string BackendThreadingArg { get; private set; } + public static bool CoreDumpArg { get; private set; } private const uint MbIconwarning = 0x30; @@ -81,6 +82,8 @@ namespace Ryujinx.Ava bool noGuiArg = ConsumeCommandLineArgument(ref args, "--no-gui") || ConsumeCommandLineArgument(ref args, "nogui"); bool coreDumpArg = ConsumeCommandLineArgument(ref args, "--core-dumps"); + CoreDumpArg = coreDumpArg; + // TODO: Ryujinx causes core dumps on Linux when it exits "uncleanly", eg. through an unhandled exception. // This is undesirable and causes very odd behavior during development (the process stops responding, // the .NET debugger freezes or suddenly detaches, /tmp/ gets filled etc.), unless explicitly requested by the user. diff --git a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs index 39e53184f..0bec24945 100644 --- a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs @@ -8,6 +8,7 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; @@ -128,6 +129,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async void Add() { + OsUtils.SetCoreDumpable(true); + IReadOnlyList result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle], @@ -158,6 +161,11 @@ namespace Ryujinx.Ava.UI.ViewModels { await ShowNewDlcAddedDialog(totalDlcAdded); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } private bool AddDownloadableContent(string path, out int numDlcAdded) diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 48e18a12e..e3d86d8a8 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1299,6 +1299,8 @@ namespace Ryujinx.Ava.UI.ViewModels private async Task LoadContentFromFolder(LocaleKeys localeMessageAddedKey, LocaleKeys localeMessageRemovedKey, LoadContentFromFolderDelegate onDirsSelected, LocaleKeys dirSelectDialogTitle) { + OsUtils.SetCoreDumpable(true); + Optional> result = await StorageProvider.OpenMultiFolderPickerAsync( new FolderPickerOpenOptions { Title = LocaleManager.Instance[dirSelectDialogTitle] }); @@ -1326,6 +1328,11 @@ namespace Ryujinx.Ava.UI.ViewModels (int)Symbol.Checkmark); }); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } #endregion @@ -1388,6 +1395,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task InstallFirmwareFromFile() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { FileTypeFilter = new List @@ -1417,20 +1426,34 @@ namespace Ryujinx.Ava.UI.ViewModels { await HandleFirmwareInstallation(result.Value.Path.LocalPath); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public async Task InstallFirmwareFromFolder() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFolderPickerAsync(); if (result.HasValue) { await HandleFirmwareInstallation(result.Value.Path.LocalPath); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public async Task InstallKeysFromFile() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { FileTypeFilter = new List @@ -1448,16 +1471,28 @@ namespace Ryujinx.Ava.UI.ViewModels { await HandleKeysInstallation(result.Value.Path.LocalPath); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public async Task InstallKeysFromFolder() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFolderPickerAsync(); if (result.HasValue) { await HandleKeysInstallation(result.Value.Path.LocalPath); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public void OpenRyujinxFolder() @@ -1561,6 +1596,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenFile() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.LoadApplicationFromFileDialogTitle], @@ -1632,6 +1669,11 @@ namespace Ryujinx.Ava.UI.ViewModels LocaleManager.Instance[LocaleKeys.MenuBarFileOpenFromFileError]); } } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public async Task LoadDlcFromFolder() @@ -1654,6 +1696,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenFolder() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFolderPickerAsync( new FolderPickerOpenOptions { @@ -1669,6 +1713,11 @@ namespace Ryujinx.Ava.UI.ViewModels await LoadApplication(applicationData); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public static bool InitializeUserConfig(ApplicationData application) @@ -1876,6 +1925,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenBinFile() { + OsUtils.SetCoreDumpable(true); + if (AppHost.Device.System.SearchingForAmiibo(out _) && IsGameRunning) { Optional result = await StorageProvider.OpenSingleFilePickerAsync( @@ -1895,6 +1946,11 @@ namespace Ryujinx.Ava.UI.ViewModels { AppHost.Device.System.ScanAmiiboFromBin(result.Value.Path.LocalPath); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } } public async Task OpenSkylanderWindow() diff --git a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs index 45e67add0..569d293e6 100644 --- a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs @@ -288,6 +288,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async void Add() { + OsUtils.SetCoreDumpable(true); + IReadOnlyList result = await _storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.SelectModDialogTitle], @@ -298,6 +300,11 @@ namespace Ryujinx.Ava.UI.ViewModels { AddMod(new DirectoryInfo(folder.Path.LocalPath)); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public void DeleteAll() diff --git a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs index 3d34643ab..c10da7bf9 100644 --- a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs @@ -7,6 +7,7 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.IO; using System.Linq; @@ -148,6 +149,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task Add() { + OsUtils.SetCoreDumpable(true); + IReadOnlyList result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { AllowMultiple = true, @@ -177,6 +180,11 @@ namespace Ryujinx.Ava.UI.ViewModels { await ShowNewUpdatesAddedDialog(totalUpdatesAdded); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public void Save() diff --git a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs index f0742a579..62e4e72a6 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs @@ -7,6 +7,7 @@ using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.Utilities; +using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.IO; using System.Linq; @@ -27,6 +28,8 @@ namespace Ryujinx.Ava.UI.Views.Settings private async Task AddDirButton(TextBox addDirBox, AvaloniaList directories) { + OsUtils.SetCoreDumpable(true); + string path = addDirBox.Text; if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !directories.Contains(path)) @@ -48,6 +51,11 @@ namespace Ryujinx.Ava.UI.Views.Settings ViewModel.GameListNeedsRefresh = true; } } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } private void RemoveGameDirButton_OnClick(object sender, RoutedEventArgs e) diff --git a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs index 3a5b7c6b7..9b9cc3303 100644 --- a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs @@ -8,6 +8,7 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; +using Ryujinx.Common.Utilities; using Ryujinx.HLE.FileSystem; using SkiaSharp; using System.Collections.Generic; @@ -62,6 +63,8 @@ namespace Ryujinx.Ava.UI.Views.User private async void Import_OnClick(object sender, RoutedEventArgs e) { + OsUtils.SetCoreDumpable(true); + IReadOnlyList result = await ((Window)this.GetVisualRoot()!).StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { AllowMultiple = false, @@ -81,6 +84,11 @@ namespace Ryujinx.Ava.UI.Views.User _profile.Image = ProcessProfileImage(File.ReadAllBytes(result[0].Path.LocalPath)); _parent.GoBack(); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } private void GoBack(object sender, RoutedEventArgs e) From c47219558e03047dd49d17eed2df4ff5031730a6 Mon Sep 17 00:00:00 2001 From: KeatonTheBot Date: Fri, 6 Mar 2026 18:13:04 -0600 Subject: [PATCH 02/18] Move SetCoreDumpable call to StorageProviderExtensions --- src/Ryujinx/Common/ApplicationHelper.cs | 15 ----- .../DownloadableContentManagerViewModel.cs | 8 --- .../UI/ViewModels/MainWindowViewModel.cs | 56 ------------------- .../UI/ViewModels/ModManagerViewModel.cs | 7 --- .../UI/ViewModels/TitleUpdateViewModel.cs | 8 --- .../UI/Views/Settings/SettingsUIView.axaml.cs | 8 --- .../UserProfileImageSelectorView.axaml.cs | 8 --- .../Utilities/StorageProviderExtensions.cs | 32 ++++++++--- 8 files changed, 23 insertions(+), 119 deletions(-) diff --git a/src/Ryujinx/Common/ApplicationHelper.cs b/src/Ryujinx/Common/ApplicationHelper.cs index f958c0159..3efd9ed62 100644 --- a/src/Ryujinx/Common/ApplicationHelper.cs +++ b/src/Ryujinx/Common/ApplicationHelper.cs @@ -18,7 +18,6 @@ using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; using Ryujinx.Common.Helper; using Ryujinx.Common.Logging; -using Ryujinx.Common.Utilities; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.Loaders.Processes.Extensions; @@ -411,8 +410,6 @@ namespace Ryujinx.Ava.Common public static async Task ExtractAoc(IStorageProvider storageProvider, string updateFilePath, string updateName) { - OsUtils.SetCoreDumpable(true); - Gommon.Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] @@ -422,17 +419,10 @@ namespace Ryujinx.Ava.Common return; ExtractAoc(result.Value.Path.LocalPath, updateFilePath, updateName); - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) { - OsUtils.SetCoreDumpable(true); - Gommon.Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] @@ -442,11 +432,6 @@ namespace Ryujinx.Ava.Common return; ExtractSection(result.Value.Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex); - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token) diff --git a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs index 0bec24945..39e53184f 100644 --- a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs @@ -8,7 +8,6 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; @@ -129,8 +128,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async void Add() { - OsUtils.SetCoreDumpable(true); - IReadOnlyList result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle], @@ -161,11 +158,6 @@ namespace Ryujinx.Ava.UI.ViewModels { await ShowNewDlcAddedDialog(totalDlcAdded); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } private bool AddDownloadableContent(string path, out int numDlcAdded) diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index e3d86d8a8..48e18a12e 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1299,8 +1299,6 @@ namespace Ryujinx.Ava.UI.ViewModels private async Task LoadContentFromFolder(LocaleKeys localeMessageAddedKey, LocaleKeys localeMessageRemovedKey, LoadContentFromFolderDelegate onDirsSelected, LocaleKeys dirSelectDialogTitle) { - OsUtils.SetCoreDumpable(true); - Optional> result = await StorageProvider.OpenMultiFolderPickerAsync( new FolderPickerOpenOptions { Title = LocaleManager.Instance[dirSelectDialogTitle] }); @@ -1328,11 +1326,6 @@ namespace Ryujinx.Ava.UI.ViewModels (int)Symbol.Checkmark); }); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } #endregion @@ -1395,8 +1388,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task InstallFirmwareFromFile() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { FileTypeFilter = new List @@ -1426,34 +1417,20 @@ namespace Ryujinx.Ava.UI.ViewModels { await HandleFirmwareInstallation(result.Value.Path.LocalPath); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public async Task InstallFirmwareFromFolder() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFolderPickerAsync(); if (result.HasValue) { await HandleFirmwareInstallation(result.Value.Path.LocalPath); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public async Task InstallKeysFromFile() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { FileTypeFilter = new List @@ -1471,28 +1448,16 @@ namespace Ryujinx.Ava.UI.ViewModels { await HandleKeysInstallation(result.Value.Path.LocalPath); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public async Task InstallKeysFromFolder() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFolderPickerAsync(); if (result.HasValue) { await HandleKeysInstallation(result.Value.Path.LocalPath); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public void OpenRyujinxFolder() @@ -1596,8 +1561,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenFile() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.LoadApplicationFromFileDialogTitle], @@ -1669,11 +1632,6 @@ namespace Ryujinx.Ava.UI.ViewModels LocaleManager.Instance[LocaleKeys.MenuBarFileOpenFromFileError]); } } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public async Task LoadDlcFromFolder() @@ -1696,8 +1654,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenFolder() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFolderPickerAsync( new FolderPickerOpenOptions { @@ -1713,11 +1669,6 @@ namespace Ryujinx.Ava.UI.ViewModels await LoadApplication(applicationData); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public static bool InitializeUserConfig(ApplicationData application) @@ -1925,8 +1876,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenBinFile() { - OsUtils.SetCoreDumpable(true); - if (AppHost.Device.System.SearchingForAmiibo(out _) && IsGameRunning) { Optional result = await StorageProvider.OpenSingleFilePickerAsync( @@ -1946,11 +1895,6 @@ namespace Ryujinx.Ava.UI.ViewModels { AppHost.Device.System.ScanAmiiboFromBin(result.Value.Path.LocalPath); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } } public async Task OpenSkylanderWindow() diff --git a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs index 569d293e6..45e67add0 100644 --- a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs @@ -288,8 +288,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async void Add() { - OsUtils.SetCoreDumpable(true); - IReadOnlyList result = await _storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.SelectModDialogTitle], @@ -300,11 +298,6 @@ namespace Ryujinx.Ava.UI.ViewModels { AddMod(new DirectoryInfo(folder.Path.LocalPath)); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public void DeleteAll() diff --git a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs index c10da7bf9..3d34643ab 100644 --- a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs @@ -7,7 +7,6 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.IO; using System.Linq; @@ -149,8 +148,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task Add() { - OsUtils.SetCoreDumpable(true); - IReadOnlyList result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { AllowMultiple = true, @@ -180,11 +177,6 @@ namespace Ryujinx.Ava.UI.ViewModels { await ShowNewUpdatesAddedDialog(totalUpdatesAdded); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public void Save() diff --git a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs index 62e4e72a6..f0742a579 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs @@ -7,7 +7,6 @@ using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.Utilities; -using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.IO; using System.Linq; @@ -28,8 +27,6 @@ namespace Ryujinx.Ava.UI.Views.Settings private async Task AddDirButton(TextBox addDirBox, AvaloniaList directories) { - OsUtils.SetCoreDumpable(true); - string path = addDirBox.Text; if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !directories.Contains(path)) @@ -51,11 +48,6 @@ namespace Ryujinx.Ava.UI.Views.Settings ViewModel.GameListNeedsRefresh = true; } } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } private void RemoveGameDirButton_OnClick(object sender, RoutedEventArgs e) diff --git a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs index 9b9cc3303..3a5b7c6b7 100644 --- a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs @@ -8,7 +8,6 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; -using Ryujinx.Common.Utilities; using Ryujinx.HLE.FileSystem; using SkiaSharp; using System.Collections.Generic; @@ -63,8 +62,6 @@ namespace Ryujinx.Ava.UI.Views.User private async void Import_OnClick(object sender, RoutedEventArgs e) { - OsUtils.SetCoreDumpable(true); - IReadOnlyList result = await ((Window)this.GetVisualRoot()!).StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { AllowMultiple = false, @@ -84,11 +81,6 @@ namespace Ryujinx.Ava.UI.Views.User _profile.Image = ProcessProfileImage(File.ReadAllBytes(result[0].Path.LocalPath)); _parent.GoBack(); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } private void GoBack(object sender, RoutedEventArgs e) diff --git a/src/Ryujinx/Utilities/StorageProviderExtensions.cs b/src/Ryujinx/Utilities/StorageProviderExtensions.cs index 68cde0f3d..2735d4336 100644 --- a/src/Ryujinx/Utilities/StorageProviderExtensions.cs +++ b/src/Ryujinx/Utilities/StorageProviderExtensions.cs @@ -1,5 +1,7 @@ using Avalonia.Platform.Storage; using Gommon; +using Ryujinx.Common.Utilities; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -11,29 +13,42 @@ namespace Ryujinx.Ava.Utilities extension(IStorageProvider storageProvider) { public Task> OpenSingleFolderPickerAsync(FolderPickerOpenOptions openOptions = null) => - storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, false)) + CoreDumpable(() => storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, false))) .Then(folders => folders.FindFirst()); - + public Task> OpenSingleFilePickerAsync(FilePickerOpenOptions openOptions = null) => - storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, false)) + CoreDumpable(() => storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, false))) .Then(files => files.FindFirst()); - + public Task>> OpenMultiFolderPickerAsync(FolderPickerOpenOptions openOptions = null) => - storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, true)) + CoreDumpable(() => storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, true))) .Then(folders => folders.Count > 0 ? Optional.Of(folders) : default); - + public Task>> OpenMultiFilePickerAsync(FilePickerOpenOptions openOptions = null) => - storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, true)) + CoreDumpable(() => storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, true))) .Then(files => files.Count > 0 ? Optional.Of(files) : default); } + private static async Task CoreDumpable(Func> picker) + { + OsUtils.SetCoreDumpable(true); + try + { + return await picker(); + } + finally + { + if (!Program.CoreDumpArg) + OsUtils.SetCoreDumpable(false); + } + } + private static FilePickerOpenOptions FixOpenOptions(this FilePickerOpenOptions openOptions, bool allowMultiple) { if (openOptions is null) return new FilePickerOpenOptions { AllowMultiple = allowMultiple }; openOptions.AllowMultiple = allowMultiple; - return openOptions; } @@ -43,7 +58,6 @@ namespace Ryujinx.Ava.Utilities return new FolderPickerOpenOptions { AllowMultiple = allowMultiple }; openOptions.AllowMultiple = allowMultiple; - return openOptions; } } From 1b2083d0ffc6ed38b01504673693b9e75d962a7f Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 02:40:18 -0400 Subject: [PATCH 03/18] [HLE] Renamed INotificationServicesForSystem and implemented a commands (and stubs) Should allow Ring Fit to get in-game, needs testing. --- .../INotificationServicesForApplication.cs | 26 +++++++++++++++++++ .../INotificationServicesForSystem.cs | 8 ------ .../INotificationSystemEventAccessor.cs | 17 ++++++++++++ 3 files changed, 43 insertions(+), 8 deletions(-) delete mode 100644 src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForSystem.cs create mode 100644 src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs index 29f8bfa85..37fd0fbee 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs @@ -4,5 +4,31 @@ namespace Ryujinx.HLE.HOS.Services.Notification class INotificationServicesForApplication : IpcService { public INotificationServicesForApplication(ServiceCtx context) { } + + [CommandCmif(520)] // 9.0.0+ + // ListAlarmSettings(nn::arp::ApplicationCertificate) -> s32 AlarmSettingsCount + public ResultCode ListAlarmSettings(ServiceCtx context) + { + // TO-DO: Currently just returns 0. Should read in an ApplicationCertificate. + int alarmSettingsCount = 0; + context.ResponseData.Write(alarmSettingsCount); + return ResultCode.Success; + } + + [CommandCmif(1000)] // 9.0.0+ + // GetNotificationCount() -> nn::notification::server::INotificationSystemEventAccessor + public ResultCode GetNotificationCount(ServiceCtx context) + { + MakeObject(context, new INotificationSystemEventAccessor(context)); + return ResultCode.Success; + } + + [CommandCmif(1040)] // 9.0.0+ + // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor + public ResultCode GetNotificationSendingNotifier(ServiceCtx context) + { + MakeObject(context, new INotificationSystemEventAccessor(context)); + return ResultCode.Success; + } } } diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForSystem.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForSystem.cs deleted file mode 100644 index c5946be84..000000000 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForSystem.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Ryujinx.HLE.HOS.Services.Notification -{ - [Service("notif:s")] // 9.0.0+ - class INotificationServicesForSystem : IpcService - { - public INotificationServicesForSystem(ServiceCtx context) { } - } -} diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs new file mode 100644 index 000000000..9298c26bb --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs @@ -0,0 +1,17 @@ +using Ryujinx.Common.Logging; + +namespace Ryujinx.HLE.HOS.Services.Notification +{ + class INotificationSystemEventAccessor : IpcService + { + public INotificationSystemEventAccessor(ServiceCtx context) { } + + [CommandCmif(0)] // 9.0.0+ + // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor + public ResultCode GetSystemEvent(ServiceCtx context) + { + Logger.Stub?.PrintStub(LogClass.Service); + return ResultCode.Success; + } + } +} From a7b78d96c96d7de3f1b09033387f3ac9d9d8f181 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 09:51:29 -0400 Subject: [PATCH 04/18] rider moment --- .../Notification/INotificationServices.cs | 24 +++++++++++++++++++ .../INotificationServicesForApplication.cs | 16 ------------- 2 files changed, 24 insertions(+), 16 deletions(-) create mode 100644 src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs new file mode 100644 index 000000000..4dd0beebf --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs @@ -0,0 +1,24 @@ +namespace Ryujinx.HLE.HOS.Services.Notification +{ + [Service("notif:s")] // 9.0.0+ + class INotificationServicesForSystem : IpcService + { + public INotificationServicesForSystem(ServiceCtx context) { } + + [CommandCmif(1000)] // 9.0.0+ + // GetNotificationCount() -> nn::notification::server::INotificationSystemEventAccessor + public ResultCode GetNotificationCount(ServiceCtx context) + { + MakeObject(context, new INotificationSystemEventAccessor(context)); + return ResultCode.Success; + } + + [CommandCmif(1040)] // 9.0.0+ + // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor + public ResultCode GetNotificationSendingNotifier(ServiceCtx context) + { + MakeObject(context, new INotificationSystemEventAccessor(context)); + return ResultCode.Success; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs index 37fd0fbee..b5ffcc877 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs @@ -14,21 +14,5 @@ namespace Ryujinx.HLE.HOS.Services.Notification context.ResponseData.Write(alarmSettingsCount); return ResultCode.Success; } - - [CommandCmif(1000)] // 9.0.0+ - // GetNotificationCount() -> nn::notification::server::INotificationSystemEventAccessor - public ResultCode GetNotificationCount(ServiceCtx context) - { - MakeObject(context, new INotificationSystemEventAccessor(context)); - return ResultCode.Success; - } - - [CommandCmif(1040)] // 9.0.0+ - // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor - public ResultCode GetNotificationSendingNotifier(ServiceCtx context) - { - MakeObject(context, new INotificationSystemEventAccessor(context)); - return ResultCode.Success; - } } } From cd9aa91ff53b76a7edf0d9970ff7f8be4b535595 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 09:52:31 -0400 Subject: [PATCH 05/18] renamed a file because i forgor --- .../HOS/Services/Notification/INotificationServices.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs index 4dd0beebf..e44983fce 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs @@ -1,9 +1,9 @@ namespace Ryujinx.HLE.HOS.Services.Notification { [Service("notif:s")] // 9.0.0+ - class INotificationServicesForSystem : IpcService + class INotificationServices : IpcService { - public INotificationServicesForSystem(ServiceCtx context) { } + public INotificationServices(ServiceCtx context) { } [CommandCmif(1000)] // 9.0.0+ // GetNotificationCount() -> nn::notification::server::INotificationSystemEventAccessor From 776dfbb7b31e8fbab6541a2cd8d7a9b716428dec Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 13:54:40 -0400 Subject: [PATCH 06/18] new stub + LogClass enum update --- .../INotificationServicesForApplication.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs index b5ffcc877..48457f745 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs @@ -1,3 +1,5 @@ +using Ryujinx.Common.Logging; + namespace Ryujinx.HLE.HOS.Services.Notification { [Service("notif:a")] // 9.0.0+ @@ -5,6 +7,8 @@ namespace Ryujinx.HLE.HOS.Services.Notification { public INotificationServicesForApplication(ServiceCtx context) { } + // Leaving this here since I can never find it: https://switchbrew.org/wiki/Glue_services + [CommandCmif(520)] // 9.0.0+ // ListAlarmSettings(nn::arp::ApplicationCertificate) -> s32 AlarmSettingsCount public ResultCode ListAlarmSettings(ServiceCtx context) @@ -14,5 +18,16 @@ namespace Ryujinx.HLE.HOS.Services.Notification context.ResponseData.Write(alarmSettingsCount); return ResultCode.Success; } + + [CommandCmif(1000)] // 9.0.0+ + // Initialize(PID-descriptor, u64 pid_reserved) + public ResultCode Intialize(ServiceCtx context) + { + ulong PID = context.Device.Processes.ActiveApplication.ProgramId; + ulong pid_reserved = context.Device.Processes.ActiveApplication.ProcessId; + + Logger.Stub?.PrintStub(LogClass.ServiceNotification, new { PID, pid_reserved }); + return ResultCode.Success; + } } } From f367334aafa1ccf18e3de1d6e1ddd09b3ff346ae Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 13:59:56 -0400 Subject: [PATCH 07/18] ??? --- src/Ryujinx.Common/Logging/LogClass.cs | 1 + .../Services/Notification/INotificationSystemEventAccessor.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Common/Logging/LogClass.cs b/src/Ryujinx.Common/Logging/LogClass.cs index 7c6810599..0e02cfcc2 100644 --- a/src/Ryujinx.Common/Logging/LogClass.cs +++ b/src/Ryujinx.Common/Logging/LogClass.cs @@ -51,6 +51,7 @@ namespace Ryujinx.Common.Logging ServiceNgct, ServiceNifm, ServiceNim, + ServiceNotification, ServiceNs, ServiceNsd, ServiceNtc, diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs index 9298c26bb..1f34d4496 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs @@ -10,7 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Notification // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor public ResultCode GetSystemEvent(ServiceCtx context) { - Logger.Stub?.PrintStub(LogClass.Service); + Logger.Stub?.PrintStub(LogClass.ServiceNotification); return ResultCode.Success; } } From f4f43a0804d626c55417048c2c46cd0fb6c9a3e0 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 14:26:14 -0400 Subject: [PATCH 08/18] fixed initialize pid request --- .../Notification/INotificationServicesForApplication.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs index 48457f745..498fc52fb 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs @@ -23,10 +23,10 @@ namespace Ryujinx.HLE.HOS.Services.Notification // Initialize(PID-descriptor, u64 pid_reserved) public ResultCode Intialize(ServiceCtx context) { - ulong PID = context.Device.Processes.ActiveApplication.ProgramId; - ulong pid_reserved = context.Device.Processes.ActiveApplication.ProcessId; + ulong pid = context.Request.HandleDesc.PId; + context.RequestData.ReadUInt64(); // pid placeholder, zero - Logger.Stub?.PrintStub(LogClass.ServiceNotification, new { PID, pid_reserved }); + Logger.Stub?.PrintStub(LogClass.ServiceNotification, new { pid }); return ResultCode.Success; } } From cc3a3f1b5d2405537450f6e78b997d0feb42fc60 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 16:44:00 -0400 Subject: [PATCH 09/18] handled the handles --- .../INotificationSystemEventAccessor.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs index 1f34d4496..8cca7cc6e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs @@ -1,16 +1,31 @@ using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.Horizon.Common; +using System; namespace Ryujinx.HLE.HOS.Services.Notification { class INotificationSystemEventAccessor : IpcService { + + private readonly KEvent _getNotificationSendingNotifierEvent; + private int _getNotificationSendingNotifierEventHandle; public INotificationSystemEventAccessor(ServiceCtx context) { } - + [CommandCmif(0)] // 9.0.0+ // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor public ResultCode GetSystemEvent(ServiceCtx context) { - Logger.Stub?.PrintStub(LogClass.ServiceNotification); + if (_getNotificationSendingNotifierEventHandle == 0) + { + if (context.Process.HandleTable.GenerateHandle(_getNotificationSendingNotifierEvent.ReadableEvent, out _getNotificationSendingNotifierEventHandle) != Result.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_getNotificationSendingNotifierEventHandle); return ResultCode.Success; } } From 9a2df6451c1ec33941dc4b19dcbd45114b183b9a Mon Sep 17 00:00:00 2001 From: KeatonTheBot Date: Mon, 12 Jan 2026 16:14:39 -0600 Subject: [PATCH 10/18] Linux: Fix file picker not launching from disabling core dumps Core dumps are disabled by default on Linux, but this prevents access to the file picker due to security hardening. To work around this, core dumps are selectively enabled and disabled around the file picker tasks. --- src/Ryujinx/Common/ApplicationHelper.cs | 15 +++++ .../DownloadableContentManagerViewModel.cs | 8 +++ .../UI/ViewModels/MainWindowViewModel.cs | 56 +++++++++++++++++++ .../UI/ViewModels/ModManagerViewModel.cs | 7 +++ .../UI/ViewModels/TitleUpdateViewModel.cs | 8 +++ .../UI/Views/Settings/SettingsUIView.axaml.cs | 8 +++ .../UserProfileImageSelectorView.axaml.cs | 8 +++ 7 files changed, 110 insertions(+) diff --git a/src/Ryujinx/Common/ApplicationHelper.cs b/src/Ryujinx/Common/ApplicationHelper.cs index 3efd9ed62..f958c0159 100644 --- a/src/Ryujinx/Common/ApplicationHelper.cs +++ b/src/Ryujinx/Common/ApplicationHelper.cs @@ -18,6 +18,7 @@ using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; using Ryujinx.Common.Helper; using Ryujinx.Common.Logging; +using Ryujinx.Common.Utilities; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.Loaders.Processes.Extensions; @@ -410,6 +411,8 @@ namespace Ryujinx.Ava.Common public static async Task ExtractAoc(IStorageProvider storageProvider, string updateFilePath, string updateName) { + OsUtils.SetCoreDumpable(true); + Gommon.Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] @@ -419,10 +422,17 @@ namespace Ryujinx.Ava.Common return; ExtractAoc(result.Value.Path.LocalPath, updateFilePath, updateName); + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) { + OsUtils.SetCoreDumpable(true); + Gommon.Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] @@ -432,6 +442,11 @@ namespace Ryujinx.Ava.Common return; ExtractSection(result.Value.Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex); + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token) diff --git a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs index 39e53184f..0bec24945 100644 --- a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs @@ -8,6 +8,7 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; @@ -128,6 +129,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async void Add() { + OsUtils.SetCoreDumpable(true); + IReadOnlyList result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle], @@ -158,6 +161,11 @@ namespace Ryujinx.Ava.UI.ViewModels { await ShowNewDlcAddedDialog(totalDlcAdded); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } private bool AddDownloadableContent(string path, out int numDlcAdded) diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index ae84a15a2..b8062d659 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1323,6 +1323,8 @@ namespace Ryujinx.Ava.UI.ViewModels private async Task LoadContentFromFolder(LocaleKeys localeMessageAddedKey, LocaleKeys localeMessageRemovedKey, LoadContentFromFolderDelegate onDirsSelected, LocaleKeys dirSelectDialogTitle) { + OsUtils.SetCoreDumpable(true); + Optional> result = await StorageProvider.OpenMultiFolderPickerAsync( new FolderPickerOpenOptions { Title = LocaleManager.Instance[dirSelectDialogTitle] }); @@ -1350,6 +1352,11 @@ namespace Ryujinx.Ava.UI.ViewModels (int)Symbol.Checkmark); }); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } #endregion @@ -1412,6 +1419,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task InstallFirmwareFromFile() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { FileTypeFilter = new List @@ -1441,20 +1450,34 @@ namespace Ryujinx.Ava.UI.ViewModels { await HandleFirmwareInstallation(result.Value.Path.LocalPath); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public async Task InstallFirmwareFromFolder() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFolderPickerAsync(); if (result.HasValue) { await HandleFirmwareInstallation(result.Value.Path.LocalPath); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public async Task InstallKeysFromFile() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { FileTypeFilter = new List @@ -1472,16 +1495,28 @@ namespace Ryujinx.Ava.UI.ViewModels { await HandleKeysInstallation(result.Value.Path.LocalPath); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public async Task InstallKeysFromFolder() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFolderPickerAsync(); if (result.HasValue) { await HandleKeysInstallation(result.Value.Path.LocalPath); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public void OpenRyujinxFolder() @@ -1585,6 +1620,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenFile() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.LoadApplicationFromFileDialogTitle], @@ -1656,6 +1693,11 @@ namespace Ryujinx.Ava.UI.ViewModels LocaleManager.Instance[LocaleKeys.MenuBarFileOpenFromFileError]); } } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public async Task LoadDlcFromFolder() @@ -1678,6 +1720,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenFolder() { + OsUtils.SetCoreDumpable(true); + Optional result = await StorageProvider.OpenSingleFolderPickerAsync( new FolderPickerOpenOptions { @@ -1693,6 +1737,11 @@ namespace Ryujinx.Ava.UI.ViewModels await LoadApplication(applicationData); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public static bool InitializeUserConfig(ApplicationData application) @@ -1900,6 +1949,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenBinFile() { + OsUtils.SetCoreDumpable(true); + if (AppHost.Device.System.SearchingForAmiibo(out _) && IsGameRunning) { Optional result = await StorageProvider.OpenSingleFilePickerAsync( @@ -1919,6 +1970,11 @@ namespace Ryujinx.Ava.UI.ViewModels { AppHost.Device.System.ScanAmiiboFromBin(result.Value.Path.LocalPath); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } } public async Task OpenSkylanderWindow() diff --git a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs index 45e67add0..569d293e6 100644 --- a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs @@ -288,6 +288,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async void Add() { + OsUtils.SetCoreDumpable(true); + IReadOnlyList result = await _storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.SelectModDialogTitle], @@ -298,6 +300,11 @@ namespace Ryujinx.Ava.UI.ViewModels { AddMod(new DirectoryInfo(folder.Path.LocalPath)); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public void DeleteAll() diff --git a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs index 3d34643ab..c10da7bf9 100644 --- a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs @@ -7,6 +7,7 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.IO; using System.Linq; @@ -148,6 +149,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task Add() { + OsUtils.SetCoreDumpable(true); + IReadOnlyList result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { AllowMultiple = true, @@ -177,6 +180,11 @@ namespace Ryujinx.Ava.UI.ViewModels { await ShowNewUpdatesAddedDialog(totalUpdatesAdded); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } public void Save() diff --git a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs index f0742a579..62e4e72a6 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs @@ -7,6 +7,7 @@ using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.Utilities; +using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.IO; using System.Linq; @@ -27,6 +28,8 @@ namespace Ryujinx.Ava.UI.Views.Settings private async Task AddDirButton(TextBox addDirBox, AvaloniaList directories) { + OsUtils.SetCoreDumpable(true); + string path = addDirBox.Text; if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !directories.Contains(path)) @@ -48,6 +51,11 @@ namespace Ryujinx.Ava.UI.Views.Settings ViewModel.GameListNeedsRefresh = true; } } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } private void RemoveGameDirButton_OnClick(object sender, RoutedEventArgs e) diff --git a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs index 3a5b7c6b7..9b9cc3303 100644 --- a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs @@ -8,6 +8,7 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; +using Ryujinx.Common.Utilities; using Ryujinx.HLE.FileSystem; using SkiaSharp; using System.Collections.Generic; @@ -62,6 +63,8 @@ namespace Ryujinx.Ava.UI.Views.User private async void Import_OnClick(object sender, RoutedEventArgs e) { + OsUtils.SetCoreDumpable(true); + IReadOnlyList result = await ((Window)this.GetVisualRoot()!).StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { AllowMultiple = false, @@ -81,6 +84,11 @@ namespace Ryujinx.Ava.UI.Views.User _profile.Image = ProcessProfileImage(File.ReadAllBytes(result[0].Path.LocalPath)); _parent.GoBack(); } + + if (!Program.CoreDumpArg) + { + OsUtils.SetCoreDumpable(false); + } } private void GoBack(object sender, RoutedEventArgs e) From b36667e2160f5de925cfe4715cc839bda2fbe5bc Mon Sep 17 00:00:00 2001 From: KeatonTheBot Date: Fri, 6 Mar 2026 18:13:04 -0600 Subject: [PATCH 11/18] Move SetCoreDumpable call to StorageProviderExtensions --- src/Ryujinx/Common/ApplicationHelper.cs | 15 ----- .../DownloadableContentManagerViewModel.cs | 8 --- .../UI/ViewModels/MainWindowViewModel.cs | 56 ------------------- .../UI/ViewModels/ModManagerViewModel.cs | 7 --- .../UI/ViewModels/TitleUpdateViewModel.cs | 8 --- .../UI/Views/Settings/SettingsUIView.axaml.cs | 8 --- .../UserProfileImageSelectorView.axaml.cs | 8 --- 7 files changed, 110 deletions(-) diff --git a/src/Ryujinx/Common/ApplicationHelper.cs b/src/Ryujinx/Common/ApplicationHelper.cs index f958c0159..3efd9ed62 100644 --- a/src/Ryujinx/Common/ApplicationHelper.cs +++ b/src/Ryujinx/Common/ApplicationHelper.cs @@ -18,7 +18,6 @@ using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; using Ryujinx.Common.Helper; using Ryujinx.Common.Logging; -using Ryujinx.Common.Utilities; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.Loaders.Processes.Extensions; @@ -411,8 +410,6 @@ namespace Ryujinx.Ava.Common public static async Task ExtractAoc(IStorageProvider storageProvider, string updateFilePath, string updateName) { - OsUtils.SetCoreDumpable(true); - Gommon.Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] @@ -422,17 +419,10 @@ namespace Ryujinx.Ava.Common return; ExtractAoc(result.Value.Path.LocalPath, updateFilePath, updateName); - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) { - OsUtils.SetCoreDumpable(true); - Gommon.Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] @@ -442,11 +432,6 @@ namespace Ryujinx.Ava.Common return; ExtractSection(result.Value.Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex); - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token) diff --git a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs index 0bec24945..39e53184f 100644 --- a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs @@ -8,7 +8,6 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; @@ -129,8 +128,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async void Add() { - OsUtils.SetCoreDumpable(true); - IReadOnlyList result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle], @@ -161,11 +158,6 @@ namespace Ryujinx.Ava.UI.ViewModels { await ShowNewDlcAddedDialog(totalDlcAdded); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } private bool AddDownloadableContent(string path, out int numDlcAdded) diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index b8062d659..ae84a15a2 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1323,8 +1323,6 @@ namespace Ryujinx.Ava.UI.ViewModels private async Task LoadContentFromFolder(LocaleKeys localeMessageAddedKey, LocaleKeys localeMessageRemovedKey, LoadContentFromFolderDelegate onDirsSelected, LocaleKeys dirSelectDialogTitle) { - OsUtils.SetCoreDumpable(true); - Optional> result = await StorageProvider.OpenMultiFolderPickerAsync( new FolderPickerOpenOptions { Title = LocaleManager.Instance[dirSelectDialogTitle] }); @@ -1352,11 +1350,6 @@ namespace Ryujinx.Ava.UI.ViewModels (int)Symbol.Checkmark); }); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } #endregion @@ -1419,8 +1412,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task InstallFirmwareFromFile() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { FileTypeFilter = new List @@ -1450,34 +1441,20 @@ namespace Ryujinx.Ava.UI.ViewModels { await HandleFirmwareInstallation(result.Value.Path.LocalPath); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public async Task InstallFirmwareFromFolder() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFolderPickerAsync(); if (result.HasValue) { await HandleFirmwareInstallation(result.Value.Path.LocalPath); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public async Task InstallKeysFromFile() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { FileTypeFilter = new List @@ -1495,28 +1472,16 @@ namespace Ryujinx.Ava.UI.ViewModels { await HandleKeysInstallation(result.Value.Path.LocalPath); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public async Task InstallKeysFromFolder() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFolderPickerAsync(); if (result.HasValue) { await HandleKeysInstallation(result.Value.Path.LocalPath); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public void OpenRyujinxFolder() @@ -1620,8 +1585,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenFile() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.LoadApplicationFromFileDialogTitle], @@ -1693,11 +1656,6 @@ namespace Ryujinx.Ava.UI.ViewModels LocaleManager.Instance[LocaleKeys.MenuBarFileOpenFromFileError]); } } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public async Task LoadDlcFromFolder() @@ -1720,8 +1678,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenFolder() { - OsUtils.SetCoreDumpable(true); - Optional result = await StorageProvider.OpenSingleFolderPickerAsync( new FolderPickerOpenOptions { @@ -1737,11 +1693,6 @@ namespace Ryujinx.Ava.UI.ViewModels await LoadApplication(applicationData); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public static bool InitializeUserConfig(ApplicationData application) @@ -1949,8 +1900,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenBinFile() { - OsUtils.SetCoreDumpable(true); - if (AppHost.Device.System.SearchingForAmiibo(out _) && IsGameRunning) { Optional result = await StorageProvider.OpenSingleFilePickerAsync( @@ -1970,11 +1919,6 @@ namespace Ryujinx.Ava.UI.ViewModels { AppHost.Device.System.ScanAmiiboFromBin(result.Value.Path.LocalPath); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } } public async Task OpenSkylanderWindow() diff --git a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs index 569d293e6..45e67add0 100644 --- a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs @@ -288,8 +288,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async void Add() { - OsUtils.SetCoreDumpable(true); - IReadOnlyList result = await _storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.SelectModDialogTitle], @@ -300,11 +298,6 @@ namespace Ryujinx.Ava.UI.ViewModels { AddMod(new DirectoryInfo(folder.Path.LocalPath)); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public void DeleteAll() diff --git a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs index c10da7bf9..3d34643ab 100644 --- a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs @@ -7,7 +7,6 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.IO; using System.Linq; @@ -149,8 +148,6 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task Add() { - OsUtils.SetCoreDumpable(true); - IReadOnlyList result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { AllowMultiple = true, @@ -180,11 +177,6 @@ namespace Ryujinx.Ava.UI.ViewModels { await ShowNewUpdatesAddedDialog(totalUpdatesAdded); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } public void Save() diff --git a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs index 62e4e72a6..f0742a579 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs @@ -7,7 +7,6 @@ using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.Utilities; -using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.IO; using System.Linq; @@ -28,8 +27,6 @@ namespace Ryujinx.Ava.UI.Views.Settings private async Task AddDirButton(TextBox addDirBox, AvaloniaList directories) { - OsUtils.SetCoreDumpable(true); - string path = addDirBox.Text; if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !directories.Contains(path)) @@ -51,11 +48,6 @@ namespace Ryujinx.Ava.UI.Views.Settings ViewModel.GameListNeedsRefresh = true; } } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } private void RemoveGameDirButton_OnClick(object sender, RoutedEventArgs e) diff --git a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs index 9b9cc3303..3a5b7c6b7 100644 --- a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs @@ -8,7 +8,6 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; -using Ryujinx.Common.Utilities; using Ryujinx.HLE.FileSystem; using SkiaSharp; using System.Collections.Generic; @@ -63,8 +62,6 @@ namespace Ryujinx.Ava.UI.Views.User private async void Import_OnClick(object sender, RoutedEventArgs e) { - OsUtils.SetCoreDumpable(true); - IReadOnlyList result = await ((Window)this.GetVisualRoot()!).StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { AllowMultiple = false, @@ -84,11 +81,6 @@ namespace Ryujinx.Ava.UI.Views.User _profile.Image = ProcessProfileImage(File.ReadAllBytes(result[0].Path.LocalPath)); _parent.GoBack(); } - - if (!Program.CoreDumpArg) - { - OsUtils.SetCoreDumpable(false); - } } private void GoBack(object sender, RoutedEventArgs e) From 33d133e2ac2e5f9b5ba6ee89a2042372f2d3fd60 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 02:40:18 -0400 Subject: [PATCH 12/18] [HLE] Renamed INotificationServicesForSystem and implemented a commands (and stubs) Should allow Ring Fit to get in-game, needs testing. --- .../INotificationServicesForApplication.cs | 26 +++++++++++++++++++ .../INotificationServicesForSystem.cs | 8 ------ .../INotificationSystemEventAccessor.cs | 17 ++++++++++++ 3 files changed, 43 insertions(+), 8 deletions(-) delete mode 100644 src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForSystem.cs create mode 100644 src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs index 29f8bfa85..37fd0fbee 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs @@ -4,5 +4,31 @@ namespace Ryujinx.HLE.HOS.Services.Notification class INotificationServicesForApplication : IpcService { public INotificationServicesForApplication(ServiceCtx context) { } + + [CommandCmif(520)] // 9.0.0+ + // ListAlarmSettings(nn::arp::ApplicationCertificate) -> s32 AlarmSettingsCount + public ResultCode ListAlarmSettings(ServiceCtx context) + { + // TO-DO: Currently just returns 0. Should read in an ApplicationCertificate. + int alarmSettingsCount = 0; + context.ResponseData.Write(alarmSettingsCount); + return ResultCode.Success; + } + + [CommandCmif(1000)] // 9.0.0+ + // GetNotificationCount() -> nn::notification::server::INotificationSystemEventAccessor + public ResultCode GetNotificationCount(ServiceCtx context) + { + MakeObject(context, new INotificationSystemEventAccessor(context)); + return ResultCode.Success; + } + + [CommandCmif(1040)] // 9.0.0+ + // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor + public ResultCode GetNotificationSendingNotifier(ServiceCtx context) + { + MakeObject(context, new INotificationSystemEventAccessor(context)); + return ResultCode.Success; + } } } diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForSystem.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForSystem.cs deleted file mode 100644 index c5946be84..000000000 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForSystem.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Ryujinx.HLE.HOS.Services.Notification -{ - [Service("notif:s")] // 9.0.0+ - class INotificationServicesForSystem : IpcService - { - public INotificationServicesForSystem(ServiceCtx context) { } - } -} diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs new file mode 100644 index 000000000..9298c26bb --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs @@ -0,0 +1,17 @@ +using Ryujinx.Common.Logging; + +namespace Ryujinx.HLE.HOS.Services.Notification +{ + class INotificationSystemEventAccessor : IpcService + { + public INotificationSystemEventAccessor(ServiceCtx context) { } + + [CommandCmif(0)] // 9.0.0+ + // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor + public ResultCode GetSystemEvent(ServiceCtx context) + { + Logger.Stub?.PrintStub(LogClass.Service); + return ResultCode.Success; + } + } +} From 9b46cc42018608f3ee223fcc71fc6b410fc9198b Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 09:51:29 -0400 Subject: [PATCH 13/18] rider moment --- .../Notification/INotificationServices.cs | 24 +++++++++++++++++++ .../INotificationServicesForApplication.cs | 16 ------------- 2 files changed, 24 insertions(+), 16 deletions(-) create mode 100644 src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs new file mode 100644 index 000000000..4dd0beebf --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs @@ -0,0 +1,24 @@ +namespace Ryujinx.HLE.HOS.Services.Notification +{ + [Service("notif:s")] // 9.0.0+ + class INotificationServicesForSystem : IpcService + { + public INotificationServicesForSystem(ServiceCtx context) { } + + [CommandCmif(1000)] // 9.0.0+ + // GetNotificationCount() -> nn::notification::server::INotificationSystemEventAccessor + public ResultCode GetNotificationCount(ServiceCtx context) + { + MakeObject(context, new INotificationSystemEventAccessor(context)); + return ResultCode.Success; + } + + [CommandCmif(1040)] // 9.0.0+ + // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor + public ResultCode GetNotificationSendingNotifier(ServiceCtx context) + { + MakeObject(context, new INotificationSystemEventAccessor(context)); + return ResultCode.Success; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs index 37fd0fbee..b5ffcc877 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs @@ -14,21 +14,5 @@ namespace Ryujinx.HLE.HOS.Services.Notification context.ResponseData.Write(alarmSettingsCount); return ResultCode.Success; } - - [CommandCmif(1000)] // 9.0.0+ - // GetNotificationCount() -> nn::notification::server::INotificationSystemEventAccessor - public ResultCode GetNotificationCount(ServiceCtx context) - { - MakeObject(context, new INotificationSystemEventAccessor(context)); - return ResultCode.Success; - } - - [CommandCmif(1040)] // 9.0.0+ - // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor - public ResultCode GetNotificationSendingNotifier(ServiceCtx context) - { - MakeObject(context, new INotificationSystemEventAccessor(context)); - return ResultCode.Success; - } } } From 8e02d091e4d59c8c8f3abb0886c65c6cb74fdd89 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 09:52:31 -0400 Subject: [PATCH 14/18] renamed a file because i forgor --- .../HOS/Services/Notification/INotificationServices.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs index 4dd0beebf..e44983fce 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServices.cs @@ -1,9 +1,9 @@ namespace Ryujinx.HLE.HOS.Services.Notification { [Service("notif:s")] // 9.0.0+ - class INotificationServicesForSystem : IpcService + class INotificationServices : IpcService { - public INotificationServicesForSystem(ServiceCtx context) { } + public INotificationServices(ServiceCtx context) { } [CommandCmif(1000)] // 9.0.0+ // GetNotificationCount() -> nn::notification::server::INotificationSystemEventAccessor From fbc90b08628a2ec27da530053066bdde2c820a66 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 13:54:40 -0400 Subject: [PATCH 15/18] new stub + LogClass enum update --- .../INotificationServicesForApplication.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs index b5ffcc877..48457f745 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs @@ -1,3 +1,5 @@ +using Ryujinx.Common.Logging; + namespace Ryujinx.HLE.HOS.Services.Notification { [Service("notif:a")] // 9.0.0+ @@ -5,6 +7,8 @@ namespace Ryujinx.HLE.HOS.Services.Notification { public INotificationServicesForApplication(ServiceCtx context) { } + // Leaving this here since I can never find it: https://switchbrew.org/wiki/Glue_services + [CommandCmif(520)] // 9.0.0+ // ListAlarmSettings(nn::arp::ApplicationCertificate) -> s32 AlarmSettingsCount public ResultCode ListAlarmSettings(ServiceCtx context) @@ -14,5 +18,16 @@ namespace Ryujinx.HLE.HOS.Services.Notification context.ResponseData.Write(alarmSettingsCount); return ResultCode.Success; } + + [CommandCmif(1000)] // 9.0.0+ + // Initialize(PID-descriptor, u64 pid_reserved) + public ResultCode Intialize(ServiceCtx context) + { + ulong PID = context.Device.Processes.ActiveApplication.ProgramId; + ulong pid_reserved = context.Device.Processes.ActiveApplication.ProcessId; + + Logger.Stub?.PrintStub(LogClass.ServiceNotification, new { PID, pid_reserved }); + return ResultCode.Success; + } } } From b330df999939cc3e8c3c07abcc7b82b78bbf2a90 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 13:59:56 -0400 Subject: [PATCH 16/18] ??? --- src/Ryujinx.Common/Logging/LogClass.cs | 1 + .../Services/Notification/INotificationSystemEventAccessor.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Common/Logging/LogClass.cs b/src/Ryujinx.Common/Logging/LogClass.cs index 7c6810599..0e02cfcc2 100644 --- a/src/Ryujinx.Common/Logging/LogClass.cs +++ b/src/Ryujinx.Common/Logging/LogClass.cs @@ -51,6 +51,7 @@ namespace Ryujinx.Common.Logging ServiceNgct, ServiceNifm, ServiceNim, + ServiceNotification, ServiceNs, ServiceNsd, ServiceNtc, diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs index 9298c26bb..1f34d4496 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs @@ -10,7 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Notification // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor public ResultCode GetSystemEvent(ServiceCtx context) { - Logger.Stub?.PrintStub(LogClass.Service); + Logger.Stub?.PrintStub(LogClass.ServiceNotification); return ResultCode.Success; } } From 20e88d625febe65adbe368946c0701708850482a Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 14:26:14 -0400 Subject: [PATCH 17/18] fixed initialize pid request --- .../Notification/INotificationServicesForApplication.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs index 48457f745..498fc52fb 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationServicesForApplication.cs @@ -23,10 +23,10 @@ namespace Ryujinx.HLE.HOS.Services.Notification // Initialize(PID-descriptor, u64 pid_reserved) public ResultCode Intialize(ServiceCtx context) { - ulong PID = context.Device.Processes.ActiveApplication.ProgramId; - ulong pid_reserved = context.Device.Processes.ActiveApplication.ProcessId; + ulong pid = context.Request.HandleDesc.PId; + context.RequestData.ReadUInt64(); // pid placeholder, zero - Logger.Stub?.PrintStub(LogClass.ServiceNotification, new { PID, pid_reserved }); + Logger.Stub?.PrintStub(LogClass.ServiceNotification, new { pid }); return ResultCode.Success; } } From bd9b5d170785214e146ad8c8bba648758fee32a6 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 14 Mar 2026 16:44:00 -0400 Subject: [PATCH 18/18] handled the handles --- .../INotificationSystemEventAccessor.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs index 1f34d4496..8cca7cc6e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Notification/INotificationSystemEventAccessor.cs @@ -1,16 +1,31 @@ using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.Horizon.Common; +using System; namespace Ryujinx.HLE.HOS.Services.Notification { class INotificationSystemEventAccessor : IpcService { + + private readonly KEvent _getNotificationSendingNotifierEvent; + private int _getNotificationSendingNotifierEventHandle; public INotificationSystemEventAccessor(ServiceCtx context) { } - + [CommandCmif(0)] // 9.0.0+ // GetNotificationSendingNotifier() -> nn::notification::server::INotificationSystemEventAccessor public ResultCode GetSystemEvent(ServiceCtx context) { - Logger.Stub?.PrintStub(LogClass.ServiceNotification); + if (_getNotificationSendingNotifierEventHandle == 0) + { + if (context.Process.HandleTable.GenerateHandle(_getNotificationSendingNotifierEvent.ReadableEvent, out _getNotificationSendingNotifierEventHandle) != Result.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_getNotificationSendingNotifierEventHandle); return ResultCode.Success; } }