diff --git a/BuildAndPushLibraries.sh b/BuildAndPushLibraries.sh deleted file mode 100644 index 4bd6cfc55..000000000 --- a/BuildAndPushLibraries.sh +++ /dev/null @@ -1,18 +0,0 @@ -function pub { - dotnet publish -c release -} - -function package { - cd src/$1 - pub - mv bin/Release/$1.1.0.0.nupkg ../../pkgs/$1.1.0.0.nupkg - cd ../../ -} - -rm -rf pkgs -mkdir pkgs - -package ARMeilleure -package Ryujinx.Memory - -dotnet nuget push pkgs/*.nupkg --source RyubingPkgs \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a2b4ccb8..ae6b61ccb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,8 +21,8 @@ Additionally, 1.2.74 & 75 were fixes for uploading Windows build artifacts. 1.2.76 fixes a rare crash on startup. -## [1.2.72]() - 2024-11-03 -PRs [#163](), [#164](), [#139]() +## [1.2.72]() - 2024-11-03 +PRs [#163](), [#164](), [#139]() ### HLE: - Add DebugMouse HID device. - Fixes "Clock Tower Rewind" crashing while loading. @@ -32,7 +32,7 @@ PRs [#163](), [#164]() - 2024-11-01 +## [1.2.69]() - 2024-11-01 ### Infra: - Compile the native libraries into the Ryujinx executable. - Remove `libarmeilleure-jitsupport.dylib` from Windows & Linux releases (dylibs are macOS-only) @@ -42,8 +42,8 @@ PRs [#163](), [#164]() - 2024-11-01 -PRs [#36](), [#135]() +## [1.2.67]() - 2024-11-01 +PRs [#36](), [#135]() ### GUI: - Set UseFloatingWatermark to false when watermark is empty @@ -54,8 +54,8 @@ PRs [#36](), [#135]( Logo now also extracts the square thumbnail you see for the game in the UI. - The "use random UUID hack" checkbox in the Amiibo screen now remembers its last state when you reopen the window in a given session. diff --git a/Directory.Packages.props b/Directory.Packages.props index 5eb7eda3a..78f9acd59 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -19,8 +19,8 @@ - - + + @@ -42,11 +42,11 @@ - - - + + + - + diff --git a/assets/locales.json b/assets/locales.json index 686173031..20ecbf6a0 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -68,76 +68,51 @@ } }, { - "ID": "MenuBarFileOpenApplet", - "Translations": { - "ar_SA": "فتح التطبيق المصغر", - "de_DE": "Öffne Anwendung", - "el_GR": "Άνοιγμα Applet", - "en_US": "Open Applet", - "es_ES": "Abrir applet", - "fr_FR": "Ouvrir une Applet", - "he_IL": "פתח יישומון", - "it_IT": "Apri applet", - "ja_JP": "アプレットを開く", - "ko_KR": "애플릿 열기", - "no_NO": "Åpne Program", - "pl_PL": "Otwórz Aplet", - "pt_BR": "Abrir Applet", - "ru_RU": "Открыть апплет", - "sv_SE": "Öppna applet", - "th_TH": "เปิด Applet", - "tr_TR": "Applet'i Aç", - "uk_UA": "Відкрити аплет", - "zh_CN": "打开小程序", - "zh_TW": "開啟小程式" - } - }, - { - "ID": "MenuBarFileOpenAppletOpenMiiApplet", + "ID": "MenuBarActionsOpenMiiEditor", "Translations": { "ar_SA": "", - "de_DE": "Mii-Bearbeitungsapplet", + "de_DE": "", "el_GR": "", - "en_US": "Mii Edit Applet", - "es_ES": "Applet Editor Mii", + "en_US": "Mii Editor", + "es_ES": "Editor de Mii", "fr_FR": "Éditeur de Mii", "he_IL": "", - "it_IT": "Applet Editor Mii", + "it_IT": "Editor di Mii", "ja_JP": "", - "ko_KR": "애플릿 Mii 편집기", - "no_NO": "Mii-redigeringsapplet", - "pl_PL": "", + "ko_KR": "Mii 편집기", + "no_NO": "Mii-redigerer", + "pl_PL": "Edytor Mii", "pt_BR": "Editor de Mii", "ru_RU": "Редактор Mii", - "sv_SE": "Redigera Mii-applet", - "th_TH": "ตัวแก้ไขตัวละคร Mii", + "sv_SE": "", + "th_TH": "", "tr_TR": "", - "uk_UA": "Аплет редагування Mii", - "zh_CN": "Mii 小程序", - "zh_TW": "Mii 編輯器小程式" + "uk_UA": "Редактор Mii", + "zh_CN": "Mii 编辑器", + "zh_TW": "" } }, { - "ID": "MenuBarFileOpenAppletOpenMiiAppletToolTip", + "ID": "MenuBarActionsOpenMiiEditorToolTip", "Translations": { "ar_SA": "‫افتح تطبيق تحرير Mii في الوضع المستقل", - "de_DE": "Öffnet das Mii-Editor-Applet im Standalone-Modus", - "el_GR": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία", - "en_US": "Open Mii Editor Applet in Standalone mode", + "de_DE": "Öffnet das Mii-Editor im Standalone-Modus", + "el_GR": "Άνοιγμα του Mii Editor σε Αυτόνομη λειτουργία", + "en_US": "Opens Mii Editor in Standalone mode", "es_ES": "Abre el editor de Mii en modo autónomo", - "fr_FR": "Ouvrir l’Applet Éditeur Mii en mode Autonome", + "fr_FR": "Ouvrir L'Éditeur de Mii en mode autonome", "he_IL": "פתח את יישומון עורך ה- Mii במצב עצמאי", - "it_IT": "Apri l'applet Editor Mii in modalità Standalone", + "it_IT": "Apri l'Editor di Mii in modalità Standalone", "ja_JP": "スタンドアロンモードで Mii エディタアプレットを開きます", "ko_KR": "독립 실행형 모드로 Mii 편집기 애플릿 열기", "no_NO": "Åpne Mii Redigerings program i eget vindu", - "pl_PL": "Otwórz aplet Mii Editor w trybie indywidualnym", + "pl_PL": "Otwórz Edytor Mii w trybie indywidualnym", "pt_BR": "Abrir Editor de Mii em Modo Independente", "ru_RU": "Открывает редактор Mii в автономном режиме", - "sv_SE": "Öppna Mii Editor Applet i fristående läge", - "th_TH": "เปิดโปรแกรม Mii Editor Applet", - "tr_TR": "Mii Editör Applet'ini Bağımsız Mod'da Aç", - "uk_UA": "Відкрити аплет Mii Editor в автономному режимі", + "sv_SE": "Öppna Mii Editor i fristående läge", + "th_TH": "เปิดโปรแกรม Mii Editor", + "tr_TR": "Mii Editör'ini Bağımsız Mod'da Aç", + "uk_UA": "Відкрити редактор Mii в автономному режимі", "zh_CN": "打开独立的 Mii 小程序", "zh_TW": "在獨立模式下開啟 Mii 編輯器小程式" } @@ -320,26 +295,26 @@ { "ID": "MenuBarFileOpenFromFile", "Translations": { - "ar_SA": "_تحميل تطبيق من ملف", - "de_DE": "Datei _öffnen", - "el_GR": "_Φόρτωση Αρχείου Εφαρμογής", - "en_US": "_Load Application from File", - "es_ES": "_Cargar aplicación desde un archivo", - "fr_FR": "_Charger une Application à partir d’un Fichier", - "he_IL": "_טען יישום מקובץ", - "it_IT": "_Carica applicazione da un file", - "ja_JP": "ファイルからアプリケーションをロード(_L)", - "ko_KR": "파일에서 앱 불러오기(_L)", - "no_NO": "_Last inn program fra fil", - "pl_PL": "_Załaduj aplikację z pliku", - "pt_BR": "_Abrir ROM do Jogo", - "ru_RU": "_Добавить приложение из файла", - "sv_SE": "_Läs in applikation från fil", - "th_TH": "โหลดแอปพลิเคชั่นจากไฟล์", - "tr_TR": "_Dosyadan Uygulama Aç", - "uk_UA": "_Завантажити програму з файлу", - "zh_CN": "加载游戏文件(_L)", - "zh_TW": "從檔案載入應用程式(_L)" + "ar_SA": "_تحميل التطبيق...", + "de_DE": "_Anwendung laden...", + "el_GR": "_Φόρτωση εφαρμογής...", + "en_US": "_Load Application...", + "es_ES": "_Cargar aplicación...", + "fr_FR": "_Charger l’Application...", + "he_IL": "_טען יישום...", + "it_IT": "_Carica applicazione...", + "ja_JP": "アプリケーションをロード(_L)...", + "ko_KR": "앱 불러오기(_L)...", + "no_NO": "_Last inn program...", + "pl_PL": "_Załaduj aplikację...", + "pt_BR": "_Carregar aplicativo...", + "ru_RU": "_Загрузить приложение...", + "sv_SE": "_Läs in applikation...", + "th_TH": "_โหลดแอปพลิเคชัน...", + "tr_TR": "_Uygulamayı yükle...", + "uk_UA": "_Завантажити застосунок...", + "zh_CN": "加载应用程序(_L)...", + "zh_TW": "載入應用程式(_L)..." } }, { @@ -370,76 +345,76 @@ { "ID": "MenuBarFileOpenUnpacked", "Translations": { - "ar_SA": "تحميل لُعْبَة غير محزومة", - "de_DE": "_Entpacktes Spiel öffnen", - "el_GR": "Φόρτωση Απακετάριστου _Παιχνιδιού", - "en_US": "Load _Unpacked Game", - "es_ES": "Cargar juego _desempaquetado", - "fr_FR": "Charger un Jeu _Décompressé", - "he_IL": "טען משחק _שאינו ארוז", - "it_IT": "Carica _gioco estratto", - "ja_JP": "展開されたゲームをロード", - "ko_KR": "압축 푼 게임 불러오기(_U)", - "no_NO": "Last inn _Upakket spill", - "pl_PL": "Załaduj _rozpakowaną grę", - "pt_BR": "Abrir Jogo _Extraído", - "ru_RU": "Добавить _распакованную игру", - "sv_SE": "Läs in _uppackat spel", - "th_TH": "โหลดเกมที่แตกไฟล์แล้ว", - "tr_TR": "_Sıkıştırılmamış Oyun Aç", - "uk_UA": "Завантажити _розпаковану гру", - "zh_CN": "加载解包后的游戏(_U)", - "zh_TW": "載入未封裝的遊戲(_U)" + "ar_SA": "تحميل لُعْبَة غير محزومة...", + "de_DE": "_Entpacktes Spiel laden...", + "el_GR": "_Φόρτωση Απακετάριστου Παιχνιδιού...", + "en_US": "Load _Unpacked Game...", + "es_ES": "Cargar juego _desempaquetado...", + "fr_FR": "Charger un Jeu Décompressé...", + "he_IL": "טען משחק _שאינו ארוז...", + "it_IT": "Carica _gioco estratto...", + "ja_JP": "_展開されたゲームをロード...", + "ko_KR": "압축 푼 게임 불러오기(_U)...", + "no_NO": "Last inn _upakket spill...", + "pl_PL": "Załaduj _rozpakowaną grę...", + "pt_BR": "Abrir Jogo _Extraído...", + "ru_RU": "Загрузить _распакованную игру...", + "sv_SE": "Läs in _uppackat spel...", + "th_TH": "โหลดเกมที่แตกไฟล์แล้ว...", + "tr_TR": "_Sıkıştırılmamış Oyun Yükle...", + "uk_UA": "Завантажити _розпаковану гру...", + "zh_CN": "加载解包后的游戏(_U)...", + "zh_TW": "載入未封裝的遊戲(_U)..." } }, { "ID": "MenuBarFileLoadDlcFromFolder", "Translations": { "ar_SA": "", - "de_DE": "DLC aus Ordner laden", + "de_DE": "DLC aus Ordner laden...", "el_GR": "", - "en_US": "Load DLC From Folder", - "es_ES": "Cargar DLC Desde Carpeta", - "fr_FR": "Charger les DLC À Partir d’un Dossier", + "en_US": "Load DLC...", + "es_ES": "Cargar DLC...", + "fr_FR": "Charger les DLC...", "he_IL": "", - "it_IT": "Carica DLC da una cartella", + "it_IT": "Carica DLC...", "ja_JP": "", - "ko_KR": "폴더에서 DLC 불러오기", - "no_NO": "Last inn DLC fra mappe", + "ko_KR": "DLC 폴더에서 불러오기...", + "no_NO": "Last inn DLC...", "pl_PL": "", - "pt_BR": "Carregar DLC da Pasta", - "ru_RU": "Загрузить DLC из папки", - "sv_SE": "Läs in DLC från mapp", - "th_TH": "โหลด DLC จากโฟลเดอร์", + "pt_BR": "Carregar DLC...", + "ru_RU": "Загрузить DLC...", + "sv_SE": "Läs in DLC...", + "th_TH": "โหลด DLC...", "tr_TR": "", - "uk_UA": "Завантажити DLC з теки", - "zh_CN": "从文件夹加载 DLC", - "zh_TW": "從資料夾中載入 DLC" + "uk_UA": "Завантажити DLC...", + "zh_CN": "加载 DLC...", + "zh_TW": "載入 DLC..." } }, { "ID": "MenuBarFileLoadTitleUpdatesFromFolder", "Translations": { "ar_SA": "", - "de_DE": "Titel-Updates aus Ordner laden", + "de_DE": "Titel-Updates aus Ordner laden...", "el_GR": "", - "en_US": "Load Title Updates From Folder", - "es_ES": "Cargar Actualizaciones de Títulos Desde Carpeta", - "fr_FR": "Charger les Mises à Jour du Titre À Partir d’un Dossier", + "en_US": "Load Title Updates...", + "es_ES": "Cargar Actualizaciones de Títulos...", + "fr_FR": "Charger les Mises à Jour du Titre...", "he_IL": "", - "it_IT": "Carica aggiornamenti da una cartella", + "it_IT": "Carica aggiornamenti...", "ja_JP": "", - "ko_KR": "폴더에서 타이틀 업데이트 불러오기", - "no_NO": "Last inn titteloppdateringer fra mappe", + "ko_KR": "타이틀 업데이트 불러오기...", + "no_NO": "Last inn titteloppdateringer...", "pl_PL": "", - "pt_BR": "Carregar Atualizações de Jogo da Pasta", - "ru_RU": "Загрузить обновления из папки", - "sv_SE": "Läs in titeluppdateringar från mapp", - "th_TH": "โหลดไฟล์อัพเดตจากโฟลเดอร์", + "pt_BR": "Carregar Atualizações de Jogo...", + "ru_RU": "Загрузить обновления...", + "sv_SE": "Läs in titeluppdateringar...", + "th_TH": "โหลดไฟล์อัพเดต...", "tr_TR": "", - "uk_UA": "Завантажити оновлення ігор з теки", - "zh_CN": "从文件夹加载游戏更新", - "zh_TW": "從資料夾中載入遊戲更新" + "uk_UA": "Завантажити оновлення...", + "zh_CN": "加载游戏更新...", + "zh_TW": "載入遊戲更新..." } }, { @@ -500,7 +475,7 @@ "el_GR": "Άνοιγμα Φακέλου Καταγραφής", "en_US": "Open Logs Folder", "es_ES": "Abrir carpeta de registros", - "fr_FR": "Ouvrir le dossier des journaux", + "fr_FR": "Ouvrir le Dossier des Journaux", "he_IL": "פתח את תיקיית קבצי הלוג", "it_IT": "Apri cartella dei log", "ja_JP": "ログフォルダを開く", @@ -695,26 +670,26 @@ { "ID": "MenuBarOptionsManageUserProfiles", "Translations": { - "ar_SA": "_إدارة الملفات الشخصية للمستخدم", - "de_DE": "_Benutzerprofile verwalten", - "el_GR": "Διαχείριση Προφίλ _Χρηστών", - "en_US": "_Manage User Profiles", - "es_ES": "_Gestionar perfiles de usuario", - "fr_FR": "_Gérer les Profils d'Utilisateurs", - "he_IL": "_נהל פרופילי משתמש", - "it_IT": "_Gestisci i profili utente", - "ja_JP": "ユーザプロファイルを管理(_M)", - "ko_KR": "사용자 프로필 관리(_M)", - "no_NO": "_Administrere Brukerprofiler", - "pl_PL": "_Zarządzaj profilami użytkowników", - "pt_BR": "_Gerenciar Perfis de Usuário", - "ru_RU": "_Управление профилями", - "sv_SE": "_Hantera användarprofiler", - "th_TH": "_จัดการโปรไฟล์ผู้ใช้งาน", - "tr_TR": "_Kullanıcı Profillerini Yönet", - "uk_UA": "_Керувати профілями користувачів", - "zh_CN": "管理用户账户(_M)", - "zh_TW": "管理使用者設定檔(_M)" + "ar_SA": "_ملفات المستخدمين", + "de_DE": "_Benutzerprofile", + "el_GR": "Προφίλ Χρηστών", + "en_US": "_User Profiles", + "es_ES": "_Perfiles de usuario", + "fr_FR": "Profils d'Utilisateurs", + "he_IL": "_פרופילי משתמש", + "it_IT": "_Profili utent", + "ja_JP": "ユーザプロファイル(_M)", + "ko_KR": "사용자 프로필(_M)", + "no_NO": "_Brukerprofiler", + "pl_PL": "_Profile użytkowników", + "pt_BR": "_Perfis de usuário", + "ru_RU": "_Учётные записи", + "sv_SE": "_Användarprofiler", + "th_TH": "_โปรไฟล์ผู้ใช้งาน", + "tr_TR": "Kullanıcı Profilleri", + "uk_UA": "Профілі користувачів", + "zh_CN": "用户配置文件(_M)", + "zh_TW": "使用者設定檔(_M)" } }, { @@ -845,51 +820,51 @@ { "ID": "MenuBarActionsInstallFirmwareFromFile", "Translations": { - "ar_SA": "تثبيت برنامج ثابت من XCI أو ZIP", - "de_DE": "Firmware von einer XCI- oder einer ZIP-Datei installieren", - "el_GR": "Εγκατάσταση Firmware από XCI ή ZIP", - "en_US": "Install Firmware from XCI or ZIP", - "es_ES": "Instalar firmware desde un archivo XCI o ZIP", - "fr_FR": "Installer un Firmware depuis un fichier XCI ou ZIP", - "he_IL": "התקן קושחה מקובץ- ZIP/XCI", - "it_IT": "Installa un firmware da file XCI o ZIP", - "ja_JP": "XCI または ZIP からファームウェアをインストール", - "ko_KR": "XCI 또는 ZIP으로 펌웨어 설치", - "no_NO": "Installer en fastvare fra XCI eller ZIP", - "pl_PL": "Zainstaluj oprogramowanie z XCI lub ZIP", - "pt_BR": "Instalar firmware a partir de um arquivo ZIP/XCI", - "ru_RU": "Установить прошивку из XCI или ZIP", - "sv_SE": "Installera en firmware från XCI eller ZIP", - "th_TH": "ติดตั้งเฟิร์มแวร์จาก ไฟล์ XCI หรือ ไฟล์ ZIP", - "tr_TR": "XCI veya ZIP'ten Yazılım Yükle", - "uk_UA": "Встановити прошивку з XCI або ZIP", - "zh_CN": "从 XCI 或 ZIP 文件安装系统固件", - "zh_TW": "從 XCI 或 ZIP 安裝韌體" + "ar_SA": "تثبيت البرنامج الثابت (.XCI أو .ZIP)", + "de_DE": "Firmware (.XCI oder .ZIP) installieren", + "el_GR": "Εγκατάσταση Firmware (.XCI ή .ZIP)", + "en_US": "Install Firmware (.XCI or .ZIP)", + "es_ES": "Instalar firmware (.XCI o .ZIP)", + "fr_FR": "Installer le Firmware (.XCI ou .ZIP)", + "he_IL": "התקן קושחה (.XCI או .ZIP)", + "it_IT": "Installa firmware (.XCI o .ZIP)", + "ja_JP": "ファームウェアをインストール(.XCI または .ZIP)", + "ko_KR": "펌웨어 (.XCI 또는 .ZIP) 설치", + "no_NO": "Installer firmware (.XCI eller .ZIP)", + "pl_PL": "Zainstaluj firmware (.XCI lub .ZIP)", + "pt_BR": "Instalar firmware (.XCI ou .ZIP)", + "ru_RU": "Установить прошивку (.XCI или .ZIP)", + "sv_SE": "Installera firmware (.XCI eller .ZIP)", + "th_TH": "ติดตั้งเฟิร์มแวร์ (.XCI หรือ .ZIP)", + "tr_TR": "Yazılım yükle (.XCI veya .ZIP)", + "uk_UA": "Встановити прошивку (.XCI або .ZIP)", + "zh_CN": "安装固件(.XCI 或 .ZIP)", + "zh_TW": "安裝韌體(.XCI 或 .ZIP)" } }, { "ID": "MenuBarActionsInstallFirmwareFromDirectory", "Translations": { - "ar_SA": "تثبيت برنامج ثابت من مجلد", - "de_DE": "Firmware aus einem Verzeichnis installieren", - "el_GR": "Εγκατάσταση Firmware από τοποθεσία", - "en_US": "Install Firmware from a Directory", - "es_ES": "Instalar firmware desde una carpeta", - "fr_FR": "Installer un firmware à partir d’un dossier", - "he_IL": "התקן קושחה מתוך תקייה", - "it_IT": "Installa un firmware da una cartella", - "ja_JP": "ディレクトリからファームウェアをインストール", - "ko_KR": "디렉터리에서 펌웨어 설치", - "no_NO": "Installer en fastvare fra en mappe", - "pl_PL": "Zainstaluj oprogramowanie z katalogu", - "pt_BR": "Instalar firmware a partir de um diretório", - "ru_RU": "Установить прошивку из папки", - "sv_SE": "Installera en firmware från en katalog", - "th_TH": "ติดตั้งเฟิร์มแวร์จากไดเร็กทอรี", - "tr_TR": "Bir Dizin Üzerinden Yazılım Yükle", - "uk_UA": "Встановити прошивку з теки", - "zh_CN": "从文件夹安装系统固件", - "zh_TW": "從資料夾安裝韌體" + "ar_SA": "تثبيت البرنامج الثابت (مجلد)", + "de_DE": "Firmware (Verzeichnis) installieren", + "el_GR": "Εγκατάσταση Firmware (φάκελος)", + "en_US": "Install Firmware (Folder)", + "es_ES": "Instalar firmware (carpeta)", + "fr_FR": "Installer le Firmware (dossier)", + "he_IL": "התקן קושחה (תיקייה)", + "it_IT": "Installa firmware (cartella)", + "ja_JP": "ファームウェアをインストール(フォルダー)", + "ko_KR": "펌웨어 (폴더) 설치", + "no_NO": "Installer firmware (mappe)", + "pl_PL": "Zainstaluj firmware (katalog)", + "pt_BR": "Instalar firmware (diretório)", + "ru_RU": "Установить прошивку (папка)", + "sv_SE": "Installera firmware (katalog)", + "th_TH": "ติดตั้งเฟิร์มแวร์ (โฟลเดอร์)", + "tr_TR": "Yazılım yükle (klasör)", + "uk_UA": "Встановити прошивку (тека)", + "zh_CN": "安装固件(文件夹)", + "zh_TW": "安裝韌體(資料夾)" } }, { @@ -921,50 +896,50 @@ "ID": "MenuBarFileActionsInstallKeysFromFile", "Translations": { "ar_SA": "", - "de_DE": "Schlüssel aus KEYS oder ZIP installieren", + "de_DE": "Schlüssel (.KEYS) installieren", "el_GR": "", - "en_US": "Install Keys from KEYS or ZIP", - "es_ES": "Instalar keys de KEYS o ZIP", - "fr_FR": "Installer des Clés à partir de .KEYS ou .ZIP", + "en_US": "Install Keys (.KEYS)", + "es_ES": "Instalar keys (.KEYS)", + "fr_FR": "Installer des Clés (.KEYS)", "he_IL": "", - "it_IT": "Installa chiavi da file KEYS o ZIP", + "it_IT": "Installa chiavi (.KEYS)", "ja_JP": "", - "ko_KR": "키나 ZIP에서 키 설치", - "no_NO": "Installer nøkler fra KEYS eller ZIP", + "ko_KR": "키 설치 (.KEYS)", + "no_NO": "Installer nøkler (.KEYS)", "pl_PL": "", - "pt_BR": "Instalar chaves de CHAVES ou ZIP", - "ru_RU": "Установить ключи из KEYS или ZIP", - "sv_SE": "Installera nycklar från KEYS eller ZIP", - "th_TH": "ติดตั้งคีย์จากไฟล์ KEYS หรือ ZIP", + "pt_BR": "Instalar chaves (.KEYS)", + "ru_RU": "Установить ключи (.KEYS)", + "sv_SE": "Installera nycklar (.KEYS)", + "th_TH": "ติดตั้งคีย์ (.KEYS)", "tr_TR": "", - "uk_UA": "Встановити ключі з файлу .KEYS або .ZIP", - "zh_CN": "从 .KEYS 文件或 .ZIP 压缩包安装密匙", - "zh_TW": "從 .KEYS 或 .ZIP 安裝金鑰" + "uk_UA": "Встановити ключі (.KEYS)", + "zh_CN": "安装密钥(.KEYS)", + "zh_TW": "安裝金鑰(.KEYS)" } }, { "ID": "MenuBarFileActionsInstallKeysFromFolder", "Translations": { "ar_SA": "", - "de_DE": "Schlüssel aus einem Verzeichnis installieren", + "de_DE": "Schlüssel (Verzeichnis) installieren", "el_GR": "", - "en_US": "Install Keys from a Directory", - "es_ES": "Instalar keys de un directorio", - "fr_FR": "Installer des Clés à partir d'un dossier", + "en_US": "Install Keys (Folder)", + "es_ES": "Instalar keys (directorio)", + "fr_FR": "Installer des Clés (dossier)", "he_IL": "", - "it_IT": "Installa chiavi da una cartella", + "it_IT": "Installa chiavi (cartella)", "ja_JP": "", - "ko_KR": "디렉터리에서 키 설치", - "no_NO": "Installer nøkler fra en mappe", + "ko_KR": "키 (폴더) 설치", + "no_NO": "Installer nøkler (mappe)", "pl_PL": "", - "pt_BR": "Instalar chaves de um diretório", - "ru_RU": "Установить ключи из папки", - "sv_SE": "Installera nycklar från en katalog", - "th_TH": "ติดตั้งคีย์จากไดเรกทอรี", + "pt_BR": "Instalar chaves (diretório)", + "ru_RU": "Установить ключи (папка)", + "sv_SE": "Installera nycklar (katalog)", + "th_TH": "ติดตั้งคีย์ (ไดเรกทอรี)", "tr_TR": "", - "uk_UA": "Встановити ключі з теки", - "zh_CN": "从一个文件夹安装密匙", - "zh_TW": "從資料夾安裝金鑰" + "uk_UA": "Встановити ключі (тека)", + "zh_CN": "安装密匙(文件夹", + "zh_TW": "安裝金鑰(資料夾" } }, { @@ -1067,6 +1042,31 @@ "zh_TW": "修剪 XCI 檔案" } }, + { + "ID": "MenuBarActionsTools", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Tools", + "es_ES": "", + "fr_FR": "Outils", + "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": "MenuBarView", "Translations": { @@ -1270,51 +1270,51 @@ { "ID": "MenuBarHelpFaqAndGuides", "Translations": { - "ar_SA": "", + "ar_SA": "الأسئلة الشائعة & الدلائل", "de_DE": "FAQ & Anleitungen", - "el_GR": "", + "el_GR": "Συχνές Ερωτήσεις & Οδηγοί", "en_US": "FAQ & Guides", - "es_ES": "FAQ y Guías", + "es_ES": "FAQ & Guías", "fr_FR": null, - "he_IL": "", - "it_IT": "Guide e domande frequenti", - "ja_JP": "", - "ko_KR": "자주 묻는 질문(FAQ) 및 안내", - "no_NO": "Vanlige spørsmål og veiledninger", - "pl_PL": "", + "he_IL": "שאלות נפוצות & מדריכים", + "it_IT": "FAQ & Guides", + "ja_JP": "よくある質問 & ガイド", + "ko_KR": "자주 묻는 질문(FAQ) & 안내", + "no_NO": "FAQ & Veiledninger", + "pl_PL": "FAQ & Przewodniki", "pt_BR": "FAQ & Guias", - "ru_RU": "FAQ и Руководства", - "sv_SE": "Frågor, svar och guider", + "ru_RU": "FAQ & Руководства", + "sv_SE": "FAQ & Guider", "th_TH": "คำถามที่พบบ่อย & คู่มือ", - "tr_TR": "", - "uk_UA": "FAQ та посібники", - "zh_CN": "问答与指南", - "zh_TW": "常見問題 (FAQ) 和指南" + "tr_TR": "SSS & Rehberler", + "uk_UA": "FAQ & посібники", + "zh_CN": "常见问题与指南", + "zh_TW": "常見問題 (FAQ) & 指南" } }, { "ID": "MenuBarHelpFaq", "Translations": { "ar_SA": "", - "de_DE": "FAQ & Fehlerbehebung Seite", + "de_DE": "FAQ & Fehlerbehebung", "el_GR": "", - "en_US": "FAQ & Troubleshooting Page", - "es_ES": "FAQ y resolución de problemas", - "fr_FR": "FAQ et Dépannage", + "en_US": "FAQ & Troubleshooting", + "es_ES": "FAQ & Resolución de problemas", + "fr_FR": "FAQ & Dépannage", "he_IL": "", - "it_IT": "Domande frequenti e risoluzione dei problemi", + "it_IT": "FAQ & Risoluzione dei problemi", "ja_JP": "", - "ko_KR": "자주 묻는 질문(FAQ) 및 문제해결 페이지", - "no_NO": "FAQ- og feilsøkingsside", + "ko_KR": "자주 묻는 질문 및 문제 해결", + "no_NO": "FAQ & Feilsøkinge", "pl_PL": "", - "pt_BR": "FAQ e Solução de Problemas", + "pt_BR": "FAQ & Solução de Problemas", "ru_RU": "FAQ & Устранение неполадок", - "sv_SE": "Frågor, svar och felsökningssida", - "th_TH": "หน้าคำถามที่พบบ่อยและแก้ไขปัญหา", + "sv_SE": "FAQ & Felsökning", + "th_TH": "", "tr_TR": "", - "uk_UA": "FAQ та усунення несправностей (eng)", - "zh_CN": "常见问题和问题排除页面", - "zh_TW": "常見問題 (FAQ) 和疑難排解頁面" + "uk_UA": "FAQ & Усунення несправностей", + "zh_CN": "常见问题与疑难解答", + "zh_TW": "" } }, { @@ -1445,26 +1445,26 @@ { "ID": "MenuBarHelpAbout", "Translations": { - "ar_SA": "حول", + "ar_SA": "حول Ryujinx", "de_DE": "Über Ryujinx", - "el_GR": "Σχετικά με", - "en_US": "About", - "es_ES": "Acerca de", - "fr_FR": "À Propos", - "he_IL": "אודות", - "it_IT": "Informazioni", + "el_GR": "Σχετικά με το Ryujinx", + "en_US": "About Ryujinx", + "es_ES": "Acerca de Ryujinx", + "fr_FR": "À Propos de Ryujinx", + "he_IL": "אודות Ryujinx", + "it_IT": "Informazioni su Ryujinx", "ja_JP": "Ryujinx について", - "ko_KR": "정보", - "no_NO": "Om", - "pl_PL": "O programie", - "pt_BR": "Sobre", - "ru_RU": "О программе", - "sv_SE": "Om", - "th_TH": "เกี่ยวกับ", - "tr_TR": "Hakkında", - "uk_UA": "Про застосунок", - "zh_CN": "关于", - "zh_TW": "關於" + "ko_KR": "Ryujinx 정보", + "no_NO": "Om Ryujinx", + "pl_PL": "O Ryujinx", + "pt_BR": "Sobre Ryujinx", + "ru_RU": "О Ryujinx", + "sv_SE": "Om Ryujinx", + "th_TH": "เกี่ยวกับ Ryujinx", + "tr_TR": "Ryujinx Hakkında", + "uk_UA": "Про Ryujinx", + "zh_CN": "关于 Ryujinx", + "zh_TW": "關於 Ryujinx" } }, { @@ -2554,7 +2554,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": null, "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -2773,23 +2773,23 @@ "ar_SA": "", "de_DE": "", "el_GR": "", - "en_US": "Show Compatibility Entry", + "en_US": "Compatibility Entry", "es_ES": "", - "fr_FR": "Afficher l’Entrée de Compatibilité", + "fr_FR": "Entrée de Compatibilité", "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "호환성 항목 표시", - "no_NO": "Vis kompatibilitetsoppføring", + "ko_KR": "호환성 항목", + "no_NO": "Kompatibilitetsoppføring", "pl_PL": "", - "pt_BR": "Mostrar Dados de Compatibilidade", + "pt_BR": "Dados de Compatibilidade", "ru_RU": "Запись о совместимости", - "sv_SE": "Visa kompatibilitetspost", - "th_TH": "แสดงรายการความเข้ากันได้", + "sv_SE": "Kompatibilitetspost", + "th_TH": "รายการความเข้ากันได้", "tr_TR": "", "uk_UA": "Iнформація про сумісність", - "zh_CN": "显示兼容性项目", - "zh_TW": "顯示相容性資訊" + "zh_CN": "兼容性项目", + "zh_TW": "相容性資訊" } }, { @@ -2798,7 +2798,7 @@ "ar_SA": "", "de_DE": "", "el_GR": "", - "en_US": "Show the selected game in the Compatibility List you can normally access via the Help menu.", + "en_US": "Shows the selected game in the Compatibility List, normally accessible via the Help menu.", "es_ES": "", "fr_FR": "Affiche le jeu sélectionné dans la liste de compatibilité accessible normalement via le menu Aide.", "he_IL": "", @@ -2873,23 +2873,23 @@ "ar_SA": "", "de_DE": "", "el_GR": "", - "en_US": "Show Game Info", - "es_ES": "Mostrar la información del juego", - "fr_FR": "Afficher les Informations du Jeu", + "en_US": "Game Info", + "es_ES": "Información del juego", + "fr_FR": "Informations sur le Jeu", "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "게임 통계 표시", - "no_NO": "Vis Spill Info", + "ko_KR": "게임 정보", + "no_NO": "Spillinfo", "pl_PL": "", - "pt_BR": "Mostrar Informações do Jogo", - "ru_RU": "Информация об игре", - "sv_SE": "Visa spelinformation", - "th_TH": "แสดงสถิติและรายละเอียดของเกมที่เลือกอยู่ในขณะนี้", + "pt_BR": "Informações do Jogo", + "ru_RU": "Информацию об игре", + "sv_SE": "Spelinformation", + "th_TH": "ข้อมูลเกม", "tr_TR": "", "uk_UA": "Інформація про гру", - "zh_CN": "显示游戏信息", - "zh_TW": "顯示遊戲資訊" + "zh_CN": "游戏信息", + "zh_TW": "遊戲資訊" } }, { @@ -2921,50 +2921,50 @@ "ID": "GameListContextMenuOpenSdModsDirectory", "Translations": { "ar_SA": "فتح مجلد تعديلات‫(mods) أتموسفير", - "de_DE": "Atmosphere-Mod-Verzeichnis öffnen", + "de_DE": "Atmosphère-Mod-Verzeichnis öffnen", "el_GR": "", - "en_US": "Open Atmosphere Mods Directory", - "es_ES": "Abrir Directorio de Mods de Atmosphere", + "en_US": "Open Atmosphère Mods Directory", + "es_ES": "Abrir Directorio de Mods de Atmosphère", "fr_FR": "Ouvrir le Dossier des Mods Atmosphère", - "he_IL": "פתח תיקיית מודים של Atmosphere", - "it_IT": "Apri la cartella delle mod Atmosphere", - "ja_JP": "Atmosphere Mods ディレクトリを開く", - "ko_KR": "Atmosphere 모드 디렉터리 열기", + "he_IL": "פתח תיקיית מודים של Atmosphère", + "it_IT": "Apri la cartella delle mod Atmosphère", + "ja_JP": "Atmosphère Mods ディレクトリを開く", + "ko_KR": "Atmosphère 모드 디렉터리 열기", "no_NO": "Åpne Atmosfære modifikasjons mappen", - "pl_PL": "Otwórz katalog modów Atmosphere", - "pt_BR": "Abrir Diretório de Mods Atmosphere", - "ru_RU": "Открыть папку с модами Atmosphere", - "sv_SE": "Öppna Atmosphere Mods-katalogen", - "th_TH": "เปิดไดเร็กทอรี่ Mods Atmosphere", + "pl_PL": "Otwórz katalog modów Atmosphère", + "pt_BR": "Abrir Diretório de Mods Atmosphère", + "ru_RU": "Открыть папку с модами Atmosphère", + "sv_SE": "Öppna Atmosphère Mods-katalogen", + "th_TH": "เปิดไดเร็กทอรี่ Mods Atmosphère", "tr_TR": "", - "uk_UA": "Відкрити теку модифікацій Atmosphere", + "uk_UA": "Відкрити теку модифікацій Atmosphère", "zh_CN": "打开大气层系统 MOD 目录", - "zh_TW": "開啟 Atmosphere 模組資料夾" + "zh_TW": "開啟 Atmosphère 模組資料夾" } }, { "ID": "GameListContextMenuOpenSdModsDirectoryToolTip", "Translations": { "ar_SA": "يفتح مجلد أتموسفير لبطاقة SD البديلة الذي يحتوي على تعديلات التطبيق. مفيد للتعديلات التي تم تعبئتها للأجهزة الحقيقية.", - "de_DE": "Öffnet das alternative SD-Karten-Atmosphere-Verzeichnis, das die Mods der Anwendung enthält. Dieser Ordner ist nützlich für Mods, die für echte Hardware erstellt worden sind.", + "de_DE": "Öffnet das alternative SD-Karten-Atmosphère-Verzeichnis, das die Mods der Anwendung enthält. Dieser Ordner ist nützlich für Mods, die für echte Hardware erstellt worden sind.", "el_GR": "", - "en_US": "Opens the alternative SD card Atmosphere directory which contains Application's Mods. Useful for mods that are packaged for real hardware.", - "es_ES": "Abre el directorio alternativo de la tarjeta SD de Atmosphere que contiene los Mods de la Aplicación. Útil para los mods que están empaquetados para el hardware real.", - "fr_FR": "Ouvre le dossier Atmosphere d’une carte SD alternative contenant les Mods de l’Application. Utile pour les mods conçus pour fonctionner sur un matériel réel.", - "he_IL": "פותח את תיקיית כרטיס ה-SD החלופית של Atmosphere המכילה את המודים של האפליקציה. שימושי עבור מודים שארוזים עבור חומרה אמיתית.", - "it_IT": "Apre la cartella alternativa di Atmosphere sulla scheda SD che contiene le mod dell'applicazione. Utile per le mod create per funzionare sull'hardware reale.", - "ja_JP": "アプリケーションの Mod データを格納する SD カードの Atmosphere ディレクトリを開きます. 実際のハードウェア用に作成された Mod データに有用です.", - "ko_KR": "해당 게임의 모드가 포함된 대체 SD 카드 Atmosphere 디렉터리를 엽니다. 실제 하드웨어용으로 패키징된 모드에 유용합니다.", + "en_US": "Opens the alternative SD card Atmosphère directory which contains Application's Mods. Useful for mods that are packaged for real hardware.", + "es_ES": "Abre el directorio alternativo de la tarjeta SD de Atmosphère que contiene los Mods de la Aplicación. Útil para los mods que están empaquetados para el hardware real.", + "fr_FR": "Ouvre le dossier Atmosphère d’une carte SD alternative contenant les Mods de l’Application. Utile pour les mods conçus pour fonctionner sur un matériel réel.", + "he_IL": "פותח את תיקיית כרטיס ה-SD החלופית של Atmosphère המכילה את המודים של האפליקציה. שימושי עבור מודים שארוזים עבור חומרה אמיתית.", + "it_IT": "Apre la cartella alternativa di Atmosphère sulla scheda SD che contiene le mod dell'applicazione. Utile per le mod create per funzionare sull'hardware reale.", + "ja_JP": "アプリケーションの Mod データを格納する SD カードの Atmosphère ディレクトリを開きます. 実際のハードウェア用に作成された Mod データに有用です.", + "ko_KR": "해당 게임의 모드가 포함된 대체 SD 카드 Atmosphère 디렉터리를 엽니다. 실제 하드웨어용으로 패키징된 모드에 유용합니다.", "no_NO": "Åpner den alternative SD-kortets Atmosfære-mappe som inneholder programmoduser. Nyttig for modifikasjoner som er pakket for ekte maskinvare.", - "pl_PL": "Otwiera alternatywny katalog Atmosphere na karcie SD, który zawiera mody danej aplikacji. Przydatne dla modów przygotowanych pod prawdziwy sprzęt.", - "pt_BR": "Abre o diretório Atmosphere do cartão SD alternativo que contém os Mods do aplicativo. Útil para mods que são empacotados para hardware real.", - "ru_RU": "Открывает альтернативную папку Atmosphere на SD-карте с модами приложения. Полезно для модов, предназначенных для реальной консоли.", - "sv_SE": "Öppnar den alternativa Atmosphere-katalogen på SD-kort som innehåller applikationens Mods. Användbart för Mods som är paketerade för riktig hårdvara.", - "th_TH": "เปิดโฟลเดอร์ Atmosphere บนการ์ด SD ทางเลือกที่เก็บม็อดของแอปพลิเคชัน ใช้สำหรับม็อดที่จัดเตรียมมาเพื่อฮาร์ดแวร์จริง", + "pl_PL": "Otwiera alternatywny katalog Atmosphère na karcie SD, który zawiera mody danej aplikacji. Przydatne dla modów przygotowanych pod prawdziwy sprzęt.", + "pt_BR": "Abre o diretório Atmosphère do cartão SD alternativo que contém os Mods do aplicativo. Útil para mods que são empacotados para hardware real.", + "ru_RU": "Открывает альтернативную папку Atmosphère на SD-карте с модами приложения. Полезно для модов, предназначенных для реальной консоли.", + "sv_SE": "Öppnar den alternativa Atmosphère-katalogen på SD-kort som innehåller applikationens Mods. Användbart för Mods som är paketerade för riktig hårdvara.", + "th_TH": "เปิดโฟลเดอร์ Atmosphère บนการ์ด SD ทางเลือกที่เก็บม็อดของแอปพลิเคชัน ใช้สำหรับม็อดที่จัดเตรียมมาเพื่อฮาร์ดแวร์จริง", "tr_TR": "", - "uk_UA": "Відкриває альтернативну теку SD-карти Atmosphere, що містить модифікації до застосунків або ігор. Корисно для модифікацій, зроблених для реального обладнання.", + "uk_UA": "Відкриває альтернативну теку SD-карти Atmosphère, що містить модифікації до застосунків або ігор. Корисно для модифікацій, зроблених для реального обладнання.", "zh_CN": "打开存放适用于大气层系统的游戏 MOD 的目录,对于为真实硬件打包的 MOD 非常有用", - "zh_TW": "開啟此應用程式模組的另一個 SD 卡 Atmosphere 資料夾。適用於為真實硬體封裝的模組。" + "zh_TW": "開啟此應用程式模組的另一個 SD 卡 Atmosphère 資料夾。適用於為真實硬體封裝的模組。" } }, { @@ -2973,23 +2973,23 @@ "ar_SA": "", "de_DE": "", "el_GR": "", - "en_US": "Check and Trim XCI File", - "es_ES": "Verificar y recortar archivo XCI", - "fr_FR": "Vérifier et Réduire le Fichier XCI", + "en_US": "Check & Trim XCI File", + "es_ES": "Verificar & recortar archivo XCI", + "fr_FR": "Vérifier & Réduire le Fichier XCI", "he_IL": "", - "it_IT": "Controlla e riduci la dimensione del file XCI", + "it_IT": "Controlla & riduci il file XCI", "ja_JP": "", - "ko_KR": "XCI 파일 확인 및 트림", - "no_NO": "Kontroller og trim XCI-filen", + "ko_KR": "XCI 파일 확인 & 트림", + "no_NO": "Kontroller & trim XCI-filen", "pl_PL": "", - "pt_BR": "Verificar e Reduzir o Arquivo XCI", - "ru_RU": "Проверить и обрезать XCI файл", - "sv_SE": "Kontrollera och optimera XCI-fil", - "th_TH": "ตรวจสอบและลดขนาดไฟล์ XCI", + "pt_BR": "Verificar & Reduzir o Arquivo XCI", + "ru_RU": "Проверить & обрезать XCI файл", + "sv_SE": "Kontrollera & optimera XCI-fil", + "th_TH": "ตรวจสอบ & ลดขนาดไฟล์ XCI", "tr_TR": "", - "uk_UA": "Перевірка та нарізка XCI Файлу", - "zh_CN": "检查并瘦身 XCI 文件", - "zh_TW": "檢查及修剪 XCI 檔案" + "uk_UA": "Перевірка & нарізка XCI Файлу", + "zh_CN": "检查并精简 XCI 文件", + "zh_TW": "檢查 & 修剪 XCI 檔案" } }, { @@ -3029,7 +3029,7 @@ "he_IL": "{1}/{0} משחקים נטענו", "it_IT": "{0}/{1} giochi caricati", "ja_JP": "{0}/{1} ゲーム", - "ko_KR": "{0}/{1}개의 게임 타이틀", + "ko_KR": "{0}/{1} 게임", "no_NO": "{0}/{1} Spill Lastet", "pl_PL": "{0}/{1} Załadowane gry", "pt_BR": "{0}/{1} Jogos Carregados", @@ -3879,7 +3879,7 @@ "he_IL": "תקיות משחקים", "it_IT": "Cartelle dei giochi", "ja_JP": "ゲームディレクトリ", - "ko_KR": "게임 데릭터리", + "ko_KR": "게임 디렉터리", "no_NO": "Spillmapper", "pl_PL": "Katalogi gier", "pt_BR": "Pasta de Jogos", @@ -10629,7 +10629,7 @@ "he_IL": "", "it_IT": "Non assegnato", "ja_JP": "", - "ko_KR": "연동 해제", + "ko_KR": "설정 안함", "no_NO": "Ikke bundet", "pl_PL": "", "pt_BR": "Não Atribuído", @@ -12070,26 +12070,26 @@ { "ID": "GameListContextMenuRunApplication", "Translations": { - "ar_SA": "تشغيل التطبيق", - "de_DE": "Anwendung ausführen", - "el_GR": "Εκτέλεση Εφαρμογής", - "en_US": "Run Application", - "es_ES": "Ejecutar aplicación", - "fr_FR": "Démarrer l'Application", - "he_IL": "הרץ יישום", - "it_IT": "Esegui applicazione", - "ja_JP": "アプリケーションを実行", - "ko_KR": "앱 실행", - "no_NO": "Kjør programmet", - "pl_PL": "Uruchom aplikację ", - "pt_BR": "Executar Aplicativo", + "ar_SA": "ابدأ", + "de_DE": "Starten", + "el_GR": "Έναρξη", + "en_US": "Start", + "es_ES": "Iniciar", + "fr_FR": "Démarrer", + "he_IL": "התחל", + "it_IT": "Avvia", + "ja_JP": "開始", + "ko_KR": "시작", + "no_NO": null, + "pl_PL": null, + "pt_BR": "Iniciar", "ru_RU": "Запуск", - "sv_SE": "Kör applikation", - "th_TH": "เปิดใช้งานแอปพลิเคชัน", - "tr_TR": "Uygulamayı Çalıştır", + "sv_SE": "Starta", + "th_TH": "เริ่ม", + "tr_TR": "Başlat", "uk_UA": "Запустити", - "zh_CN": "启动游戏", - "zh_TW": "執行應用程式" + "zh_CN": "启动", + "zh_TW": "開始" } }, { @@ -15564,7 +15564,7 @@ "tr_TR": "", "uk_UA": "", "zh_CN": "显示与此游戏不兼容的 Amiibo", - "zh_TW": "" + "zh_TW": "顯示與此遊戲不相容的 Amiibo" } }, { @@ -19029,7 +19029,7 @@ "he_IL": "נייד", "it_IT": "Portatile", "ja_JP": "携帯", - "ko_KR": "휴대", + "ko_KR": "핸드헬드", "no_NO": "Håndholdt", "pl_PL": "Przenośny", "pt_BR": "Portátil", @@ -19243,28 +19243,103 @@ } }, { - "ID": "OpenFolderDialogTitle", + "ID": "LoadApplicationFromFileDialogTitle", "Translations": { - "ar_SA": "حدد مجلدا يحتوي على لعبة غير مضغوطة", - "de_DE": "Wähle einen Ordner mit einem entpackten Spiel", - "el_GR": "Επιλέξτε ένα φάκελο με ένα αποσυμπιεσμένο παιχνίδι", - "en_US": "Select a folder with an unpacked game", - "es_ES": "Selecciona una carpeta con un juego desempaquetado", - "fr_FR": "Sélectionnez un dossier avec un jeu décompressé", - "he_IL": "בחר תיקיה עם משחק לא ארוז", - "it_IT": "Seleziona una cartella con un gioco estratto", - "ja_JP": "展開されたゲームフォルダを選択", - "ko_KR": "압축 해제된 게임이 있는 폴더를 선택", - "no_NO": "Velg en mappe med et pakket ut spill", - "pl_PL": "Wybierz folder z rozpakowaną grą", - "pt_BR": "Selecione uma pasta com um jogo descompactado", - "ru_RU": "Выберите папку с распакованной игрой", - "sv_SE": "Välj en mapp med ett uppackat spel", - "th_TH": "เลือกโฟลเดอร์ที่มีเกมที่แตกไฟล์แล้ว", - "tr_TR": "Ayrıştırılmamış oyun içeren bir klasör seçin", - "uk_UA": "Виберіть теку з розпакованою грою", - "zh_CN": "选择包含解包游戏的目录并加载", - "zh_TW": "選取未封裝遊戲的資料夾" + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Choose a Switch compatible FILE to load", + "es_ES": "Elige un ARCHIVO compatible con Switch para cargar", + "fr_FR": "Choisissez un FICHIER compatible avec Switch à charger", + "he_IL": "", + "it_IT": "Scegli un FILE compatibile con Switch da caricare", + "ja_JP": "", + "ko_KR": "불러올 Switch 호환 파일을 선택", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Escolha um ARQUIVO compatível com Switch para carregar", + "ru_RU": "Выберите ФАЙЛ, совместимый с Switch, для загрузки", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Виберіть ФАЙЛ, сумісний із Switch, для завантаження", + "zh_CN": "请选择要加载的 Switch 兼容文件", + "zh_TW": "" + } + }, + { + "ID": "LoadUnpackedGameFromFolderDialogTitle", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Choose an UNPACKED Switch compatible application to load", + "es_ES": "Elige una aplicación DESEMPAQUETADA compatible con Switch para cargar", + "fr_FR": "Choisissez une application DÉCOMPRESSEÉE compatible avec Switch à charger", + "he_IL": "", + "it_IT": "Scegli un’applicazione DECOMPRESSA compatibile con Switch da caricare", + "ja_JP": "", + "ko_KR": "불러올 언팩된 Switch 호환 앱을 선택", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Escolha um aplicativo DESCOMPACTADO compatível com Switch para carregar", + "ru_RU": "Выберите РАСПАКОВАННОЕ, совместимое с Switch, приложение для загрузки", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Виберіть РОЗПАКОВАНИЙ сумісний із Switch додаток для завантаження", + "zh_CN": "请选择要加载的已解包的 Switch 兼容应用程序", + "zh_TW": "" + } + }, + { + "ID": "LoadTitleUpdatesFromFolderDialogTitle", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Choose one or more FOLDERS to bulk load title updates from", + "es_ES": "Elige una o más CARPETAS para cargar actualizaciones de título de forma masiva", + "fr_FR": "Choisissez un ou plusieurs DOSSIERS pour charger en masse des mises à jour du titre", + "he_IL": "", + "it_IT": "Scegli una o più CARTELLE da cui caricare in blocco gli aggiornamenti del titolo", + "ja_JP": "", + "ko_KR": "타이틀 업데이트를 대량으로 불러올 폴더를 하나 이상 선택", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Escolha uma ou mais PASTAS para carregar atualizações de título em massa", + "ru_RU": "Выберите одну или несколько ПАПОК для массовой загрузки обновлений заголовков", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Виберіть одну або кілька ПАПОК для масового завантаження оновлень титулів", + "zh_CN": "请选择一个或多个文件夹来批量加载游戏更新", + "zh_TW": "" + } + }, + { + "ID": "LoadDLCFromFolderDialogTitle", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Choose one or more FOLDERS to bulk load DLC from", + "es_ES": "Elige una o más CARPETAS para cargar DLC de forma masiva", + "fr_FR": "Choisissez un ou plusieurs DOSSIERS pour charger en masse des DLC", + "he_IL": "", + "it_IT": "Scegli una o più CARTELLE da cui caricare DLC in blocco", + "ja_JP": "", + "ko_KR": "DLC를 대량으로 불러올 폴더를 하나 이상 선택", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Escolha uma ou mais PASTAS para carregar DLC em massa", + "ru_RU": "Выберите одну или несколько ПАПОК для массовой загрузки DLC", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Виберіть одну або кілька ПАПОК для масового завантаження DLC", + "zh_CN": "请选择一个或多个文件夹来批量加载 DLC", + "zh_TW": "" } }, { @@ -23598,23 +23673,23 @@ "ar_SA": "", "de_DE": "", "el_GR": "", - "en_US": "Open Compatibility List", - "es_ES": "Abrir lista de compatibilidad", - "fr_FR": "Ouvrir la liste de compatibilité", + "en_US": "Compatibility List", + "es_ES": "Lista de compatibilidad", + "fr_FR": "Liste de Compatibilité", "he_IL": "", - "it_IT": "", + "it_IT": "Lista di compatibilità", "ja_JP": "", - "ko_KR": "호환성 목록 열기", - "no_NO": "Åpne kompatibilitetslisten", - "pl_PL": "", - "pt_BR": "Lista de Compatibilidade", - "ru_RU": "Список совместимости", - "sv_SE": "Öppna kompatibilitetslistan", - "th_TH": "เปิดรายการความเข้ากันได้", + "ko_KR": "호환성 목록", + "no_NO": "Kompatibilitetsliste", + "pl_PL": "Lista kompatybilności", + "pt_BR": "Lista de compatibilidade", + "ru_RU": "Cписок совместимости", + "sv_SE": "Kompatibilitetslista", + "th_TH": "รายการความเข้ากันได้", "tr_TR": "", - "uk_UA": "Відкрити Список Сумісності", - "zh_CN": "打开兼容性列表", - "zh_TW": "開啟相容性列表" + "uk_UA": "Список сумісності", + "zh_CN": "兼容性列表", + "zh_TW": "相容性列表" } }, { @@ -23704,7 +23779,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "상태", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -23714,7 +23789,7 @@ "tr_TR": "", "uk_UA": "", "zh_CN": "状态", - "zh_TW": "" + "zh_TW": "統計" } }, { @@ -24139,7 +24214,7 @@ "tr_TR": "", "uk_UA": "", "zh_CN": "调试", - "zh_TW": "" + "zh_TW": "除錯" } }, { @@ -24164,7 +24239,7 @@ "tr_TR": "", "uk_UA": "", "zh_CN": "调试", - "zh_TW": "" + "zh_TW": "除錯" } }, { @@ -24189,7 +24264,7 @@ "tr_TR": "", "uk_UA": "", "zh_CN": "警告: 仅限开发者使用,会降低性能", - "zh_TW": "" + "zh_TW": "警告:僅供開發者使用,會降低效能" } }, { @@ -24214,7 +24289,7 @@ "tr_TR": "", "uk_UA": "", "zh_CN": "开启 GDB Stub", - "zh_TW": "" + "zh_TW": "啟用 GDB Stub" } }, { @@ -24239,7 +24314,7 @@ "tr_TR": "", "uk_UA": "", "zh_CN": "启用 GDB stub 使得可以调试正在运行的应用程序。仅限开发用途!", - "zh_TW": "" + "zh_TW": "啟用 GDB stub 可利用 gdb 除錯正在執行的應用程式。僅供開發使用!" } }, { @@ -24264,7 +24339,7 @@ "tr_TR": "", "uk_UA": "", "zh_CN": "GDB Stub 端口:", - "zh_TW": "" + "zh_TW": "GDB Stub 通訊埠:" } }, { @@ -24289,7 +24364,7 @@ "tr_TR": "", "uk_UA": "", "zh_CN": "启动时暂停应用程序", - "zh_TW": "" + "zh_TW": "執行時暫停應用程式" } }, { @@ -24314,7 +24389,7 @@ "tr_TR": "", "uk_UA": "", "zh_CN": "在执行首条指令前挂起应用程序,这样就可以从最早的点开始调试。", - "zh_TW": "" + "zh_TW": "在執行首項指令前暫停應用程式,以便從最早的點開始除錯。" } }, { @@ -24333,13 +24408,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Открыть список игр LDN", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "打开 LDN 游戏列表", - "zh_TW": "" + "zh_TW": "開啟 LDN 遊戲瀏覽器" } }, { @@ -24358,13 +24433,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Браузер игр LDN - {0} игр", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "LDN 游戏浏览器 - {0} 个游戏", - "zh_TW": "" + "zh_TW": "LDN 遊戲瀏覽器 - {0} 個遊戲" } }, { @@ -24383,13 +24458,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Поиск среди {0} игр LDN...", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "搜索到 {0} 个 LDN 游戏...", - "zh_TW": "" + "zh_TW": "搜尋 {0} 個 LDN 遊戲" } }, { @@ -24408,13 +24483,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Что такое LDN?", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "什么是 LDN", - "zh_TW": "" + "zh_TW": "LDN 是甚麼? (只有英文)" } }, { @@ -24433,13 +24508,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Обновить доступные игры с сервера по адресу {0}", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "在 {0} 时从服务器刷新可用游戏", - "zh_TW": "" + "zh_TW": "從 {0} 伺服器重新整理有效的遊戲" } }, { @@ -24458,13 +24533,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Количество игроков - Отключить", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "玩家计数 - 关闭", - "zh_TW": "" + "zh_TW": "玩家數量 - 停用" } }, { @@ -24483,13 +24558,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Количество игроков - По Возрастанию", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "玩家计数 - 递增", - "zh_TW": "" + "zh_TW": "玩家數量 - 遞增" } }, { @@ -24508,13 +24583,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Количество игроков - По Убыванию", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "玩家计数 - 递减", - "zh_TW": "" + "zh_TW": "玩家數量 - 遞減" } }, { @@ -24533,13 +24608,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Фильтры", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "筛选", - "zh_TW": "" + "zh_TW": "篩選" } }, { @@ -24558,13 +24633,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Показывать только публичные игры", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "仅显示公开游戏", - "zh_TW": "" + "zh_TW": "只列出公開遊戲" } }, { @@ -24583,13 +24658,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Показывать только доступные для присоединения игры", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "仅显示可加入的游戏", - "zh_TW": "" + "zh_TW": "只列出可加入遊戲" } }, { @@ -24608,13 +24683,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Прокси главного сервера", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "主服务器代理", - "zh_TW": "" + "zh_TW": "主代理伺服器" } }, { @@ -24633,13 +24708,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": null, "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": null, - "zh_TW": "" + "zh_TW": "對等網路 (P2P)" } }, { @@ -24658,13 +24733,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Подключается через сервер RyuLDN (медленнее).", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "通过 RyuLDN 服务器进行连接 (较慢)。", - "zh_TW": "" + "zh_TW": "透過 RyuLDN 伺服器連線 (較慢)。" } }, { @@ -24683,13 +24758,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Подключается через прямое соединение (Peer-to-Peer) через UPnP (быстрее).", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "通过 UPnP 进行点对点连接 (较快)。", - "zh_TW": "" + "zh_TW": "透過 UPnP 和對等網路 (P2P) 連線 (較快)。" } }, { @@ -24708,13 +24783,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Создано: {0}", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "已创建: {0} ", - "zh_TW": "" + "zh_TW": "建立於:{0}" } }, { @@ -24733,13 +24808,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Игроки ({0} из {1}):", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "玩家 ({0} 之 {1}):", - "zh_TW": "" + "zh_TW": "玩家數量 ({1} 之 {0}):" } }, { @@ -24758,13 +24833,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Можно присоединиться", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "可加入", - "zh_TW": "" + "zh_TW": "可加入" } }, { @@ -24783,13 +24858,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "К игре можно присоединиться, если она публичная или если вы знаете пароль", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "如果游戏是公开的或您知道口令则它是可加入的。", - "zh_TW": "" + "zh_TW": "如果遊戲是公開,或是你已知的網路密碼片語 (passphrase),則為可加入。" } }, { @@ -24808,13 +24883,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Нельзя присоединиться", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "不可加入", - "zh_TW": "" + "zh_TW": "不可加入" } }, { @@ -24833,13 +24908,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Игра в данный момент идёт", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "游戏当前正在进行中。", - "zh_TW": "" + "zh_TW": "遊戲已在進行中。" } }, { @@ -24858,13 +24933,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Публичная", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "公开", - "zh_TW": "" + "zh_TW": "公開" } }, { @@ -24883,13 +24958,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Любой может присоединиться к этой игре.", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "任何人都可以加入此游戏。", - "zh_TW": "" + "zh_TW": "任何人都可加入此遊戲。" } }, { @@ -24908,13 +24983,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Частная", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "私密", - "zh_TW": "" + "zh_TW": "私人" } }, { @@ -24933,13 +25008,13 @@ "no_NO": "", "pl_PL": "", "pt_BR": "", - "ru_RU": "", + "ru_RU": "Вы можете присоединиться к этой игре только если в настройках у вас тот же LDN пароль.", "sv_SE": "", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "如果您在设置中有某些 LDN 口令则可加入此游戏。", - "zh_TW": "" + "zh_TW": "你只能加入與 LDN 網路密碼片語 (passphrase) 設定相同的遊戲。" } } ] diff --git a/docs/compatibility.csv b/docs/compatibility.csv index 59b8f361f..21baad773 100644 --- a/docs/compatibility.csv +++ b/docs/compatibility.csv @@ -978,7 +978,7 @@ 0100416004C00000,"DOOM",gpu;slow;nvdec;online-broken,ingame,2024-09-23 15:40:07 010018900DD00000,"DOOM (1993)",nvdec;online-broken,menus,2022-09-06 13:32:19 01008CB01E52E000,"DOOM + DOOM II",opengl;ldn-untested;LAN,playable,2024-09-12 07:06:01 -010029D00E740000,"DOOM 3",crash,menus,2024-08-03 05:25:47 +010029D00E740000,"DOOM 3",crash;slow,menus,2024-08-03 05:25:47 01005D700E742000,"DOOM 64",nvdec;vulkan,playable,2020-10-13 23:47:28 0100D4F00DD02000,"DOOM II (Classic)",nvdec;online,playable,2021-06-03 20:10:01 0100B1A00D8CE000,"DOOM® Eternal",gpu;slow;nvdec;online-broken,ingame,2024-08-28 15:57:17 @@ -1097,7 +1097,7 @@ 0100F9600E746000,"ESP Ra.De. Psi",audio;slow,ingame,2024-03-07 15:05:08 010073000FE18000,"Esports powerful pro yakyuu 2020",gpu;crash;Needs More Attention,ingame,2024-04-29 05:34:14 01004F9012FD8000,"Estranged: The Departure",nvdec;UE4,playable,2022-10-24 10:37:58 -010018f01e0a0000,"Eternights",,playable,2025-07-30 12:10:24 +010018F01E0A0000,"Eternights",,playable,2025-07-30 12:10:24 0100CB900B498000,"Eternum Ex",,playable,2021-01-13 20:28:32 010092501EB2C000,"Europa (Demo)",gpu;crash;UE4,ingame,2024-04-23 10:47:12 01007BE0160D6000,"EVE ghost enemies",gpu,ingame,2023-01-14 03:13:30 @@ -1243,7 +1243,7 @@ 010003F00BD48000,"Friday the 13th: Killer Puzzle",,playable,2021-01-28 01:33:38 010092A00C4B6000,"Friday the 13th: The Game Ultimate Slasher Edition",nvdec;online-broken;UE4,playable,2022-09-06 17:33:27 0100F200178F4000,"FRONT MISSION 1st: Remake",,playable,2023-06-09 07:44:24 -0100c4e018a24000,"FRONT MISSION 2: Remake",,playable,2025-07-30 12:11:23 +0100C4E018A24000,"FRONT MISSION 2: Remake",,playable,2025-07-30 12:11:23 01007E6019872000,"FRONT MISSION 3: Remake",,playable,2025-07-30 12:12:02 0100861012474000,"Frontline Zed",,playable,2020-10-03 12:55:59 0100B5300B49A000,"Frost",,playable,2022-07-27 12:00:36 @@ -1450,6 +1450,7 @@ 0100F7300ED2C000,"Hoggy2",,playable,2022-10-10 13:53:35 0100F7E00C70E000,"Hogwarts Legacy",UE4;slow,ingame,2024-09-03 19:53:58 0100633007D48000,"Hollow Knight",nvdec,playable,2023-01-16 15:44:56 +010013C00E930000,"Hollow Knight: Silksong",,playable,2025-09-04 17:23:22 0100F2100061E800,"Hollow0",UE4;gpu,ingame,2021-03-03 23:42:56 0100342009E16000,"Holy Potatoes! What The Hell?!",,playable,2020-07-03 10:48:56 010071B00C904000,"HoPiKo",,playable,2021-01-13 20:12:38 @@ -1888,7 +1889,7 @@ 010097800EA20000,"Monster Energy Supercross - The Official Videogame 3",UE4;audout;nvdec;online,playable,2021-06-14 12:37:54 0100E9900ED74000,"Monster Farm",32-bit;nvdec,playable,2021-05-05 19:29:13 0100770008DD8000,"Monster Hunter Generations Ultimate™",32-bit;online-broken;ldn-works,playable,2024-03-18 14:35:36 -0100B04011742000,"Monster Hunter Rise",gpu;slow;crash;nvdec;online-broken;Needs Update;ldn-works,ingame,2024-08-24 11:04:59 +0100B04011742000,"MONSTER HUNTER RISE",gpu;slow;crash;nvdec;online-broken;Needs Update;ldn-works,ingame,2024-08-24 11:04:59 010093A01305C000,"Monster Hunter Rise Demo",online-broken;ldn-works;demo,playable,2022-10-18 23:04:17 0100E21011446000,"Monster Hunter Stories 2: Wings of Ruin",services,ingame,2022-07-10 19:27:30 010042501329E000,"MONSTER HUNTER STORIES 2: WINGS OF RUIN Trial Version",demo,playable,2022-11-13 22:20:26 @@ -2313,7 +2314,7 @@ 010077B00BDD8000,"Professional Farmer: Nintendo Switch™ Edition",slow,playable,2020-12-16 13:38:19 010018300C83A000,"Professor Lupo and his Horrible Pets",,playable,2020-06-12 00:08:45 0100D1F0132F6000,"Professor Lupo: Ocean",,playable,2021-04-14 16:33:33 -0100c3a017834000,"Prodeus",,playable,2025-07-30 12:07:52 +0100C3A017834000,"Prodeus",,playable,2025-07-30 12:07:52 0100BBD00976C000,"Project Highrise: Architect's Edition",,playable,2022-08-10 17:19:12 0100ACE00DAB6000,"Project Nimbus: Complete Edition",nvdec;UE4;vulkan-backend-bug,playable,2022-08-10 17:35:43 01002980140F6000,"Project TRIANGLE STRATEGY™ Debut Demo",UE4;demo,playable,2022-10-24 21:40:27 @@ -2579,6 +2580,7 @@ 0100C610154CA000,"Shadowrun: Hong Kong - Extended Edition",gpu;Needs Update,ingame,2022-10-04 20:53:09 010000000EEF0000,"Shadows 2: Perfidia",,playable,2020-08-07 12:43:46 0100AD700CBBE000,"Shadows of Adam",,playable,2021-01-11 13:35:58 +010037A01F96C000,"Shadows of the Damned: Hella Remastered",,playable,2025-09-05 11:34:32 01002A800C064000,"Shadowverse Champions Battle",,playable,2022-10-02 22:59:29 01003B90136DA000,"Shadowverse: Champion's Battle",crash,nothing,2023-03-06 00:31:50 0100820013612000,"Shady Part of Me",,playable,2022-10-20 11:31:55 @@ -2977,6 +2979,7 @@ 0100EBA01548E000,"The Cruel King and the Great Hero",gpu;services,ingame,2022-12-02 07:02:08 010051800E922000,"The Dark Crystal: Age of Resistance Tactics",,playable,2020-08-11 13:43:41 01003DE00918E000,"The Darkside Detective",,playable,2020-06-03 22:16:18 +010032B015D66000,"The DioField Chronicle",,playable,2025-09-05 11:35:50 01000A10041EA000,"The Elder Scrolls V: Skyrim",gpu;crash,ingame,2024-07-14 03:21:31 01004A9006B84000,"The End Is Nigh",,playable,2020-06-01 11:26:45 0100CA100489C000,"The Escapists 2",nvdec,playable,2020-09-24 12:31:31 diff --git a/src/Ryujinx.Common/TitleIDs.cs b/src/Ryujinx.Common/TitleIDs.cs index 329078af9..b541fae5a 100644 --- a/src/Ryujinx.Common/TitleIDs.cs +++ b/src/Ryujinx.Common/TitleIDs.cs @@ -182,6 +182,7 @@ namespace Ryujinx.Common "01001cc01b2d4000", // Goat Simulator 3 "01003620068ea000", // Hand of Fate 2 "0100f7e00c70e000", // Hogwarts Legacy + "010013c00e930000", // Hollow Knight: Silksong "010085500130a000", // Lego City: Undercover "010073c01af34000", // LEGO Horizon Adventures "0100d71004694000", // Minecraft diff --git a/src/Ryujinx.HLE/FileSystem/ContentManager.cs b/src/Ryujinx.HLE/FileSystem/ContentManager.cs index 6ce19efee..9c6bfced6 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentManager.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentManager.cs @@ -501,53 +501,13 @@ namespace Ryujinx.HLE.FileSystem using FileStream file = File.OpenRead(keysSource); - switch (info.Extension) + if (info.Extension is ".keys") { - case ".zip": - using (ZipArchive archive = ZipFile.OpenRead(keysSource)) - { - InstallKeysFromZip(archive, installDirectory); - } - - break; - case ".keys": - 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 static void InstallKeysFromZip(ZipArchive archive, string installDirectory) - { - string temporaryDirectory = Path.Combine(installDirectory, "temp"); - if (Directory.Exists(temporaryDirectory)) - { - Directory.Delete(temporaryDirectory, true); - } - - Directory.CreateDirectory(temporaryDirectory); - foreach (ZipArchiveEntry 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); + VerifyKeysFile(keysSource); + File.Copy(keysSource, Path.Combine(installDirectory, info.Name), true); + } + else + throw new InvalidFirmwarePackageException("Input file is not a valid key package"); } private void FinishInstallation(string temporaryDirectory, string registeredDirectory) diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs index 8648b0642..9986bf824 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs @@ -31,11 +31,13 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati private readonly KEvent _friendInvitationStorageChannelEvent; private readonly KEvent _notificationStorageChannelEvent; private readonly KEvent _healthWarningDisappearedSystemEvent; + private readonly KEvent _unknownEvent; private int _gpuErrorDetectedSystemEventHandle; private int _friendInvitationStorageChannelEventHandle; private int _notificationStorageChannelEventHandle; private int _healthWarningDisappearedSystemEventHandle; + private int _unknownEventHandle; private bool _gamePlayRecordingState; @@ -50,6 +52,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati _friendInvitationStorageChannelEvent = new KEvent(system.KernelContext); _notificationStorageChannelEvent = new KEvent(system.KernelContext); _healthWarningDisappearedSystemEvent = new KEvent(system.KernelContext); + _unknownEvent = new KEvent(system.KernelContext); _horizon = system.LibHacHorizonManager.AmClient; } @@ -647,6 +650,23 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati return ResultCode.Success; } + + [CommandCmif(210)] // 20.0.0+ + // GetUnknownEvent() -> handle + public ResultCode GetUnknownEvent(ServiceCtx context) + { + if (_unknownEventHandle == 0) + { + if (context.Process.HandleTable.GenerateHandle(_unknownEvent.ReadableEvent, out _unknownEventHandle) != Result.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_unknownEventHandle); + + return ResultCode.Success; + } [CommandCmif(1001)] // 10.0.0+ // PrepareForJit() diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs index f567bbc3c..092d0215a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Common/RingLifo.cs @@ -39,9 +39,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common public ref AtomicStorage GetCurrentAtomicEntryRef() { - ulong countAvailaible = Math.Min(Math.Max(0, ReadCurrentCount()), 1); + ulong countAvailable = Math.Min(Math.Max(0, ReadCurrentCount()), 1); - if (countAvailaible == 0) + if (countAvailable == 0) { _storage[0] = default; @@ -54,7 +54,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common while (true) { - int inputEntryIndex = (int)((index + MaxEntries + 1 - countAvailaible) % MaxEntries); + int inputEntryIndex = (int)((index + MaxEntries + 1 - countAvailable) % MaxEntries); ref AtomicStorage result = ref storageSpan[inputEntryIndex]; @@ -63,9 +63,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common if (samplingNumber0 != samplingNumber1 && (result.SamplingNumber - result.SamplingNumber) != 1) { - ulong tempCount = Math.Min(ReadCurrentCount(), countAvailaible); + ulong tempCount = Math.Min(ReadCurrentCount(), countAvailable); - countAvailaible = Math.Min(tempCount, 1); + countAvailable = Math.Min(tempCount, 1); index = ReadCurrentIndex(); continue; diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCondition.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCondition.cs new file mode 100644 index 000000000..813020188 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadCondition.cs @@ -0,0 +1,23 @@ +namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad +{ + struct NpadCondition + { +#pragma warning disable CS0414 // Field is assigned but its value is never used + private uint _00; + private uint _04; + private NpadJoyHoldType _holdType; + private uint _0C; +#pragma warning restore CS0414 // Field is assigned but its value is never used + + public static NpadCondition Create() + { + return new NpadCondition() + { + _00 = 0, + _04 = 1, + _holdType = NpadJoyHoldType.Horizontal, + _0C = 1, + }; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs index f79a2657e..c518cf95d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs @@ -41,6 +41,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad public NpadLarkType LarkTypeRight; public NpadLuciaType LuciaType; public uint Unknown43EC; + public ulong SixAxisSensorPropertiesArray; [StructLayout(LayoutKind.Sequential, Size = 123, Pack = 1)] private struct Reserved2Struct { } diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs index adbbbc78b..1ac796407 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs @@ -52,6 +52,12 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory /// [FieldOffset(0x3DC00)] public RingLifo DebugMouse; + + /// + /// Pad Condition. + /// + [FieldOffset(0x3e200)] + public NpadCondition Condition; public static SharedMemory Create() { @@ -61,6 +67,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory TouchScreen = RingLifo.Create(), Mouse = RingLifo.Create(), Keyboard = RingLifo.Create(), + Condition = NpadCondition.Create(), }; Span npadsSpan = result.Npads.AsSpan(); diff --git a/src/Ryujinx.HLE/Switch.cs b/src/Ryujinx.HLE/Switch.cs index e1aa8e0e4..03fba1514 100644 --- a/src/Ryujinx.HLE/Switch.cs +++ b/src/Ryujinx.HLE/Switch.cs @@ -20,6 +20,18 @@ namespace Ryujinx.HLE { public class Switch : IDisposable { + /// + /// Currently running emulated Switch, if there is one. + /// + /// Proper usage of this property null checks it before use, unless the caller is certain that the emulation is running. + /// + /// + /// In case the emulation is running, there might be a way to directly pass the instance, which is preferred. + /// + /// + /// The instance is set to this on any instantiation, and set to null on any disposal. + /// + /// public static Switch Shared { get; private set; } public HleConfiguration Configuration { get; } diff --git a/src/Ryujinx/Common/ApplicationHelper.cs b/src/Ryujinx/Common/ApplicationHelper.cs index afdab3af5..3efd9ed62 100644 --- a/src/Ryujinx/Common/ApplicationHelper.cs +++ b/src/Ryujinx/Common/ApplicationHelper.cs @@ -1,6 +1,5 @@ using Avalonia.Platform.Storage; using Avalonia.Threading; -using Gommon; using LibHac; using LibHac.Account; using LibHac.Common; @@ -411,7 +410,7 @@ namespace Ryujinx.Ava.Common public static async Task ExtractAoc(IStorageProvider storageProvider, string updateFilePath, string updateName) { - Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions + Gommon.Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] }); @@ -424,7 +423,7 @@ namespace Ryujinx.Ava.Common public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) { - Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions + Gommon.Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] }); diff --git a/src/Ryujinx/Common/LocaleManager.cs b/src/Ryujinx/Common/LocaleManager.cs index 0b0a2caad..bc9cfdf15 100644 --- a/src/Ryujinx/Common/LocaleManager.cs +++ b/src/Ryujinx/Common/LocaleManager.cs @@ -19,7 +19,7 @@ namespace Ryujinx.Ava.Common.Locale private readonly Dictionary _localeStrings; private readonly ConcurrentDictionary _dynamicValues; private string _localeLanguageCode; - + public string CurrentLanguageCode => _localeLanguageCode; public static LocaleManager Instance { get; } = new(); public event Action LocaleChanged; diff --git a/src/Ryujinx/Systems/AppHost.cs b/src/Ryujinx/Systems/AppHost.cs index 29eb0a8ec..89f9412ba 100644 --- a/src/Ryujinx/Systems/AppHost.cs +++ b/src/Ryujinx/Systems/AppHost.cs @@ -1045,7 +1045,7 @@ namespace Ryujinx.Ava.Systems _viewModel.Window.TitleBar.ExtendsContentIntoTitleBar = true; } - if (_viewModel.WindowState is WindowState.FullScreen || _viewModel.StartGamesWithoutUI) + if (_viewModel.WindowState is WindowState.FullScreen || _viewModel.StartGamesWithoutUi) { _viewModel.ShowMenuAndStatusBar = false; } diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs index 313a43358..48bc1571a 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs @@ -117,7 +117,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary using UniqueRef npdmFile = new(); - Result result = pfs.OpenFile(ref npdmFile.Ref, "/main.npdm".ToU8Span(), OpenMode.Read); + LibHac.Result result = pfs.OpenFile(ref npdmFile.Ref, "/main.npdm".ToU8Span(), OpenMode.Read); if (ResultFs.PathNotFound.Includes(result)) { diff --git a/src/Ryujinx/Systems/PlayReport/PlayReports.Formatters.cs b/src/Ryujinx/Systems/PlayReport/PlayReports.Formatters.cs index dacf3ef0e..5aeb923da 100644 --- a/src/Ryujinx/Systems/PlayReport/PlayReports.Formatters.cs +++ b/src/Ryujinx/Systems/PlayReport/PlayReports.Formatters.cs @@ -97,8 +97,10 @@ namespace Ryujinx.Ava.Systems.PlayReport //TODO DLC Locations _ => FormattedValue.ForceReset }; - - return $"{playStatus} in {locations}"; + + return locations.Reset + ? FormattedValue.ForceReset + : $"{playStatus} in {locations}"; } private static FormattedValue SuperSmashBrosUltimate_Mode(SparseMultiValue values) diff --git a/src/Ryujinx/Systems/Updater/Updater.GitLab.cs b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs index 3411daa5d..17f01c136 100644 --- a/src/Ryujinx/Systems/Updater/Updater.GitLab.cs +++ b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs @@ -7,6 +7,7 @@ using Ryujinx.Common.Logging; using Ryujinx.Systems.Update.Client; using Ryujinx.Systems.Update.Common; using System; +using System.Net.Http; using System.Threading.Tasks; namespace Ryujinx.Ava.Systems @@ -14,16 +15,38 @@ namespace Ryujinx.Ava.Systems internal static partial class Updater { private static VersionResponse _versionResponse; + private static UpdateClient _updateClient; - private static UpdateClient CreateUpdateClient() - => UpdateClient.Builder() + private static async Task> QueryLatestVersionAsync() + { + _updateClient ??= UpdateClient.Builder() .WithServerEndpoint("https://update.ryujinx.app") // This is the default, and doesn't need to be provided; it's here for transparency. .WithLogger((format, args, caller) => Logger.Info?.Print( LogClass.Application, args.Length is 0 ? format : format.Format(args), caller: caller) - ); + ); + + try + { + return await _updateClient.QueryLatestAsync(ReleaseInformation.IsCanaryBuild + ? ReleaseChannel.Canary + : ReleaseChannel.Stable); + } + catch (HttpRequestException hre) + when (hre.HttpRequestError is HttpRequestError.ConnectionError) + { + return Return.Failure( + new MessageError("Connection error occurred. Is your internet down?")); + } + catch (HttpRequestException hre) + when (hre.HttpRequestError is HttpRequestError.NameResolutionError) + { + return Return.Failure( + new MessageError("DNS resolution error occurred. Is your internet down?")); + } + } public static async Task> CheckVersionAsync(bool showVersionUpToDate = false) { @@ -41,22 +64,18 @@ namespace Ryujinx.Ava.Systems return default; } - using UpdateClient updateClient = CreateUpdateClient(); - try { - _versionResponse = await updateClient.QueryLatestAsync(ReleaseInformation.IsCanaryBuild - ? ReleaseChannel.Canary - : ReleaseChannel.Stable); + _versionResponse = await QueryLatestVersionAsync().Then(x => x.Unwrap()); } catch (Exception e) { - Logger.Error?.Print(LogClass.Application, $"An error occurred when requesting for updates ({e.GetType().AsFullNamePrettyString()}): {e.Message}"); + Logger.Error?.Print(LogClass.Application, $"{e.GetType().AsPrettyString()} thrown when requesting updates: {e.Message}"); _running = false; return default; } - + if (_versionResponse == null) { // logging is done via the UpdateClient library diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml index cb71ffcd2..8cd1f5914 100755 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml @@ -71,12 +71,12 @@ Command="{Binding OpenTitleUpdateManager}" CommandParameter="{Binding}" Header="{ext:Locale GameListContextMenuManageTitleUpdates}" - Icon="{ext:Icon fa-solid fa-code-compare}" /> + Icon="{ext:Icon fa-solid fa-diagram-predecessor}" /> + Icon="{ext:Icon fa-solid fa-puzzle-piece}" /> + Icon="{ext:Icon fa-solid fa-folder-closed}" /> + Icon="{ext:Icon fa-solid fa-folder-closed}" /> + Icon="{ext:Icon fa-solid fa-folder-closed}" /> + xmlns:sty="using:FluentAvalonia.Styling" + xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"> @@ -19,7 +20,7 @@ - + diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index d1b2d6916..99b269ab1 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -562,7 +562,7 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public bool StartGamesWithoutUI + public bool StartGamesWithoutUi { get => ConfigurationState.Instance.UI.StartNoUI; set @@ -974,9 +974,8 @@ namespace Ryujinx.Ava.UI.ViewModels string dialogTitle = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallTitle); string dialogMessage = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallMessage); - - bool alreadyKesyInstalled = ContentManager.AreKeysAlredyPresent(systemDirectory); - if (alreadyKesyInstalled) + + if (ContentManager.AreKeysAlredyPresent(systemDirectory)) { dialogMessage += LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallSubMessage); } @@ -994,7 +993,7 @@ namespace Ryujinx.Ava.UI.ViewModels if (result == UserResult.Yes) { - Logger.Info?.Print(LogClass.Application, $"Installing Keys"); + Logger.Info?.Print(LogClass.Application, $"Installing keys from {filename}"); Thread thread = new(() => { @@ -1204,17 +1203,16 @@ namespace Ryujinx.Ava.UI.ViewModels _rendererWaitEvent.Set(); } - private async Task LoadContentFromFolder(LocaleKeys localeMessageAddedKey, LocaleKeys localeMessageRemovedKey, LoadContentFromFolderDelegate onDirsSelected) + private async Task LoadContentFromFolder(LocaleKeys localeMessageAddedKey, LocaleKeys localeMessageRemovedKey, LoadContentFromFolderDelegate onDirsSelected, LocaleKeys dirSelectDialogTitle) { - IReadOnlyList result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions + Optional> result = await StorageProvider.OpenMultiFolderPickerAsync(new FolderPickerOpenOptions { - Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle], - AllowMultiple = true, + Title = LocaleManager.Instance[dirSelectDialogTitle] }); - if (result.Count > 0) + if (result.TryGet(out IReadOnlyList foldersToLoad)) { - List dirs = result.Select(it => it.Path.LocalPath).ToList(); + List dirs = foldersToLoad.Select(it => it.Path.LocalPath).ToList(); int numAdded = onDirsSelected(dirs, out int numRemoved); string msg = string.Join("\n", @@ -1270,51 +1268,26 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public void TakeScreenshot() - { - AppHost.ScreenshotRequested = true; - } + public void TakeScreenshot() => AppHost.ScreenshotRequested = true; - public void HideUi() - { - ShowMenuAndStatusBar = false; - } + public void HideUi() => ShowMenuAndStatusBar = false; - public void ToggleStartGamesInFullscreen() - { - StartGamesInFullscreen = !StartGamesInFullscreen; - } + public void ToggleStartGamesInFullscreen() => StartGamesInFullscreen = !StartGamesInFullscreen; - public void ToggleStartGamesWithoutUI() - { - StartGamesWithoutUI = !StartGamesWithoutUI; - } + public void ToggleStartGamesWithoutUi() => StartGamesWithoutUi = !StartGamesWithoutUi; - public void ToggleShowConsole() - { - ShowConsole = !ShowConsole; - } + public void ToggleShowConsole() => ShowConsole = !ShowConsole; - public void SetListMode() - { - Glyph = Glyph.List; - } + public void SetListMode() => Glyph = Glyph.List; - public void SetGridMode() - { - Glyph = Glyph.Grid; - } + public void SetGridMode() => Glyph = Glyph.Grid; - public void SetAspectRatio(AspectRatio aspectRatio) - { - ConfigurationState.Instance.Graphics.AspectRatio.Value = aspectRatio; - } + public void SetAspectRatio(AspectRatio aspectRatio) => ConfigurationState.Instance.Graphics.AspectRatio.Value = aspectRatio; public async Task InstallFirmwareFromFile() { - IReadOnlyList result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions + Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { - AllowMultiple = false, FileTypeFilter = new List { new(LocaleManager.Instance[LocaleKeys.FileDialogAllTypes]) @@ -1338,69 +1311,50 @@ namespace Ryujinx.Ava.UI.ViewModels }, }); - if (result.Count > 0) + if (result.HasValue) { - await HandleFirmwareInstallation(result[0].Path.LocalPath); + await HandleFirmwareInstallation(result.Value.Path.LocalPath); } } public async Task InstallFirmwareFromFolder() { - IReadOnlyList result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions - { - AllowMultiple = false, - }); + Optional result = await StorageProvider.OpenSingleFolderPickerAsync(); - if (result.Count > 0) + if (result.HasValue) { - await HandleFirmwareInstallation(result[0].Path.LocalPath); + await HandleFirmwareInstallation(result.Value.Path.LocalPath); } } public async Task InstallKeysFromFile() { - IReadOnlyList result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions + Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { - AllowMultiple = false, FileTypeFilter = new List { - new(LocaleManager.Instance[LocaleKeys.FileDialogAllTypes]) - { - Patterns = ["*.keys", "*.zip"], - AppleUniformTypeIdentifiers = ["com.ryujinx.xci", "public.zip-archive"], - MimeTypes = ["application/keys", "application/zip"], - }, new("KEYS") { Patterns = ["*.keys"], AppleUniformTypeIdentifiers = ["com.ryujinx.xci"], MimeTypes = ["application/keys"], }, - new("ZIP") - { - Patterns = ["*.zip"], - AppleUniformTypeIdentifiers = ["public.zip-archive"], - MimeTypes = ["application/zip"], - }, }, }); - if (result.Count > 0) + if (result.HasValue) { - await HandleKeysInstallation(result[0].Path.LocalPath); + await HandleKeysInstallation(result.Value.Path.LocalPath); } } public async Task InstallKeysFromFolder() { - IReadOnlyList result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions - { - AllowMultiple = false, - }); + Optional result = await StorageProvider.OpenSingleFolderPickerAsync(); - if (result.Count > 0) + if (result.HasValue) { - await HandleKeysInstallation(result[0].Path.LocalPath); + await HandleKeysInstallation(result.Value.Path.LocalPath); } } @@ -1503,10 +1457,9 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenFile() { - IReadOnlyList result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions + Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { - Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle], - AllowMultiple = false, + Title = LocaleManager.Instance[LocaleKeys.LoadApplicationFromFileDialogTitle], FileTypeFilter = new List { new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) @@ -1562,9 +1515,9 @@ namespace Ryujinx.Ava.UI.ViewModels }, }); - if (result.Count > 0) + if (result.HasValue) { - if (ApplicationLibrary.TryGetApplicationsFromFile(result[0].Path.LocalPath, + if (ApplicationLibrary.TryGetApplicationsFromFile(result.Value.Path.LocalPath, out List applications)) { await LoadApplication(applications[0]); @@ -1581,7 +1534,8 @@ namespace Ryujinx.Ava.UI.ViewModels await LoadContentFromFolder( LocaleKeys.AutoloadDlcAddedMessage, LocaleKeys.AutoloadDlcRemovedMessage, - ApplicationLibrary.AutoLoadDownloadableContents); + ApplicationLibrary.AutoLoadDownloadableContents, + LocaleKeys.LoadDLCFromFolderDialogTitle); } public async Task LoadTitleUpdatesFromFolder() @@ -1589,23 +1543,23 @@ namespace Ryujinx.Ava.UI.ViewModels await LoadContentFromFolder( LocaleKeys.AutoloadUpdateAddedMessage, LocaleKeys.AutoloadUpdateRemovedMessage, - ApplicationLibrary.AutoLoadTitleUpdates); + ApplicationLibrary.AutoLoadTitleUpdates, + LocaleKeys.LoadTitleUpdatesFromFolderDialogTitle); } public async Task OpenFolder() { - IReadOnlyList result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions + Optional result = await StorageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions { - Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle], - AllowMultiple = false, + Title = LocaleManager.Instance[LocaleKeys.LoadUnpackedGameFromFolderDialogTitle] }); - if (result.Count > 0) + if (result.TryGet(out IStorageFolder value)) { ApplicationData applicationData = new() { - Name = Path.GetFileNameWithoutExtension(result[0].Path.LocalPath), - Path = result[0].Path.LocalPath, + Name = Path.GetFileNameWithoutExtension(value.Path.LocalPath), + Path = value.Path.LocalPath, }; await LoadApplication(applicationData); @@ -1810,10 +1764,9 @@ namespace Ryujinx.Ava.UI.ViewModels { if (AppHost.Device.System.SearchingForAmiibo(out _) && IsGameRunning) { - IReadOnlyList result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions + Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle], - AllowMultiple = false, FileTypeFilter = new List { new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) @@ -1822,9 +1775,10 @@ namespace Ryujinx.Ava.UI.ViewModels } } }); - if (result.Count > 0) + + if (result.HasValue) { - AppHost.Device.System.ScanAmiiboFromBin(result[0].Path.LocalPath); + AppHost.Device.System.ScanAmiiboFromBin(result.Value.Path.LocalPath); } } } diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml index 76bafe0c4..9b5c85793 100755 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml @@ -39,36 +39,29 @@ Header="{ext:Locale MenuBarFileOpenUnpacked}" Icon="{ext:Icon fa-solid fa-folder-open}" IsEnabled="{Binding EnableNonGameRunningControls}" /> - + - - - - + Icon="{ext:Icon fa-solid fa-terminal}" /> + @@ -132,11 +125,6 @@ Icon="{ext:Icon fa-solid fa-globe}" Classes="withCheckbox"> - - - - - + + + - + + + + - + + - + diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs index d8dff3eb3..f6bf43795 100644 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs @@ -61,6 +61,14 @@ namespace Ryujinx.Ava.UI.Views.Main WindowSize1080PMenuItem.Command = WindowSize1440PMenuItem.Command = WindowSize2160PMenuItem.Command = Commands.Create(ChangeWindowSize); + + LocaleManager.Instance.LocaleChanged += OnLocaleChanged; + } + + private void OnLocaleChanged() + { + ChangeLanguageMenuItem.ItemsSource = GenerateLanguageMenuItems(); + Menu.Close(); } private IEnumerable GenerateToggleFileTypeItems() => @@ -80,6 +88,7 @@ namespace Ryujinx.Ava.UI.Views.Main const string LocalePath = "Ryujinx/Assets/Locale.json"; string languageJson = EmbeddedResources.ReadAllText(LocalePath); + string currentLanguageCode = LocaleManager.Instance.CurrentLanguageCode; LocalesJson locales = JsonHelper.Deserialize(languageJson, LocalesJsonContext.Default.LocalesJson); @@ -105,7 +114,7 @@ namespace Ryujinx.Ava.UI.Views.Main Padding = new Thickness(15, 0, 0, 0), Margin = new Thickness(3, 0, 3, 0), HorizontalAlignment = HorizontalAlignment.Stretch, - Header = languageName, + Header = language == currentLanguageCode ? $"{languageName} ✔" : languageName, Command = Commands.Create(() => MainWindowViewModel.ChangeLanguage(language)) };