From 4f5af0ecf3f02b954682d02062c7765947e0a024 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:53:08 +0100 Subject: [PATCH 1/6] Added Tool for installing keys --- src/Ryujinx.HLE/FileSystem/ContentManager.cs | 68 ++++++++ src/Ryujinx/Assets/Locales/en_US.json | 10 ++ .../UI/ViewModels/MainWindowViewModel.cs | 146 ++++++++++++++++++ .../UI/Views/Main/MainMenuBarView.axaml | 4 + 4 files changed, 228 insertions(+) diff --git a/src/Ryujinx.HLE/FileSystem/ContentManager.cs b/src/Ryujinx.HLE/FileSystem/ContentManager.cs index fc8def9d21..31c293ebb7 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentManager.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentManager.cs @@ -8,6 +8,7 @@ using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.NcaUtils; using LibHac.Tools.Ncm; +using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Common.Memory; using Ryujinx.Common.Utilities; @@ -474,6 +475,56 @@ public void InstallFirmware(string firmwareSource) FinishInstallation(temporaryDirectory, registeredDirectory); } + public void InstallKeys(string keysSource) + { + string systemDirectory = AppDataManager.KeysDirPath; + //if(AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile) + //{ + // systemDirectory = AppDataManager.KeysDirPathUser; + //} + + if (Directory.Exists(keysSource)) + { + foreach (var filePath in Directory.EnumerateFiles(keysSource, "*.keys")) + { + File.Copy(filePath, Path.Combine(systemDirectory, Path.GetFileName(filePath)), true); + } + + return; + } + + if (!File.Exists(keysSource)) + { + throw new FileNotFoundException("Keys file does not exist."); + } + + FileInfo info = new(keysSource); + + using FileStream file = File.OpenRead(keysSource); + + switch (info.Extension) + { + case ".zip": + using (ZipArchive archive = ZipFile.OpenRead(keysSource)) + { + + foreach (var entry in archive.Entries) + { + if (Path.GetExtension(entry.FullName).Equals(".keys", StringComparison.OrdinalIgnoreCase)) + { + entry.ExtractToFile(Path.Combine(systemDirectory, entry.Name), overwrite: true); + } + } + } + break; + case ".keys": + File.Copy(keysSource, Path.Combine(systemDirectory, info.Name), true); + break; + default: + throw new InvalidFirmwarePackageException("Input file is not a valid key package"); + } + } + private void FinishInstallation(string temporaryDirectory, string registeredDirectory) { if (Directory.Exists(registeredDirectory)) @@ -947,5 +998,22 @@ public SystemVersion GetCurrentFirmwareVersion() return null; } + + public bool AreKeysAlredyPresent() + { + if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")) && !File.Exists(Path.Combine(AppDataManager.KeysDirPath, "title.keys"))) + { + if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile && (File.Exists(Path.Combine(AppDataManager.KeysDirPathUser, "prod.keys")) || File.Exists(Path.Combine(AppDataManager.KeysDirPathUser, "title.keys")))) + { + return true; + } + } + else + { + return true; + } + + return false; + } } } diff --git a/src/Ryujinx/Assets/Locales/en_US.json b/src/Ryujinx/Assets/Locales/en_US.json index fdd2d4df20..53f8653873 100644 --- a/src/Ryujinx/Assets/Locales/en_US.json +++ b/src/Ryujinx/Assets/Locales/en_US.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "Install Firmware", "MenuBarFileToolsInstallFirmwareFromFile": "Install a firmware from XCI or ZIP", "MenuBarFileToolsInstallFirmwareFromDirectory": "Install a firmware from a directory", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "Manage file types", "MenuBarToolsInstallFileTypes": "Install file types", "MenuBarToolsUninstallFileTypes": "Uninstall file types", @@ -504,6 +507,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDo you want to continue?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installing firmware...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "System version {0} successfully installed.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "A valid Keys file was not found in {0}.", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis will replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "There would be no other profiles to be opened if selected profile is deleted", "DialogUserProfileDeletionConfirmMessage": "Do you want to delete the selected profile", "DialogUserProfileUnsavedChangesTitle": "Warning - Unsaved Changes", diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 53263847b0..233e2d5bff 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1180,6 +1180,105 @@ await ContentDialogHelper.CreateInfoDialog( } } + private async Task HandleKeysInstallation(string filename) + { + try + { + //bool isValidKeysFilke = true; + + //if (!isValidKeysFilke) + //{ + // await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysNotFoundErrorMessage, filename)); + + // return; + //} + + string dialogTitle = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallTitle); + string dialogMessage = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallMessage); + + bool alreadyKesyInstalled = ContentManager.AreKeysAlredyPresent(); + if (alreadyKesyInstalled) + { + dialogMessage += LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallSubMessage); + } + + dialogMessage += LocaleManager.Instance[LocaleKeys.DialogKeysInstallerKeysInstallConfirmMessage]; + + UserResult result = await ContentDialogHelper.CreateConfirmationDialog( + dialogTitle, + dialogMessage, + LocaleManager.Instance[LocaleKeys.InputDialogYes], + LocaleManager.Instance[LocaleKeys.InputDialogNo], + LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); + + UpdateWaitWindow waitingDialog = new(dialogTitle, LocaleManager.Instance[LocaleKeys.DialogKeysInstallerKeysInstallWaitMessage]); + + if (result == UserResult.Yes) + { + Logger.Info?.Print(LogClass.Application, $"Installing Keys"); + + Thread thread = new(() => + { + Dispatcher.UIThread.InvokeAsync(delegate + { + waitingDialog.Show(); + }); + + try + { + ContentManager.InstallKeys(filename); + + Dispatcher.UIThread.InvokeAsync(async delegate + { + waitingDialog.Close(); + + string message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallSuccessMessage); + + await ContentDialogHelper.CreateInfoDialog( + dialogTitle, + message, + LocaleManager.Instance[LocaleKeys.InputDialogOk], + string.Empty, + LocaleManager.Instance[LocaleKeys.RyujinxInfo]); + + Logger.Info?.Print(LogClass.Application, message); + }); + } + catch (Exception ex) + { + Dispatcher.UIThread.InvokeAsync(async () => + { + waitingDialog.Close(); + + await ContentDialogHelper.CreateErrorDialog(ex.Message); + }); + } + finally + { + VirtualFileSystem.ReloadKeySet(); + } + }) + { + Name = "GUI.KeysInstallerThread", + }; + + thread.Start(); + } + } + catch (MissingKeyException ex) + { + if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime) + { + Logger.Error?.Print(LogClass.Application, ex.ToString()); + + await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys); + } + } + catch (Exception ex) + { + await ContentDialogHelper.CreateErrorDialog(ex.Message); + } + } private void ProgressHandler(T state, int current, int total) where T : Enum { Dispatcher.UIThread.Post(() => @@ -1467,6 +1566,53 @@ public async Task InstallFirmwareFromFolder() } } + public async Task InstallKeysFromFile() + { + var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions + { + AllowMultiple = false, + FileTypeFilter = new List + { + new(LocaleManager.Instance[LocaleKeys.FileDialogAllTypes]) + { + Patterns = new[] { "*.keys", "*.zip" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci", "public.zip-archive" }, + MimeTypes = new[] { "application/keys", "application/zip" }, + }, + new("KEYS") + { + Patterns = new[] { "*.keys" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" }, + MimeTypes = new[] { "application/keys" }, + }, + new("ZIP") + { + Patterns = new[] { "*.zip" }, + AppleUniformTypeIdentifiers = new[] { "public.zip-archive" }, + MimeTypes = new[] { "application/zip" }, + }, + }, + }); + + if (result.Count > 0) + { + await HandleKeysInstallation(result[0].Path.LocalPath); + } + } + + public async Task InstallKeysFromFolder() + { + var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions + { + AllowMultiple = false, + }); + + if (result.Count > 0) + { + await HandleKeysInstallation(result[0].Path.LocalPath); + } + } + public void OpenRyujinxFolder() { OpenHelper.OpenFolder(AppDataManager.BaseDirPath); diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml index 883bf89711..1cc9f22cd4 100644 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml @@ -264,6 +264,10 @@ + + + + From 9e921ae5c8eb15fbf78c1a4899d6b67500e2ec8f Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:54:33 +0100 Subject: [PATCH 2/6] Implemented missing code sections --- src/Ryujinx.HLE/FileSystem/ContentManager.cs | 89 +++++++++++++------ src/Ryujinx/Assets/Locales/en_US.json | 4 +- .../UI/ViewModels/MainWindowViewModel.cs | 25 +++--- 3 files changed, 80 insertions(+), 38 deletions(-) diff --git a/src/Ryujinx.HLE/FileSystem/ContentManager.cs b/src/Ryujinx.HLE/FileSystem/ContentManager.cs index 31c293ebb7..38386bc995 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentManager.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentManager.cs @@ -8,7 +8,6 @@ using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.NcaUtils; using LibHac.Tools.Ncm; -using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Common.Memory; using Ryujinx.Common.Utilities; @@ -22,6 +21,7 @@ using System.IO.Compression; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using Path = System.IO.Path; namespace Ryujinx.HLE.FileSystem @@ -475,19 +475,14 @@ public void InstallFirmware(string firmwareSource) FinishInstallation(temporaryDirectory, registeredDirectory); } - public void InstallKeys(string keysSource) + public void InstallKeys(string keysSource, string installDirectory) { - string systemDirectory = AppDataManager.KeysDirPath; - //if(AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile) - //{ - // systemDirectory = AppDataManager.KeysDirPathUser; - //} - if (Directory.Exists(keysSource)) { foreach (var filePath in Directory.EnumerateFiles(keysSource, "*.keys")) { - File.Copy(filePath, Path.Combine(systemDirectory, Path.GetFileName(filePath)), true); + VerifyKeysFile(filePath); + File.Copy(filePath, Path.Combine(installDirectory, Path.GetFileName(filePath)), true); } return; @@ -507,24 +502,47 @@ public void InstallKeys(string keysSource) case ".zip": using (ZipArchive archive = ZipFile.OpenRead(keysSource)) { - - foreach (var entry in archive.Entries) - { - if (Path.GetExtension(entry.FullName).Equals(".keys", StringComparison.OrdinalIgnoreCase)) - { - entry.ExtractToFile(Path.Combine(systemDirectory, entry.Name), overwrite: true); - } - } + InstallKeysFromZip(archive, installDirectory); } break; case ".keys": - File.Copy(keysSource, Path.Combine(systemDirectory, info.Name), true); + VerifyKeysFile(keysSource); + File.Copy(keysSource, Path.Combine(installDirectory, info.Name), true); break; default: throw new InvalidFirmwarePackageException("Input file is not a valid key package"); } } + private void InstallKeysFromZip(ZipArchive archive, string installDirectory) + { + string temporaryDirectory = Path.Combine(installDirectory, "temp"); + if (Directory.Exists(temporaryDirectory)) + { + Directory.Delete(temporaryDirectory, true); + } + Directory.CreateDirectory(temporaryDirectory); + foreach (var entry in archive.Entries) + { + if (Path.GetExtension(entry.FullName).Equals(".keys", StringComparison.OrdinalIgnoreCase)) + { + string extractDestination = Path.Combine(temporaryDirectory, entry.Name); + entry.ExtractToFile(extractDestination, overwrite: true); + try + { + VerifyKeysFile(extractDestination); + File.Move(extractDestination, Path.Combine(installDirectory, entry.Name), true); + } + catch (Exception) + { + Directory.Delete(temporaryDirectory, true); + throw; + } + } + } + Directory.Delete(temporaryDirectory, true); + } + private void FinishInstallation(string temporaryDirectory, string registeredDirectory) { if (Directory.Exists(registeredDirectory)) @@ -999,20 +1017,41 @@ public SystemVersion GetCurrentFirmwareVersion() return null; } - public bool AreKeysAlredyPresent() + public void VerifyKeysFile(string filePath) { - if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")) && !File.Exists(Path.Combine(AppDataManager.KeysDirPath, "title.keys"))) + string schemaPattern = @"^[a-zA-Z0-9_]+ = [a-zA-Z0-9]+$"; + + if (File.Exists(filePath)) { - if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile && (File.Exists(Path.Combine(AppDataManager.KeysDirPathUser, "prod.keys")) || File.Exists(Path.Combine(AppDataManager.KeysDirPathUser, "title.keys")))) + // Read all lines from the file + string[] lines = File.ReadAllLines(filePath); + + for (int i = 0; i < lines.Length; i++) { - return true; + string line = lines[i].Trim(); + + // Check if the line matches the schema + if (!Regex.IsMatch(line, schemaPattern)) + { + throw new FormatException("Keys file doesn't have a correct schema."); + } } - } - else + } else { - return true; + throw new FileNotFoundException("Keys file not found at " + filePath); } + } + public bool AreKeysAlredyPresent(string pathToCheck) + { + string[] fileNames = { "prod.keys", "title.keys", "console.keys" }; + foreach (var file in fileNames) + { + if (File.Exists(Path.Combine(pathToCheck, file))) + { + return true; + } + } return false; } } diff --git a/src/Ryujinx/Assets/Locales/en_US.json b/src/Ryujinx/Assets/Locales/en_US.json index 53f8653873..9ddc9f4c44 100644 --- a/src/Ryujinx/Assets/Locales/en_US.json +++ b/src/Ryujinx/Assets/Locales/en_US.json @@ -507,10 +507,10 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDo you want to continue?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installing firmware...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "System version {0} successfully installed.", - "DialogKeysInstallerKeysNotFoundErrorMessage": "A valid Keys file was not found in {0}.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", "DialogKeysInstallerKeysInstallTitle": "Install Keys", "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", - "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis will replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 233e2d5bff..9ddfd746c8 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1184,19 +1184,16 @@ private async Task HandleKeysInstallation(string filename) { try { - //bool isValidKeysFilke = true; - - //if (!isValidKeysFilke) - //{ - // await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysNotFoundErrorMessage, filename)); - - // return; - //} + string systemDirectory = AppDataManager.KeysDirPath; + if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile && Directory.Exists(AppDataManager.KeysDirPathUser)) + { + systemDirectory = AppDataManager.KeysDirPathUser; + } string dialogTitle = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallTitle); string dialogMessage = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallMessage); - bool alreadyKesyInstalled = ContentManager.AreKeysAlredyPresent(); + bool alreadyKesyInstalled = ContentManager.AreKeysAlredyPresent(systemDirectory); if (alreadyKesyInstalled) { dialogMessage += LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallSubMessage); @@ -1226,7 +1223,7 @@ private async Task HandleKeysInstallation(string filename) try { - ContentManager.InstallKeys(filename); + ContentManager.InstallKeys(filename, systemDirectory); Dispatcher.UIThread.InvokeAsync(async delegate { @@ -1250,7 +1247,13 @@ await ContentDialogHelper.CreateInfoDialog( { waitingDialog.Close(); - await ContentDialogHelper.CreateErrorDialog(ex.Message); + string message = ex.Message; + if(ex is FormatException) + { + message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysNotFoundErrorMessage, filename); + } + + await ContentDialogHelper.CreateErrorDialog(message); }); } finally From d4afd62bc16d28ea1f66b8ed72a2e596f25247ca Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:50:38 +0100 Subject: [PATCH 3/6] Added missing translations --- src/Ryujinx/Assets/Locales/ar_SA.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/de_DE.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/el_GR.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/es_ES.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/fr_FR.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/he_IL.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/it_IT.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/ja_JP.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/ko_KR.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/pl_PL.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/pt_BR.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/ru_RU.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/th_TH.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/tr_TR.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/uk_UA.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/zh_CN.json | 10 ++++++++++ src/Ryujinx/Assets/Locales/zh_TW.json | 10 ++++++++++ 17 files changed, 170 insertions(+) diff --git a/src/Ryujinx/Assets/Locales/ar_SA.json b/src/Ryujinx/Assets/Locales/ar_SA.json index 781568fee9..dd1e3076ff 100644 --- a/src/Ryujinx/Assets/Locales/ar_SA.json +++ b/src/Ryujinx/Assets/Locales/ar_SA.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "تثبيت البرنامج الثابت", "MenuBarFileToolsInstallFirmwareFromFile": "تثبيت برنامج ثابت من XCI أو ZIP", "MenuBarFileToolsInstallFirmwareFromDirectory": "تثبيت برنامج ثابت من مجلد", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "إدارة أنواع الملفات", "MenuBarToolsInstallFileTypes": "تثبيت أنواع الملفات", "MenuBarToolsUninstallFileTypes": "إزالة أنواع الملفات", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\nهل تريد المتابعة؟", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "تثبيت البرنامج الثابت...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "تم تثبيت إصدار النظام {0} بنجاح.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "لن تكون هناك ملفات الشخصية أخرى لفتحها إذا تم حذف الملف الشخصي المحدد", "DialogUserProfileDeletionConfirmMessage": "هل تريد حذف الملف الشخصي المحدد", "DialogUserProfileUnsavedChangesTitle": "تحذير - التغييرات غير محفوظة", diff --git a/src/Ryujinx/Assets/Locales/de_DE.json b/src/Ryujinx/Assets/Locales/de_DE.json index c6f9768c6d..e1759e655a 100644 --- a/src/Ryujinx/Assets/Locales/de_DE.json +++ b/src/Ryujinx/Assets/Locales/de_DE.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "Firmware installieren", "MenuBarFileToolsInstallFirmwareFromFile": "Firmware von einer XCI- oder einer ZIP-Datei installieren", "MenuBarFileToolsInstallFirmwareFromDirectory": "Firmware aus einem Verzeichnis installieren", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "Dateitypen verwalten", "MenuBarToolsInstallFileTypes": "Dateitypen installieren", "MenuBarToolsUninstallFileTypes": "Dateitypen deinstallieren", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nMöchtest du fortfahren?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Firmware wird installiert...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Systemversion {0} wurde erfolgreich installiert.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "Es können keine anderen Profile geöffnet werden, wenn das ausgewählte Profil gelöscht wird.", "DialogUserProfileDeletionConfirmMessage": "Möchtest du das ausgewählte Profil löschen?", "DialogUserProfileUnsavedChangesTitle": "Warnung - Nicht gespeicherte Änderungen", diff --git a/src/Ryujinx/Assets/Locales/el_GR.json b/src/Ryujinx/Assets/Locales/el_GR.json index 76049fc3fc..c98f19cf6b 100644 --- a/src/Ryujinx/Assets/Locales/el_GR.json +++ b/src/Ryujinx/Assets/Locales/el_GR.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "Εγκατάσταση Firmware", "MenuBarFileToolsInstallFirmwareFromFile": "Εγκατάσταση Firmware από XCI ή ZIP", "MenuBarFileToolsInstallFirmwareFromDirectory": "Εγκατάσταση Firmware από τοποθεσία", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "Διαχείριση τύπων αρχείων", "MenuBarToolsInstallFileTypes": "Εγκαταστήσετε τύπους αρχείων.", "MenuBarToolsUninstallFileTypes": "Απεγκαταστήσετε τύπους αρχείων", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nΘέλετε να συνεχίσετε;", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Εγκατάσταση Firmware...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Η έκδοση συστήματος {0} εγκαταστάθηκε με επιτυχία.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "Δεν θα υπάρχουν άλλα προφίλ εάν διαγραφεί το επιλεγμένο", "DialogUserProfileDeletionConfirmMessage": "Θέλετε να διαγράψετε το επιλεγμένο προφίλ", "DialogUserProfileUnsavedChangesTitle": "Προσοχή - Μην Αποθηκευμένες Αλλαγές.", diff --git a/src/Ryujinx/Assets/Locales/es_ES.json b/src/Ryujinx/Assets/Locales/es_ES.json index cf5c586d0b..ae3ae20398 100644 --- a/src/Ryujinx/Assets/Locales/es_ES.json +++ b/src/Ryujinx/Assets/Locales/es_ES.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "Instalar firmware", "MenuBarFileToolsInstallFirmwareFromFile": "Instalar firmware desde un archivo XCI o ZIP", "MenuBarFileToolsInstallFirmwareFromDirectory": "Instalar firmware desde una carpeta", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "Administrar tipos de archivo", "MenuBarToolsInstallFileTypes": "Instalar tipos de archivo", "MenuBarToolsUninstallFileTypes": "Desinstalar tipos de archivo", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n¿Continuar?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalando firmware...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Versión de sistema {0} instalada con éxito.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "Si eliminas el perfil seleccionado no quedará ningún otro perfil", "DialogUserProfileDeletionConfirmMessage": "¿Quieres eliminar el perfil seleccionado?", "DialogUserProfileUnsavedChangesTitle": "Advertencia - Cambios sin guardar", diff --git a/src/Ryujinx/Assets/Locales/fr_FR.json b/src/Ryujinx/Assets/Locales/fr_FR.json index 0073a2cf50..9188e91928 100644 --- a/src/Ryujinx/Assets/Locales/fr_FR.json +++ b/src/Ryujinx/Assets/Locales/fr_FR.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "Installer un firmware", "MenuBarFileToolsInstallFirmwareFromFile": "Installer un firmware depuis un fichier XCI ou ZIP", "MenuBarFileToolsInstallFirmwareFromDirectory": "Installer un firmware depuis un dossier", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "Gérer les types de fichiers", "MenuBarToolsInstallFileTypes": "Installer les types de fichiers", "MenuBarToolsUninstallFileTypes": "Désinstaller les types de fichiers", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nVoulez-vous continuer ?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installation du firmware...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Version du système {0} installée avec succès.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "Il n'y aurait aucun autre profil à ouvrir si le profil sélectionné est supprimé", "DialogUserProfileDeletionConfirmMessage": "Voulez-vous supprimer le profil sélectionné ?", "DialogUserProfileUnsavedChangesTitle": "Avertissement - Modifications non enregistrées", diff --git a/src/Ryujinx/Assets/Locales/he_IL.json b/src/Ryujinx/Assets/Locales/he_IL.json index 91e3e24e41..cd59b5cc9b 100644 --- a/src/Ryujinx/Assets/Locales/he_IL.json +++ b/src/Ryujinx/Assets/Locales/he_IL.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "התקן קושחה", "MenuBarFileToolsInstallFirmwareFromFile": "התקן קושחה מקובץ- ZIP/XCI", "MenuBarFileToolsInstallFirmwareFromDirectory": "התקן קושחה מתוך תקייה", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "ניהול סוגי קבצים", "MenuBarToolsInstallFileTypes": "סוגי קבצי התקנה", "MenuBarToolsUninstallFileTypes": "סוגי קבצי הסרה", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nהאם ברצונך להמשיך?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "מתקין קושחה...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "גרסת המערכת {0} הותקנה בהצלחה.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "לא יהיו פרופילים אחרים שייפתחו אם הפרופיל שנבחר יימחק", "DialogUserProfileDeletionConfirmMessage": "האם ברצונך למחוק את הפרופיל שנבחר", "DialogUserProfileUnsavedChangesTitle": "אזהרה - שינויים לא שמורים", diff --git a/src/Ryujinx/Assets/Locales/it_IT.json b/src/Ryujinx/Assets/Locales/it_IT.json index 2a92e70dc7..acbed6e0c5 100644 --- a/src/Ryujinx/Assets/Locales/it_IT.json +++ b/src/Ryujinx/Assets/Locales/it_IT.json @@ -27,6 +27,9 @@ "MenuBarToolsInstallFirmware": "Installa firmware", "MenuBarFileToolsInstallFirmwareFromFile": "Installa un firmware da file XCI o ZIP", "MenuBarFileToolsInstallFirmwareFromDirectory": "Installa un firmare da una cartella", + "MenuBarToolsInstallKeys": "Installa Chiavi", + "MenuBarFileToolsInstallKeysFromFile": "Installa Chiavi da file KEYS o ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Installa Chiavi da una Cartella", "MenuBarToolsManageFileTypes": "Gestisci i tipi di file", "MenuBarToolsInstallFileTypes": "Installa i tipi di file", "MenuBarToolsUninstallFileTypes": "Disinstalla i tipi di file", @@ -504,6 +507,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nVuoi continuare?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installazione del firmware...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "La versione del sistema {0} è stata installata.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "E' stato trovato un file di chiavi invalido ' {0}", + "DialogKeysInstallerKeysInstallTitle": "Installa Chavi", + "DialogKeysInstallerKeysInstallMessage": "Un nuovo file di Chiavi sarà intallato.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nQuesto potrebbe sovrascrivere alcune delle Chiavi già installate.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nVuoi continuare?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installando le chiavi...", + "DialogKeysInstallerKeysInstallSuccessMessage": "Nuovo file di chiavi installato con successo.", "DialogUserProfileDeletionWarningMessage": "Non ci sarebbero altri profili da aprire se il profilo selezionato viene cancellato", "DialogUserProfileDeletionConfirmMessage": "Vuoi eliminare il profilo selezionato?", "DialogUserProfileUnsavedChangesTitle": "Attenzione - Modifiche Non Salvate", diff --git a/src/Ryujinx/Assets/Locales/ja_JP.json b/src/Ryujinx/Assets/Locales/ja_JP.json index b8e5870a64..9384c28b3a 100644 --- a/src/Ryujinx/Assets/Locales/ja_JP.json +++ b/src/Ryujinx/Assets/Locales/ja_JP.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "ファームウェアをインストール", "MenuBarFileToolsInstallFirmwareFromFile": "XCI または ZIP からファームウェアをインストール", "MenuBarFileToolsInstallFirmwareFromDirectory": "ディレクトリからファームウェアをインストール", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "ファイル形式を管理", "MenuBarToolsInstallFileTypes": "ファイル形式をインストール", "MenuBarToolsUninstallFileTypes": "ファイル形式をアンインストール", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n続けてよろしいですか?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "ファームウェアをインストール中...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "システムバージョン {0} が正常にインストールされました.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "選択されたプロファイルを削除すると,プロファイルがひとつも存在しなくなります", "DialogUserProfileDeletionConfirmMessage": "選択されたプロファイルを削除しますか", "DialogUserProfileUnsavedChangesTitle": "警告 - 保存されていない変更", diff --git a/src/Ryujinx/Assets/Locales/ko_KR.json b/src/Ryujinx/Assets/Locales/ko_KR.json index 5bda1565b0..d232092dbb 100644 --- a/src/Ryujinx/Assets/Locales/ko_KR.json +++ b/src/Ryujinx/Assets/Locales/ko_KR.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "펌웨어 설치", "MenuBarFileToolsInstallFirmwareFromFile": "XCI 또는 ZIP으로 펌웨어 설치", "MenuBarFileToolsInstallFirmwareFromDirectory": "디렉터리에서 펌웨어 설치", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "파일 형식 관리", "MenuBarToolsInstallFileTypes": "파일 형식 설치", "MenuBarToolsUninstallFileTypes": "파일 형식 제거", @@ -504,6 +507,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n계속하시겠습니까?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "펌웨어 설치 중...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "시스템 버전 {0}이(가) 설치되었습니다.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "선택한 프로필을 삭제하면 다른 프로필을 열 수 없음", "DialogUserProfileDeletionConfirmMessage": "선택한 프로필을 삭제하시겠습니까?", "DialogUserProfileUnsavedChangesTitle": "경고 - 저장되지 않은 변경 사항", diff --git a/src/Ryujinx/Assets/Locales/pl_PL.json b/src/Ryujinx/Assets/Locales/pl_PL.json index fa88bab5e3..e45c445b46 100644 --- a/src/Ryujinx/Assets/Locales/pl_PL.json +++ b/src/Ryujinx/Assets/Locales/pl_PL.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "Zainstaluj oprogramowanie", "MenuBarFileToolsInstallFirmwareFromFile": "Zainstaluj oprogramowanie z XCI lub ZIP", "MenuBarFileToolsInstallFirmwareFromDirectory": "Zainstaluj oprogramowanie z katalogu", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "Zarządzaj rodzajami plików", "MenuBarToolsInstallFileTypes": "Typy plików instalacyjnych", "MenuBarToolsUninstallFileTypes": "Typy plików dezinstalacyjnych", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nCzy chcesz kontynuować?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalowanie firmware'u...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Wersja systemu {0} została pomyślnie zainstalowana.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "Nie będzie innych profili do otwarcia, jeśli wybrany profil zostanie usunięty", "DialogUserProfileDeletionConfirmMessage": "Czy chcesz usunąć wybrany profil", "DialogUserProfileUnsavedChangesTitle": "Uwaga - Niezapisane zmiany", diff --git a/src/Ryujinx/Assets/Locales/pt_BR.json b/src/Ryujinx/Assets/Locales/pt_BR.json index 5b7a214945..044b5ebc0b 100644 --- a/src/Ryujinx/Assets/Locales/pt_BR.json +++ b/src/Ryujinx/Assets/Locales/pt_BR.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "_Instalar firmware", "MenuBarFileToolsInstallFirmwareFromFile": "Instalar firmware a partir de um arquivo ZIP/XCI", "MenuBarFileToolsInstallFirmwareFromDirectory": "Instalar firmware a partir de um diretório", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "Gerenciar tipos de arquivo", "MenuBarToolsInstallFileTypes": "Instalar tipos de arquivo", "MenuBarToolsUninstallFileTypes": "Desinstalar tipos de arquivos", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDeseja continuar?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalando firmware...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Versão do sistema {0} instalada com sucesso.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "Não haveria nenhum perfil selecionado se o perfil atual fosse deletado", "DialogUserProfileDeletionConfirmMessage": "Deseja deletar o perfil selecionado", "DialogUserProfileUnsavedChangesTitle": "Alerta - Alterações não salvas", diff --git a/src/Ryujinx/Assets/Locales/ru_RU.json b/src/Ryujinx/Assets/Locales/ru_RU.json index cd17eb3015..ce94b9385a 100644 --- a/src/Ryujinx/Assets/Locales/ru_RU.json +++ b/src/Ryujinx/Assets/Locales/ru_RU.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "Установка прошивки", "MenuBarFileToolsInstallFirmwareFromFile": "Установить прошивку из XCI или ZIP", "MenuBarFileToolsInstallFirmwareFromDirectory": "Установить прошивку из папки", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "Управление типами файлов", "MenuBarToolsInstallFileTypes": "Установить типы файлов", "MenuBarToolsUninstallFileTypes": "Удалить типы файлов", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nПродолжить?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Установка прошивки...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Прошивка версии {0} успешно установлена.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "Если выбранный профиль будет удален, другие профили не будут открываться.", "DialogUserProfileDeletionConfirmMessage": "Удалить выбранный профиль?", "DialogUserProfileUnsavedChangesTitle": "Внимание - Несохраненные изменения", diff --git a/src/Ryujinx/Assets/Locales/th_TH.json b/src/Ryujinx/Assets/Locales/th_TH.json index d32cfb737b..6556f599d9 100644 --- a/src/Ryujinx/Assets/Locales/th_TH.json +++ b/src/Ryujinx/Assets/Locales/th_TH.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "ติดตั้งเฟิร์มแวร์", "MenuBarFileToolsInstallFirmwareFromFile": "ติดตั้งเฟิร์มแวร์จาก ไฟล์ XCI หรือ ไฟล์ ZIP", "MenuBarFileToolsInstallFirmwareFromDirectory": "ติดตั้งเฟิร์มแวร์จากไดเร็กทอรี", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "จัดการประเภทไฟล์", "MenuBarToolsInstallFileTypes": "ติดตั้งประเภทไฟล์", "MenuBarToolsUninstallFileTypes": "ถอนการติดตั้งประเภทไฟล์", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nคุณต้องการดำเนินการต่อหรือไม่?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "กำลังติดตั้งเฟิร์มแวร์...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "ระบบเวอร์ชั่น {0} ติดตั้งเรียบร้อยแล้ว", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "จะไม่มีโปรไฟล์อื่นให้เปิดหากโปรไฟล์ที่เลือกถูกลบ", "DialogUserProfileDeletionConfirmMessage": "คุณต้องการลบโปรไฟล์ที่เลือกหรือไม่?", "DialogUserProfileUnsavedChangesTitle": "คำเตือน - มีการเปลี่ยนแปลงที่ไม่ได้บันทึก", diff --git a/src/Ryujinx/Assets/Locales/tr_TR.json b/src/Ryujinx/Assets/Locales/tr_TR.json index 1ac9a0b6ed..cc76f136b9 100644 --- a/src/Ryujinx/Assets/Locales/tr_TR.json +++ b/src/Ryujinx/Assets/Locales/tr_TR.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "Yazılım Yükle", "MenuBarFileToolsInstallFirmwareFromFile": "XCI veya ZIP'ten Yazılım Yükle", "MenuBarFileToolsInstallFirmwareFromDirectory": "Bir Dizin Üzerinden Yazılım Yükle", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "Dosya uzantılarını yönet", "MenuBarToolsInstallFileTypes": "Dosya uzantılarını yükle", "MenuBarToolsUninstallFileTypes": "Dosya uzantılarını kaldır", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDevam etmek istiyor musunuz?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Firmware yükleniyor...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Sistem sürümü {0} başarıyla yüklendi.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "Seçilen profil silinirse kullanılabilen başka profil kalmayacak", "DialogUserProfileDeletionConfirmMessage": "Seçilen profili silmek istiyor musunuz", "DialogUserProfileUnsavedChangesTitle": "Uyarı - Kaydedilmemiş Değişiklikler", diff --git a/src/Ryujinx/Assets/Locales/uk_UA.json b/src/Ryujinx/Assets/Locales/uk_UA.json index 0e22263b6f..67cf9b2152 100644 --- a/src/Ryujinx/Assets/Locales/uk_UA.json +++ b/src/Ryujinx/Assets/Locales/uk_UA.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "Установити прошивку", "MenuBarFileToolsInstallFirmwareFromFile": "Установити прошивку з XCI або ZIP", "MenuBarFileToolsInstallFirmwareFromDirectory": "Установити прошивку з теки", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "Керувати типами файлів", "MenuBarToolsInstallFileTypes": "Установити типи файлів", "MenuBarToolsUninstallFileTypes": "Видалити типи файлів", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nВи хочете продовжити?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "Встановлення прошивки...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Версію системи {0} успішно встановлено.", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "Якщо вибраний профіль буде видалено, інші профілі не відкриватимуться", "DialogUserProfileDeletionConfirmMessage": "Ви хочете видалити вибраний профіль", "DialogUserProfileUnsavedChangesTitle": "Увага — Незбережені зміни", diff --git a/src/Ryujinx/Assets/Locales/zh_CN.json b/src/Ryujinx/Assets/Locales/zh_CN.json index 004d5007ba..ac6e66da54 100644 --- a/src/Ryujinx/Assets/Locales/zh_CN.json +++ b/src/Ryujinx/Assets/Locales/zh_CN.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "安装系统固件", "MenuBarFileToolsInstallFirmwareFromFile": "从 XCI 或 ZIP 文件中安装系统固件", "MenuBarFileToolsInstallFirmwareFromDirectory": "从文件夹中安装系统固件", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "管理文件扩展名", "MenuBarToolsInstallFileTypes": "关联文件扩展名", "MenuBarToolsUninstallFileTypes": "取消关联扩展名", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n是否继续?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "安装系统固件中...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "成功安装系统固件版本 {0} 。", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "删除后将没有可用的账户", "DialogUserProfileDeletionConfirmMessage": "是否删除所选账户", "DialogUserProfileUnsavedChangesTitle": "警告 - 有未保存的更改", diff --git a/src/Ryujinx/Assets/Locales/zh_TW.json b/src/Ryujinx/Assets/Locales/zh_TW.json index 9bfc243aef..e48e17bd97 100644 --- a/src/Ryujinx/Assets/Locales/zh_TW.json +++ b/src/Ryujinx/Assets/Locales/zh_TW.json @@ -30,6 +30,9 @@ "MenuBarToolsInstallFirmware": "安裝韌體", "MenuBarFileToolsInstallFirmwareFromFile": "從 XCI 或 ZIP 安裝韌體", "MenuBarFileToolsInstallFirmwareFromDirectory": "從資料夾安裝韌體", + "MenuBarToolsInstallKeys": "Install Keys", + "MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP", + "MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory", "MenuBarToolsManageFileTypes": "管理檔案類型", "MenuBarToolsInstallFileTypes": "安裝檔案類型", "MenuBarToolsUninstallFileTypes": "移除檔案類型", @@ -497,6 +500,13 @@ "DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n您確定要繼續嗎?", "DialogFirmwareInstallerFirmwareInstallWaitMessage": "正在安裝韌體...", "DialogFirmwareInstallerFirmwareInstallSuccessMessage": "成功安裝系統版本 {0}。", + "DialogKeysInstallerKeysNotFoundErrorMessage": "An invalid Keys file was found in {0}", + "DialogKeysInstallerKeysInstallTitle": "Install Keys", + "DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.", + "DialogKeysInstallerKeysInstallSubMessage": "\n\nThis may replace some of the current installed Keys.", + "DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?", + "DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...", + "DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.", "DialogUserProfileDeletionWarningMessage": "如果刪除選取的設定檔,將無法開啟其他設定檔", "DialogUserProfileDeletionConfirmMessage": "您是否要刪除所選設定檔", "DialogUserProfileUnsavedChangesTitle": "警告 - 未儲存的變更", From 037c0b434f5ab7445300c126d0bf94947e6314e8 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Fri, 22 Nov 2024 10:59:35 +0100 Subject: [PATCH 4/6] Added dev.keys to the list of files supported --- src/Ryujinx.HLE/FileSystem/ContentManager.cs | 2 +- src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Ryujinx.HLE/FileSystem/ContentManager.cs b/src/Ryujinx.HLE/FileSystem/ContentManager.cs index 38386bc995..b4e1216640 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentManager.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentManager.cs @@ -1044,7 +1044,7 @@ public void VerifyKeysFile(string filePath) public bool AreKeysAlredyPresent(string pathToCheck) { - string[] fileNames = { "prod.keys", "title.keys", "console.keys" }; + string[] fileNames = { "prod.keys", "title.keys", "console.keys", "dev.keys" }; foreach (var file in fileNames) { if (File.Exists(Path.Combine(pathToCheck, file))) diff --git a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs index 39c544eac1..ef9c493a84 100644 --- a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs +++ b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs @@ -223,9 +223,10 @@ public void ReloadKeySet() { KeySet ??= KeySet.CreateDefaultKeySet(); - string keyFile = null; + string prodKeyFile = null; string titleKeyFile = null; string consoleKeyFile = null; + string devKeyFile = null; if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile) { @@ -236,13 +237,14 @@ public void ReloadKeySet() void LoadSetAtPath(string basePath) { - string localKeyFile = Path.Combine(basePath, "prod.keys"); + string localProdKeyFile = Path.Combine(basePath, "prod.keys"); string localTitleKeyFile = Path.Combine(basePath, "title.keys"); string localConsoleKeyFile = Path.Combine(basePath, "console.keys"); + string localDevKeyFile = Path.Combine(basePath, "dev.keys"); - if (File.Exists(localKeyFile)) + if (File.Exists(localProdKeyFile)) { - keyFile = localKeyFile; + prodKeyFile = localProdKeyFile; } if (File.Exists(localTitleKeyFile)) @@ -254,9 +256,14 @@ void LoadSetAtPath(string basePath) { consoleKeyFile = localConsoleKeyFile; } + + if (File.Exists(localDevKeyFile)) + { + devKeyFile = localDevKeyFile; + } } - ExternalKeyReader.ReadKeyFile(KeySet, keyFile, titleKeyFile, consoleKeyFile, null); + ExternalKeyReader.ReadKeyFile(KeySet, prodKeyFile, devKeyFile, titleKeyFile, consoleKeyFile, null); } public void ImportTickets(IFileSystem fs) From dc28bdbfa4681e3c11a856291f452a1f0572988e Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:00:03 +0100 Subject: [PATCH 5/6] Improved controls on keys files --- src/Ryujinx.HLE/FileSystem/ContentManager.cs | 47 +++++++++++++++----- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/Ryujinx.HLE/FileSystem/ContentManager.cs b/src/Ryujinx.HLE/FileSystem/ContentManager.cs index b4e1216640..51f6058fc3 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentManager.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentManager.cs @@ -1019,27 +1019,54 @@ public SystemVersion GetCurrentFirmwareVersion() public void VerifyKeysFile(string filePath) { - string schemaPattern = @"^[a-zA-Z0-9_]+ = [a-zA-Z0-9]+$"; + // Verify the keys file format refers to https://github.com/Thealexbarney/LibHac/blob/master/KEYS.md + string genericPattern = @"^[a-z0-9_]+ = [a-z0-9]+$"; + string titlePattern = @"^[a-z0-9]{32} = [a-z0-9]{32}$"; if (File.Exists(filePath)) { // Read all lines from the file + string fileName = Path.GetFileName(filePath); string[] lines = File.ReadAllLines(filePath); - for (int i = 0; i < lines.Length; i++) + bool verified = false; + switch (fileName) { - string line = lines[i].Trim(); - - // Check if the line matches the schema - if (!Regex.IsMatch(line, schemaPattern)) - { - throw new FormatException("Keys file doesn't have a correct schema."); - } + case "prod.keys": + verified = verifyKeys(lines, genericPattern); + break; + case "title.keys": + verified = verifyKeys(lines, titlePattern); + break; + case "console.keys": + verified = verifyKeys(lines, genericPattern); + break; + case "dev.keys": + verified = verifyKeys(lines, genericPattern); + break; + default: + throw new FormatException($"Keys file name \"{fileName}\" not supported. Only \"prod.keys\", \"title.keys\", \"console.keys\", \"dev.keys\" are supported."); + } + if (!verified) + { + throw new FormatException($"Invalid \"{filePath}\" file format."); } } else { - throw new FileNotFoundException("Keys file not found at " + filePath); + throw new FileNotFoundException($"Keys file not found at \"{filePath}\"."); + } + } + + private bool verifyKeys(string[] lines, string regex) + { + foreach (string line in lines) + { + if (!Regex.IsMatch(line, regex)) + { + return false; + } } + return true; } public bool AreKeysAlredyPresent(string pathToCheck) From 2341174ac92d1b34e39bb6b1a46b54915f4d7731 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Mon, 25 Nov 2024 18:08:46 +0100 Subject: [PATCH 6/6] Moved Install Keys menu item on top of Install Firmware menu item --- src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml index 1cc9f22cd4..62dbab8e35 100644 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml @@ -260,14 +260,14 @@ IsEnabled="{Binding IsGameRunning}" /> - - - - + + + +