From 5ae86fc493a2e26555648c29f8913293e26f5ae0 Mon Sep 17 00:00:00 2001 From: BowedCascade <110-BowedCascade@users.noreply.git.ryujinx.app> Date: Sat, 14 Mar 2026 13:52:58 -0500 Subject: [PATCH 1/3] Fix keys file overwrite on installation and method name typo (ryubing/ryujinx!268) See merge request ryubing/ryujinx!268 --- src/Ryujinx.HLE/FileSystem/ContentManager.cs | 19 +++++++++---------- .../UI/ViewModels/MainWindowViewModel.cs | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/Ryujinx.HLE/FileSystem/ContentManager.cs b/src/Ryujinx.HLE/FileSystem/ContentManager.cs index d0fe0f1a7..d6eedd32f 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentManager.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentManager.cs @@ -488,6 +488,8 @@ namespace Ryujinx.HLE.FileSystem if (keyPaths.Length is 0) throw new FileNotFoundException($"Directory '{keysSource}' contained no '.keys' files."); + List failedFiles = new(); + foreach (string filePath in keyPaths) { try @@ -497,17 +499,20 @@ namespace Ryujinx.HLE.FileSystem catch (Exception e) { Logger.Error?.Print(LogClass.Application, e.Message); + failedFiles.Add(Path.GetFileName(filePath)); continue; } string destPath = Path.Combine(installDirectory, Path.GetFileName(filePath)); - if (File.Exists(destPath)) - File.Delete(destPath); - File.Copy(filePath, destPath, true); } + if (failedFiles.Count > 0) + { + throw new InvalidOperationException($"Failed to install the following key files: {string.Join(", ", failedFiles)}"); + } + return; } @@ -518,8 +523,6 @@ namespace Ryujinx.HLE.FileSystem FileInfo info = new(keysSource); - using FileStream file = File.OpenRead(keysSource); - if (info.Extension is not ".keys") throw new InvalidFirmwarePackageException("Input file extension is not .keys"); @@ -534,10 +537,6 @@ namespace Ryujinx.HLE.FileSystem string dest = Path.Combine(installDirectory, info.Name); - if (File.Exists(dest)) - File.Delete(dest); - - // overwrite: true seems to not work on its own? https://github.com/Ryubing/Issues/issues/189 File.Copy(keysSource, dest, true); } @@ -1059,7 +1058,7 @@ namespace Ryujinx.HLE.FileSystem } } - public static bool AreKeysAlredyPresent(string pathToCheck) + public static bool AreKeysAlreadyPresent(string pathToCheck) { string[] fileNames = ["prod.keys", "title.keys", "console.keys", "dev.keys"]; foreach (string file in fileNames) diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 48e18a12e..1c8235010 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1062,7 +1062,7 @@ namespace Ryujinx.Ava.UI.ViewModels string dialogMessage = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallMessage); - if (ContentManager.AreKeysAlredyPresent(systemDirectory)) + if (ContentManager.AreKeysAlreadyPresent(systemDirectory)) { dialogMessage += LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys From 648b609ebb5472b717a82891adee578cc8bf7ade Mon Sep 17 00:00:00 2001 From: BowedCascade <110-BowedCascade@users.noreply.git.ryujinx.app> Date: Sat, 14 Mar 2026 13:56:20 -0500 Subject: [PATCH 2/3] Add restart emulation command (ryubing/ryujinx!276) See merge request ryubing/ryujinx!276 --- assets/Locales/Root.json | 27 ++++++++++++++++++- .../UI/ViewModels/MainWindowViewModel.cs | 24 +++++++++++++++++ .../UI/Views/Main/MainMenuBarView.axaml | 6 +++++ .../UI/Views/Main/MainMenuBarView.axaml.cs | 1 + src/Ryujinx/UI/Windows/MainWindow.axaml | 1 + 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/assets/Locales/Root.json b/assets/Locales/Root.json index c427ea78b..ac9aa09a4 100644 --- a/assets/Locales/Root.json +++ b/assets/Locales/Root.json @@ -575,6 +575,31 @@ "zh_TW": "停止模擬" } }, + { + "ID": "MenuBarOptionsRestartEmulation", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Restart Emulation", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "MenuBarOptionsSettings", "Translations": { @@ -24876,4 +24901,4 @@ } } ] -} +} \ No newline at end of file diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 1c8235010..ae84a15a2 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -174,6 +174,7 @@ namespace Ryujinx.Ava.UI.ViewModels private string _screenshotKey = "F8"; private float _volume; private ApplicationData _currentApplicationData; + private bool _pendingRestart; private readonly AutoResetEvent _rendererWaitEvent; private int _customVSyncInterval; private int _customVSyncIntervalPercentageProxy; @@ -1250,6 +1251,14 @@ namespace Ryujinx.Ava.UI.ViewModels await LoadApplication(_currentApplicationData); } + else if (_pendingRestart) + { + _pendingRestart = false; + + Logger.Info?.Print(LogClass.Application, $"Restarting emulation for '{_currentApplicationData.Name}'"); + + await LoadApplication(_currentApplicationData); + } else { // Otherwise, clear state. @@ -1258,6 +1267,21 @@ namespace Ryujinx.Ava.UI.ViewModels } } + public void RestartEmulation() + { + if (AppHost is null || _currentApplicationData is null) + { + Logger.Warning?.Print(LogClass.Application, "RestartEmulation called but no application is running."); + + return; + } + + Logger.Info?.Print(LogClass.Application, $"Restart requested for '{_currentApplicationData.Name}'"); + + _pendingRestart = true; + AppHost.Stop(); + } + private void Update_StatusBar(object sender, StatusUpdatedEventArgs args) { if (ShowMenuAndStatusBar && !ShowLoadProgress) diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml index d5a59c181..5e41017d8 100755 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml @@ -167,6 +167,12 @@ Icon="{ext:Icon fa-solid fa-stop}" InputGesture="Escape" IsEnabled="{Binding IsGameRunning}" /> + ViewModel.AppHost?.Pause()); ResumeEmulationMenuItem.Command = Commands.Create(() => ViewModel.AppHost?.Resume()); StopEmulationMenuItem.Command = Commands.Create(() => ViewModel.AppHost?.ShowExitPrompt().OrCompleted()); + RestartEmulationMenuItem.Command = Commands.Create(() => ViewModel.RestartEmulation()); CheatManagerMenuItem.Command = Commands.CreateSilentFail(OpenCheatManagerForCurrentApp); InstallFileTypesMenuItem.Command = Commands.Create(InstallFileTypes); UninstallFileTypesMenuItem.Command = Commands.Create(UninstallFileTypes); diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml b/src/Ryujinx/UI/Windows/MainWindow.axaml index b7385c9cb..39a70ba16 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml @@ -41,6 +41,7 @@ + From 9cae62096a543f084469ab28832ac903012e4c9f Mon Sep 17 00:00:00 2001 From: Coxxs <58-coxxs@users.noreply.git.ryujinx.app> Date: Sat, 14 Mar 2026 13:57:49 -0500 Subject: [PATCH 3/3] HLE: Implement CreateContextForSystem (ryubing/ryujinx!285) See merge request ryubing/ryujinx!285 --- src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs b/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs index 8f38f293f..3d8fb5d51 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs @@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Ssl public ISslService(ServiceCtx context) { } [CommandCmif(0)] - // CreateContext(nn::ssl::sf::SslVersion, u64, pid) -> object + // CreateContext(nn::ssl::sf::SslVersion, u64 pid_placeholder, pid) -> object public ResultCode CreateContext(ServiceCtx context) { SslVersion sslVersion = (SslVersion)context.RequestData.ReadUInt32(); @@ -126,14 +126,18 @@ namespace Ryujinx.HLE.HOS.Services.Ssl } [CommandCmif(100)] - // CreateContextForSystem(u64 pid, nn::ssl::sf::SslVersion, u64) + // CreateContextForSystem(nn::ssl::sf::SslVersion, u64 pid_placeholder, pid) -> object public ResultCode CreateContextForSystem(ServiceCtx context) { - ulong pid = context.RequestData.ReadUInt64(); SslVersion sslVersion = (SslVersion)context.RequestData.ReadUInt32(); +#pragma warning disable IDE0059 // Remove unnecessary value assignment ulong pidPlaceholder = context.RequestData.ReadUInt64(); +#pragma warning restore IDE0059 - Logger.Stub?.PrintStub(LogClass.ServiceSsl, new { pid, sslVersion, pidPlaceholder }); + // Note: We use ISslContext here instead of ISslContextForSystem class because Ryujinx implements both in one class. + MakeObject(context, new ISslContext(context.Request.HandleDesc.PId, sslVersion)); + + Logger.Stub?.PrintStub(LogClass.ServiceSsl, new { sslVersion }); return ResultCode.Success; }