diff --git a/assets/locales.json b/assets/locales.json
index ae896da30..22848de4e 100644
--- a/assets/locales.json
+++ b/assets/locales.json
@@ -58,7 +58,7 @@
"no_NO": "Norsk",
"pl_PL": "Polski",
"pt_BR": "Português (BR)",
- "ru_RU": "Русский (RU)",
+ "ru_RU": "Русский",
"sv_SE": "Svenska",
"th_TH": "ภาษาไทย",
"tr_TR": "Türkçe",
@@ -75,7 +75,7 @@
"el_GR": "Άνοιγμα Applet",
"en_US": "Open Applet",
"es_ES": "Abrir applet",
- "fr_FR": "Ouvrir une applet",
+ "fr_FR": "Ouvrir une Applet",
"he_IL": "פתח יישומון",
"it_IT": "Apri applet",
"ja_JP": "アプレットを開く",
@@ -108,9 +108,9 @@
"no_NO": "Mii-redigeringsapplet",
"pl_PL": "",
"pt_BR": "Editor de Mii",
- "ru_RU": "Апплет Mii Editor",
+ "ru_RU": "Редактор Mii",
"sv_SE": "Redigera Mii-applet",
- "th_TH": "",
+ "th_TH": "ตัวแก้ไขตัวละคร Mii",
"tr_TR": "",
"uk_UA": "Аплет редагування Mii",
"zh_CN": "Mii 小程序",
@@ -125,7 +125,7 @@
"el_GR": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία",
"en_US": "Open Mii Editor Applet 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’Applet Éditeur Mii en mode Autonome",
"he_IL": "פתח את יישומון עורך ה- Mii במצב עצמאי",
"it_IT": "Apri l'applet Editor Mii in modalità Standalone",
"ja_JP": "スタンドアロンモードで Mii エディタアプレットを開きます",
@@ -133,7 +133,7 @@
"no_NO": "Åpne Mii Redigerings program i eget vindu",
"pl_PL": "Otwórz aplet Mii Editor w trybie indywidualnym",
"pt_BR": "Abrir Editor de Mii em Modo Independente",
- "ru_RU": "Открывает апплет Mii Editor в автономном режиме",
+ "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ç",
@@ -150,7 +150,7 @@
"el_GR": "Άμεση Πρόσβαση Ποντικιού",
"en_US": "Direct Mouse Access",
"es_ES": "Acceso directo al ratón",
- "fr_FR": "Accès direct à la souris",
+ "fr_FR": "Accès Direct à la Souris",
"he_IL": "גישה ישירה לעכבר",
"it_IT": "Accesso diretto al mouse",
"ja_JP": "マウス直接アクセス",
@@ -158,7 +158,7 @@
"no_NO": "Direkte tilgang med Mus",
"pl_PL": "Bezpośredni dostęp do myszy",
"pt_BR": "Acesso Direto ao Mouse",
- "ru_RU": "Прямой ввод мыши",
+ "ru_RU": "Прямой Ввод Мыши",
"sv_SE": "Direkt musåtkomst",
"th_TH": "เข้าถึงเมาส์ได้โดยตรง",
"tr_TR": "Doğrudan Mouse Erişimi",
@@ -175,7 +175,7 @@
"el_GR": "Λειτουργία Διαχείρισης Μνήμης:",
"en_US": "Memory Manager Mode:",
"es_ES": "Modo del administrador de memoria:",
- "fr_FR": "Mode de gestion de la mémoire :",
+ "fr_FR": "Mode de Gestion de la Mémoire :",
"he_IL": "מצב מנהל זיכרון:",
"it_IT": "Modalità di gestione della memoria:",
"ja_JP": "メモリ管理モード:",
@@ -183,7 +183,7 @@
"no_NO": "Memory Manager-modus",
"pl_PL": "Tryb menedżera pamięci:",
"pt_BR": "Modo de Gerenciamento da Memória:",
- "ru_RU": "Режим менеджера памяти:",
+ "ru_RU": "Режим управления памяти:",
"sv_SE": "Läge för minnehanterare:",
"th_TH": "โหมดจัดการหน่วยความจำ:",
"tr_TR": "Hafıza Yönetim Modu:",
@@ -225,7 +225,7 @@
"el_GR": "Υπολογιστής (γρήγορο)",
"en_US": "Host (Fast)",
"es_ES": "Host (rápido)",
- "fr_FR": "Hôte (rapide)",
+ "fr_FR": "Hôte (Rapide)",
"he_IL": "מארח (מהיר)",
"it_IT": "Host (veloce)",
"ja_JP": "ホスト (高速)",
@@ -233,7 +233,7 @@
"no_NO": "Vert (rask)",
"pl_PL": "Gospodarz (szybki)",
"pt_BR": "Hóspede (rápido)",
- "ru_RU": "Хост (быстро)",
+ "ru_RU": "Хост (быстрый)",
"sv_SE": "Värd (snabb)",
"th_TH": "โฮสต์ (เร็ว)",
"tr_TR": "Host (hızlı)",
@@ -250,7 +250,7 @@
"el_GR": "Χωρίς Ελέγχους (γρηγορότερο, μη ασφαλές)",
"en_US": "Host Unchecked (Fastest, Unsafe)",
"es_ES": "Host sin verificación (más rápido, inseguro)",
- "fr_FR": "Hôte non vérifié (plus rapide, non sécurisé)",
+ "fr_FR": "Hôte Non Vérifié (plus rapide, non sécurisé)",
"he_IL": "מארח לא מבוקר (המהיר ביותר, לא בטוח)",
"it_IT": "Host Unchecked (più veloce, non sicura)",
"ja_JP": "ホスト, チェックなし (最高速, 安全でない)",
@@ -258,7 +258,7 @@
"no_NO": "Vert Ukontrollert (raskets, utrygt)",
"pl_PL": "Gospodarza (NIESPRAWDZONY, najszybszy, niebezpieczne)",
"pt_BR": "Hóspede sem Verificação (mais rápido, inseguro)",
- "ru_RU": "Хост не установлен (самый быстрый, небезопасный)",
+ "ru_RU": "Хост без проверки (самый быстрый, небезопасный)",
"sv_SE": "Värd inte kontrollerad (snabbaste, osäkert)",
"th_TH": "ไม่ได้ตรวจสอบโฮสต์ (เร็วที่สุด, แต่ไม่ปลอดภัย)",
"tr_TR": "Host Unchecked (en hızlısı, tehlikeli)",
@@ -325,7 +325,7 @@
"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",
+ "fr_FR": "_Charger une Application à partir d’un Fichier",
"he_IL": "_טען יישום מקובץ",
"it_IT": "_Carica applicazione da un file",
"ja_JP": "ファイルからアプリケーションをロード(_L)",
@@ -358,7 +358,7 @@
"no_NO": "Ingen apper ble funnet i valgt fil.",
"pl_PL": "",
"pt_BR": "Nenhum aplicativo encontrado no arquivo selecionado.",
- "ru_RU": "Приложения в выбранном файле не найдены",
+ "ru_RU": "Приложений в выбранном файле не найдены",
"sv_SE": "Inga applikationer hittades i vald fil.",
"th_TH": "ไม่พบแอปพลิเคชั่นจากไฟล์ที่เลือก",
"tr_TR": "",
@@ -375,7 +375,7 @@
"el_GR": "Φόρτωση Απακετάριστου _Παιχνιδιού",
"en_US": "Load _Unpacked Game",
"es_ES": "Cargar juego _desempaquetado",
- "fr_FR": "Charger un jeu décompressé",
+ "fr_FR": "Charger un Jeu _Décompressé",
"he_IL": "טען משחק _שאינו ארוז",
"it_IT": "Carica _gioco estratto",
"ja_JP": "展開されたゲームをロード",
@@ -400,7 +400,7 @@
"el_GR": "",
"en_US": "Load DLC From Folder",
"es_ES": "Cargar DLC Desde Carpeta",
- "fr_FR": "Charger les DLC à partir d’un dossier",
+ "fr_FR": "Charger les DLC À Partir d’un Dossier",
"he_IL": "",
"it_IT": "Carica DLC da una cartella",
"ja_JP": "",
@@ -425,7 +425,7 @@
"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",
+ "fr_FR": "Charger les Mises à Jour du Titre À Partir d’un Dossier",
"he_IL": "",
"it_IT": "Carica aggiornamenti da una cartella",
"ja_JP": "",
@@ -450,7 +450,7 @@
"el_GR": "Άνοιγμα Φακέλου Ryujinx",
"en_US": "Open Ryujinx Folder",
"es_ES": "Abrir carpeta de Ryujinx",
- "fr_FR": "Ouvrir le dossier Ryujinx",
+ "fr_FR": "Ouvrir le Dossier Ryujinx",
"he_IL": "פתח את תיקיית ריוג'ינקס",
"it_IT": "Apri cartella di Ryujinx",
"ja_JP": "Ryujinx フォルダを開く",
@@ -475,7 +475,7 @@
"el_GR": "",
"en_US": "Open Screenshots Folder",
"es_ES": "",
- "fr_FR": "Ouvrir le dossier des captures d’écran",
+ "fr_FR": "Ouvrir le Dossier de Capture d'Écrans",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -483,9 +483,9 @@
"no_NO": "Åpne Skjermbilde Mappen",
"pl_PL": "",
"pt_BR": "Abrir Pasta de Capturas de Tela",
- "ru_RU": "Открыть папку со скриншотами",
+ "ru_RU": "Открыть папку снимков экрана",
"sv_SE": "Öppna skärmbildsmappen",
- "th_TH": "",
+ "th_TH": "เปิดโฟลเดอร์ที่เก็บภาพหน้าจอ",
"tr_TR": "",
"uk_UA": "Відкрити теку скріншотів",
"zh_CN": "打开截图文件夹",
@@ -508,7 +508,7 @@
"no_NO": "Åpne Logg mappen",
"pl_PL": "Otwórz folder plików dziennika zdarzeń",
"pt_BR": "Abrir Pasta de _Logs",
- "ru_RU": "Открыть папку с логами",
+ "ru_RU": "Открыть папку журналов",
"sv_SE": "Öppna loggmapp",
"th_TH": "เปิดโฟลเดอร์ Logs",
"tr_TR": "Logs Klasörünü aç",
@@ -533,7 +533,7 @@
"no_NO": "_Avslutt",
"pl_PL": "_Wyjdź",
"pt_BR": "_Sair",
- "ru_RU": "_Выход",
+ "ru_RU": "_Выйти",
"sv_SE": "_Avsluta",
"th_TH": "_ออก",
"tr_TR": "_Çıkış",
@@ -550,7 +550,7 @@
"el_GR": "_Επιλογές",
"en_US": "_Options",
"es_ES": "_Opciones",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "_אפשרויות",
"it_IT": "_Opzioni",
"ja_JP": "オプション(_O)",
@@ -575,7 +575,7 @@
"el_GR": "Λειτουργία Πλήρους Οθόνης",
"en_US": "Toggle Fullscreen",
"es_ES": "Cambiar a pantalla completa.",
- "fr_FR": "Basculer en plein écran",
+ "fr_FR": "Basculer en Plein Écran",
"he_IL": "שנה מצב- מסך מלא",
"it_IT": "Schermo intero",
"ja_JP": "全画面切り替え",
@@ -583,7 +583,7 @@
"no_NO": "Fullskjermsvisning av/på",
"pl_PL": "Przełącz na tryb pełnoekranowy",
"pt_BR": "Mudar para Tela Cheia",
- "ru_RU": "Включить полноэкранный режим",
+ "ru_RU": "Переключить полноэкранный режим",
"sv_SE": "Växla helskärm",
"th_TH": "สลับเป็นโหมดเต็มหน้าจอ",
"tr_TR": "Tam Ekran Modunu Aç",
@@ -600,7 +600,7 @@
"el_GR": "Εκκίνηση Παιχνιδιών σε Πλήρη Οθόνη",
"en_US": "Start Games in Fullscreen Mode",
"es_ES": "Iniciar juegos en pantalla completa",
- "fr_FR": "Démarrer les jeux en mode plein écran",
+ "fr_FR": "Démarrer les Jeux en Mode Plein Écran",
"he_IL": "התחל משחקים במסך מלא",
"it_IT": "Avvia i giochi a schermo intero",
"ja_JP": "全画面モードでゲームを開始",
@@ -625,7 +625,7 @@
"el_GR": "",
"en_US": "Start Games with UI Hidden",
"es_ES": "",
- "fr_FR": "Démarrer les jeux avec l’interface cachée",
+ "fr_FR": "Démarrer les Jeux avec l’Interface Cachée",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -635,7 +635,7 @@
"pt_BR": "Iniciar Jogos Ocultando a Interface",
"ru_RU": "Запускать игры скрывая интерфейс",
"sv_SE": "Starta spel med dolt användargränssnitt",
- "th_TH": "",
+ "th_TH": "เริ่มเกมโดยซ่อน UI",
"tr_TR": "",
"uk_UA": "Запускати ігри з прихованим інтерфейсом",
"zh_CN": "启动游戏时隐藏 UI",
@@ -650,7 +650,7 @@
"el_GR": "Διακοπή Εξομοίωσης",
"en_US": "Stop Emulation",
"es_ES": "Detener emulación",
- "fr_FR": "Arrêter l'émulation",
+ "fr_FR": "Arrêter l'Émulation",
"he_IL": "עצור אמולציה",
"it_IT": "Ferma emulazione",
"ja_JP": "エミュレーションを中止",
@@ -658,7 +658,7 @@
"no_NO": "Stopp Emulering",
"pl_PL": "Zatrzymaj emulację",
"pt_BR": "Parar a Emulação",
- "ru_RU": "Остановить эмуляцию",
+ "ru_RU": "Остановить",
"sv_SE": "Stoppa emulering",
"th_TH": "หยุดการจำลอง",
"tr_TR": "Emülasyonu Durdur",
@@ -700,7 +700,7 @@
"el_GR": "Διαχείριση Προφίλ _Χρηστών",
"en_US": "_Manage User Profiles",
"es_ES": "_Gestionar perfiles de usuario",
- "fr_FR": "_Gérer les profils utilisateur",
+ "fr_FR": "_Gérer les Profils d'Utilisateurs",
"he_IL": "_נהל פרופילי משתמש",
"it_IT": "_Gestisci i profili utente",
"ja_JP": "ユーザプロファイルを管理(_M)",
@@ -708,7 +708,7 @@
"no_NO": "_Administrere Brukerprofiler",
"pl_PL": "_Zarządzaj profilami użytkowników",
"pt_BR": "_Gerenciar Perfis de Usuário",
- "ru_RU": "_Менеджер учётных записей",
+ "ru_RU": "_Управление профилями",
"sv_SE": "_Hantera användarprofiler",
"th_TH": "_จัดการโปรไฟล์ผู้ใช้งาน",
"tr_TR": "_Kullanıcı Profillerini Yönet",
@@ -725,7 +725,7 @@
"el_GR": "_Δράσεις",
"en_US": "_Actions",
"es_ES": "_Acciones",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "_פעולות",
"it_IT": "_Azioni",
"ja_JP": "アクション(_A)",
@@ -735,7 +735,7 @@
"pt_BR": "_Ações",
"ru_RU": "_Действия",
"sv_SE": "_Åtgärder",
- "th_TH": "การดำเนินการ",
+ "th_TH": "_การดำเนินการ",
"tr_TR": "_Eylemler",
"uk_UA": "_Дії",
"zh_CN": "操作(_A)",
@@ -750,17 +750,17 @@
"el_GR": "Προσομοίωση Μηνύματος Αφύπνισης",
"en_US": "Simulate Wake-Up Message",
"es_ES": "Simular mensaje de reactivación",
- "fr_FR": "Simuler un message de réveil",
+ "fr_FR": "Simuler un Message de Réveil",
"he_IL": "דמה הודעת השכמה",
"it_IT": "Simula messaggio Wake-up",
"ja_JP": "スリープ復帰メッセージをシミュレート",
- "ko_KR": "웨이크업 메시지 시뮬레이션",
+ "ko_KR": "절전 모드 해제 메시지 시뮬레이션",
"no_NO": "Simuler oppvåknings-melding",
"pl_PL": "Symuluj wiadomość wybudzania",
"pt_BR": "Simular Mensagem de Acordar o Console",
"ru_RU": "Имитировать сообщение пробуждения",
"sv_SE": "Simulera uppvakningsmeddelande",
- "th_TH": "จำลองข้อความปลุก",
+ "th_TH": "จำลองการปลุกอุปกรณ์ให้ทำงาน",
"tr_TR": "Uyandırma Mesajı Simüle Et",
"uk_UA": "Симулювати повідомлення про пробудження",
"zh_CN": "模拟唤醒消息",
@@ -808,9 +808,9 @@
"no_NO": "Skann en Amiibo (fra bin fil)",
"pl_PL": "",
"pt_BR": "Escaneie um Amiibo (de um .bin)",
- "ru_RU": "Сканировать Amiibo (из папки Bin)",
+ "ru_RU": "Сканировать Amiibo (из .bin)",
"sv_SE": "Skanna en Amiibo (från bin-fil)",
- "th_TH": "",
+ "th_TH": "สแกนอามีโบ (จากไฟล์ Bin)",
"tr_TR": "",
"uk_UA": "Сканувати Amiibo (з теки Bin)",
"zh_CN": "扫描 Amiibo (从 bin 文件)",
@@ -825,7 +825,7 @@
"el_GR": "Εγκατάσταση Firmware",
"en_US": "Install Firmware",
"es_ES": "Instalar firmware",
- "fr_FR": "Installer le firmware",
+ "fr_FR": "Installer le Firmware",
"he_IL": "התקן קושחה",
"it_IT": "Installa firmware",
"ja_JP": "ファームウェアをインストール",
@@ -833,7 +833,7 @@
"no_NO": "Installer fastvare",
"pl_PL": "Zainstaluj oprogramowanie",
"pt_BR": "Instalar Firmware",
- "ru_RU": "Установка прошивки",
+ "ru_RU": "Установить прошивку",
"sv_SE": "Installera firmware",
"th_TH": "ติดตั้งเฟิร์มแวร์",
"tr_TR": "Yazılım Yükle",
@@ -850,7 +850,7 @@
"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",
+ "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 からファームウェアをインストール",
@@ -900,7 +900,7 @@
"el_GR": "",
"en_US": "Install Keys",
"es_ES": "",
- "fr_FR": "Installer des clés",
+ "fr_FR": "Installer des Clés",
"he_IL": "",
"it_IT": "Installa chiavi",
"ja_JP": "",
@@ -910,7 +910,7 @@
"pt_BR": "Instalar Chaves",
"ru_RU": "Установить ключи",
"sv_SE": "Installera nycklar",
- "th_TH": "",
+ "th_TH": "ติดตั้งคีย์",
"tr_TR": "",
"uk_UA": "Встановити ключі",
"zh_CN": "安装密匙",
@@ -925,7 +925,7 @@
"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",
+ "fr_FR": "Installer des Clés à partir de .KEYS ou .ZIP",
"he_IL": "",
"it_IT": "Installa chiavi da file KEYS o ZIP",
"ja_JP": "",
@@ -933,9 +933,9 @@
"no_NO": "Installer nøkler fra KEYS eller ZIP",
"pl_PL": "",
"pt_BR": "Instalar chaves de CHAVES ou ZIP",
- "ru_RU": "Установить ключи из файла KEYS или ZIP",
+ "ru_RU": "Установить ключи из KEYS или ZIP",
"sv_SE": "Installera nycklar från KEYS eller ZIP",
- "th_TH": "",
+ "th_TH": "ติดตั้งคีย์จากไฟล์ KEYS หรือ ZIP",
"tr_TR": "",
"uk_UA": "Встановити ключі з файлу .KEYS або .ZIP",
"zh_CN": "从 .KEYS 文件或 .ZIP 压缩包安装密匙",
@@ -950,7 +950,7 @@
"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",
+ "fr_FR": "Installer des Clés à partir d'un dossier",
"he_IL": "",
"it_IT": "Installa chiavi da una cartella",
"ja_JP": "",
@@ -960,7 +960,7 @@
"pt_BR": "Instalar chaves de um diretório",
"ru_RU": "Установить ключи из папки",
"sv_SE": "Installera nycklar från en katalog",
- "th_TH": "",
+ "th_TH": "ติดตั้งคีย์จากไดเรกทอรี",
"tr_TR": "",
"uk_UA": "Встановити ключі з теки",
"zh_CN": "从一个文件夹安装密匙",
@@ -975,7 +975,7 @@
"el_GR": "Διαχείριση τύπων αρχείων",
"en_US": "Manage File Types",
"es_ES": "Administrar tipos de archivo",
- "fr_FR": "Gérer les types de fichiers",
+ "fr_FR": "Gérer les Types de Fichiers",
"he_IL": "ניהול סוגי קבצים",
"it_IT": "Gestisci i tipi di file",
"ja_JP": "ファイル形式を管理",
@@ -1000,7 +1000,7 @@
"el_GR": "Εγκαταστήσετε τύπους αρχείων.",
"en_US": "Install File Types",
"es_ES": "Instalar tipos de archivo",
- "fr_FR": "Installer des types de fichiers",
+ "fr_FR": "Installer des Types de Fichiers",
"he_IL": "סוגי קבצי התקנה",
"it_IT": "Installa i tipi di file",
"ja_JP": "ファイル形式をインストール",
@@ -1025,7 +1025,7 @@
"el_GR": "Απεγκαταστήσετε τύπους αρχείων",
"en_US": "Uninstall File Types",
"es_ES": "Desinstalar tipos de archivo",
- "fr_FR": "Désinstaller des types de fichiers",
+ "fr_FR": "Désinstaller des Types de Fichiers",
"he_IL": "סוגי קבצי הסרה",
"it_IT": "Disinstalla i tipi di file",
"ja_JP": "ファイル形式をアンインストール",
@@ -1050,7 +1050,7 @@
"el_GR": "",
"en_US": "Trim XCI Files",
"es_ES": "Recortar archivos XCI",
- "fr_FR": "Réduire les fichiers XCI",
+ "fr_FR": "Réduire les Fichiers XCI",
"he_IL": "",
"it_IT": "Riduci dimensioni dei file XCI",
"ja_JP": "",
@@ -1058,9 +1058,9 @@
"no_NO": "Trim XCI-filer",
"pl_PL": "",
"pt_BR": "Reduzir Arquivos XCI",
- "ru_RU": "Уменьшить размер XCI файлов",
+ "ru_RU": "Обрезать XCI файлы",
"sv_SE": "Optimera XCI-filer",
- "th_TH": "",
+ "th_TH": "ตัดแต่งไฟล์ XCI",
"tr_TR": "",
"uk_UA": "Обрізати XCI файли",
"zh_CN": "瘦身 XCI 文件",
@@ -1100,7 +1100,7 @@
"el_GR": "",
"en_US": "Window Size",
"es_ES": "Tamaño Ventana",
- "fr_FR": "Taille de la fenêtre",
+ "fr_FR": "Taille de la Fenêtre",
"he_IL": "",
"it_IT": "Dimensione finestra",
"ja_JP": "",
@@ -1250,7 +1250,7 @@
"el_GR": "Έλεγχος για Ενημερώσεις",
"en_US": "Check for Updates",
"es_ES": "Buscar actualizaciones",
- "fr_FR": "Vérifier les mises à jour",
+ "fr_FR": "Vérifier les Mises à Jour",
"he_IL": "חפש עדכונים",
"it_IT": "Controlla aggiornamenti",
"ja_JP": "アップデートを確認",
@@ -1275,7 +1275,7 @@
"el_GR": "",
"en_US": "FAQ & Guides",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "Guide e domande frequenti",
"ja_JP": "",
@@ -1285,7 +1285,7 @@
"pt_BR": "FAQ & Guias",
"ru_RU": "FAQ и Руководства",
"sv_SE": "Frågor, svar och guider",
- "th_TH": "",
+ "th_TH": "คำถามที่พบบ่อย & คู่มือ",
"tr_TR": "",
"uk_UA": "FAQ та посібники",
"zh_CN": "问答与指南",
@@ -1310,7 +1310,7 @@
"pt_BR": "FAQ e Solução de Problemas",
"ru_RU": "FAQ & Устранение неполадок",
"sv_SE": "Frågor, svar och felsökningssida",
- "th_TH": "",
+ "th_TH": "หน้าคำถามที่พบบ่อยและแก้ไขปัญหา",
"tr_TR": "",
"uk_UA": "FAQ та усунення несправностей (eng)",
"zh_CN": "常见问题和问题排除页面",
@@ -1333,9 +1333,9 @@
"no_NO": "Åpner FAQ- og feilsøkingssiden på den offisielle Ryujinx-wikien",
"pl_PL": "",
"pt_BR": "Abre a página de FAQ e solução de problemas no wiki oficial do Ryujinx",
- "ru_RU": "Открывает страницы с FAQ и Устранением неполадок на официальной странице вики Ryujinx",
+ "ru_RU": "Открывает страницу FAQ и устранения неполадок на официальной вики Ryujinx",
"sv_SE": "Öppnar Frågor, svar och felsökningssidan på den officiella Ryujinx-wikin",
- "th_TH": "",
+ "th_TH": "เปิดหน้ารวมคำถามที่พบบ่อยและวิธีแก้ไขปัญหาบนเว็บไซต์วิกิของ Ryujinx",
"tr_TR": "",
"uk_UA": "Відкриває сторінку з Посібником по усуненню помилок та несправностей на офіційній вікі-сторінці Ryujinx (англійською)",
"zh_CN": "打开 Ryujinx 官方 Wiki 的常见问题和问题排除页面",
@@ -1360,7 +1360,7 @@
"pt_BR": "Guia de Instalação e Configuração",
"ru_RU": "Руководство по установке и настройке",
"sv_SE": "Konfigurationsguide",
- "th_TH": "",
+ "th_TH": "คู่มือการติดตั้งและปรับแต่งระบบ",
"tr_TR": "",
"uk_UA": "Посібник зі встановлення та налаштування (eng)",
"zh_CN": "安装与配置指南",
@@ -1375,7 +1375,7 @@
"el_GR": "",
"en_US": "Opens the Setup & Configuration guide on the official Ryujinx wiki",
"es_ES": "",
- "fr_FR": "Ouvre le guide d'installation et de configuration sur le wiki officiel de Ryujinx",
+ "fr_FR": "Ouvre le guide d'Installation et de Configuration sur le wiki officiel de Ryujinx",
"he_IL": "",
"it_IT": "Apre la guida all'installazione e alla configurazione presente nella wiki ufficiale di Ryujinx",
"ja_JP": "",
@@ -1383,9 +1383,9 @@
"no_NO": "Åpner oppsett- og konfigurasjonsveiledningen på den offisielle Ryujinx-wikien",
"pl_PL": "",
"pt_BR": "Abre o guia de instalação e configuração no wiki oficial do Ryujinx",
- "ru_RU": "Открывает страницу Руководство по установке и настройке на официальной странице вики Ryujinx",
+ "ru_RU": "Открывает руководство по установке и настройке на официальной вики Ryujinx",
"sv_SE": "Öppnar konfigurationsguiden på den officiella Ryujinx-wikin",
- "th_TH": "",
+ "th_TH": "เปิดคู่มือการติดตั้งและตั้งค่าบนวิกิอย่างเป็นทางการของ Ryujinx",
"tr_TR": "",
"uk_UA": "Відкриває посібник з Налаштування та конфігурації на офіційній вікі-сторінці Ryujinx (англійською)",
"zh_CN": "打开 Ryujinx 官方 Wiki 的安装与配置指南",
@@ -1408,9 +1408,9 @@
"no_NO": "Flerspillerveiledning (LDN/LAN)",
"pl_PL": "",
"pt_BR": "Guia Multijogador (LDN/LAN)",
- "ru_RU": "Гайд по мультиплееру (LDN/LAN)",
+ "ru_RU": "Руководство по мультиплееру (LDN/LAN)",
"sv_SE": "Flerspelarguide (LDN/LAN)",
- "th_TH": "",
+ "th_TH": "คู่มือการเล่นหลายคนผ่านระบบ LDN หรือ LAN",
"tr_TR": "",
"uk_UA": "Посібник з мультиплеєру (LDN/LAN) (eng)",
"zh_CN": "多人游戏(LDN/LAN)指南",
@@ -1433,9 +1433,9 @@
"no_NO": "Åpner flerspillerveiledningen på den offisielle Ryujinx-wikien",
"pl_PL": "",
"pt_BR": "Abre o guia multijogador no wiki oficial do Ryujinx",
- "ru_RU": "Открывает гайд по мультиплееру на официальной странице вики Ryujinx",
+ "ru_RU": "Открывает руководство по мультиплееру на официальной вики Ryujinx",
"sv_SE": "Öppnar flerspelarguiden på den officiella Ryujinx-wikin",
- "th_TH": "",
+ "th_TH": "เปิดคู่มือการเล่นหลายคนบนวิกิอย่างเป็นทางการของ Ryujinx",
"tr_TR": "",
"uk_UA": "Відкриває посібник з налаштування Мультиплеєру на офіційній вікі-сторінці Ryujinx (англійською)",
"zh_CN": "打开 Ryujinx 官方 Wiki 的多人游戏指南",
@@ -1450,7 +1450,7 @@
"el_GR": "Σχετικά με",
"en_US": "About",
"es_ES": "Acerca de",
- "fr_FR": "À propos",
+ "fr_FR": "À Propos",
"he_IL": "אודות",
"it_IT": "Informazioni",
"ja_JP": "Ryujinx について",
@@ -1585,7 +1585,7 @@
"pt_BR": "Desenvolvido por {0}",
"ru_RU": "Разработана {0}",
"sv_SE": "Utvecklat av {0}",
- "th_TH": "",
+ "th_TH": "พัฒนาโดย {0}",
"tr_TR": "",
"uk_UA": "Розроблено: {0}",
"zh_CN": "由 {0} 开发",
@@ -1625,7 +1625,7 @@
"el_GR": "Χρόνος:",
"en_US": "Play Time:",
"es_ES": "Tiempo jugado:",
- "fr_FR": "Temps de jeu:",
+ "fr_FR": "Temps de Jeu:",
"he_IL": "",
"it_IT": "Tempo di gioco:",
"ja_JP": "プレイ時間:",
@@ -1635,7 +1635,7 @@
"pt_BR": "Tempo de Jogo:",
"ru_RU": "Время в игре:",
"sv_SE": "Speltid:",
- "th_TH": "เล่นไปแล้ว:",
+ "th_TH": "เวลาที่เล่น:",
"tr_TR": "Oynama Süresi:",
"uk_UA": "Зіграно часу:",
"zh_CN": "游玩时长:",
@@ -1650,7 +1650,7 @@
"el_GR": "Παίχτηκε: ",
"en_US": "Last Played:",
"es_ES": "Jugado por última vez:",
- "fr_FR": "Dernière partie jouée:",
+ "fr_FR": "Dernière Partie Jouée:",
"he_IL": "",
"it_IT": "Ultima partita:",
"ja_JP": "最終プレイ日時:",
@@ -1660,7 +1660,7 @@
"pt_BR": "Última vez Jogado:",
"ru_RU": "Последний запуск:",
"sv_SE": "Senast spelad:",
- "th_TH": "เล่นล่าสุด:",
+ "th_TH": "เล่นไปล่าสุด:",
"tr_TR": "Son Oynama Tarihi:",
"uk_UA": "Востаннє зіграно:",
"zh_CN": "最近游玩:",
@@ -1700,7 +1700,7 @@
"el_GR": "Μέγεθος Αρχείου: {0}",
"en_US": "File Size: {0}",
"es_ES": "Tamaño del archivo: {0}",
- "fr_FR": "Taille du fichier: {0}",
+ "fr_FR": "Taille du Fichier: {0}",
"he_IL": "",
"it_IT": "Dimensione file: {0}",
"ja_JP": "ファイルサイズ: {0}",
@@ -1750,7 +1750,7 @@
"el_GR": "Χρόνος",
"en_US": "Play Time",
"es_ES": "Tiempo jugado",
- "fr_FR": "Temps de jeu",
+ "fr_FR": "Temps de Jeu",
"he_IL": "זמן משחק",
"it_IT": "Tempo di gioco",
"ja_JP": "プレイ時間",
@@ -1760,7 +1760,7 @@
"pt_BR": "Tempo de Jogo",
"ru_RU": "Время в игре",
"sv_SE": "Speltid",
- "th_TH": "เล่นไปแล้ว",
+ "th_TH": "เวลาที่เล่น",
"tr_TR": "Oynama Süresi",
"uk_UA": "Зіграно часу",
"zh_CN": "游玩时长",
@@ -1775,7 +1775,7 @@
"el_GR": "Παίχτηκε",
"en_US": "Last Played",
"es_ES": "Jugado por última vez",
- "fr_FR": "Dernière partie jouée",
+ "fr_FR": "Dernière Partie Jouée",
"he_IL": "שוחק לאחרונה",
"it_IT": "Ultima partita",
"ja_JP": "最終プレイ日時",
@@ -1800,7 +1800,7 @@
"el_GR": "Κατάληξη",
"en_US": "File Ext.",
"es_ES": "Extensión",
- "fr_FR": "Extension du fichier",
+ "fr_FR": "Extension du Fichier",
"he_IL": "סיומת קובץ",
"it_IT": "Estensione",
"ja_JP": "ファイル拡張子",
@@ -1825,7 +1825,7 @@
"el_GR": "Μέγεθος Αρχείου",
"en_US": "File Size",
"es_ES": "Tamaño del archivo",
- "fr_FR": "Taille du fichier",
+ "fr_FR": "Taille du Fichier",
"he_IL": "גודל הקובץ",
"it_IT": "Dimensione file",
"ja_JP": "ファイルサイズ",
@@ -1935,7 +1935,7 @@
"pt_BR": "Status: Desativado",
"ru_RU": "Статус: Отключено",
"sv_SE": "Status: Inaktiverad",
- "th_TH": "",
+ "th_TH": "สถานะ: ถูกปิดใช้งาน",
"tr_TR": "Durum: Devre Dışı",
"uk_UA": "Статус: Вимкнено",
"zh_CN": "状态:禁用",
@@ -1958,9 +1958,9 @@
"no_NO": "Status: Stigende",
"pl_PL": "Stan: Rosnący",
"pt_BR": "Status: Crescente",
- "ru_RU": "Статус: По возрастанию",
+ "ru_RU": "Статус: По Возрастанию",
"sv_SE": "Status: Stigande",
- "th_TH": "สถานะ: เพิ่มขึ้น",
+ "th_TH": "สถานะ: เรียงจากน้อยไปมาก",
"tr_TR": "Durum: Artan",
"uk_UA": "Статус: Зростання",
"zh_CN": "状态:升序",
@@ -1985,7 +1985,7 @@
"pt_BR": "Status: Decrescente",
"ru_RU": "Статус: По Убыванию",
"sv_SE": "Status: Fallande",
- "th_TH": "สถานะ: ลดลง",
+ "th_TH": "สถานะ: เรียงจากมากไปน้อย",
"tr_TR": "Durum: Azalan",
"uk_UA": "Статус: Зменшення",
"zh_CN": "状态:降序",
@@ -2010,7 +2010,7 @@
"pt_BR": "Compatibilidade:",
"ru_RU": "Совместимость:",
"sv_SE": "Kompatibilitet:",
- "th_TH": "",
+ "th_TH": "ความเข้ากันได้:",
"tr_TR": "",
"uk_UA": "Сумісність:",
"zh_CN": "兼容性:",
@@ -2033,9 +2033,9 @@
"no_NO": "Tittel ID:",
"pl_PL": "",
"pt_BR": "ID do Título:",
- "ru_RU": "ID приложения",
+ "ru_RU": "ID приложения:",
"sv_SE": "Titel-id:",
- "th_TH": "",
+ "th_TH": "รหัสเกม:",
"tr_TR": "",
"uk_UA": "ID гри:",
"zh_CN": "标题 ID:",
@@ -2050,7 +2050,7 @@
"el_GR": "",
"en_US": "Hosted Games: {0}",
"es_ES": "",
- "fr_FR": "Jeux hébergés : {0}",
+ "fr_FR": "Jeux Hébergés : {0}",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -2060,7 +2060,7 @@
"pt_BR": "Jogos Hospedados: {0}",
"ru_RU": "Запущенно игр: {0}",
"sv_SE": "Värdskap för spel: {0}",
- "th_TH": "",
+ "th_TH": "เกมที่โฮสต์: {0}",
"tr_TR": "",
"uk_UA": "Розміщені ігри: {0}",
"zh_CN": "服务的游戏: {0}",
@@ -2075,7 +2075,7 @@
"el_GR": "",
"en_US": "Online Players: {0}",
"es_ES": "",
- "fr_FR": "Joueurs en ligne : {0}",
+ "fr_FR": "Joueurs en Ligne : {0}",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -2085,7 +2085,7 @@
"pt_BR": "Jogadores Online: {0}",
"ru_RU": "Игроков онлайн: {0}",
"sv_SE": "Online-spelare: {0}",
- "th_TH": "",
+ "th_TH": "จำนวนผู้เล่นออนไลน์: {0}",
"tr_TR": "",
"uk_UA": "Гравців онлайн: {0}",
"zh_CN": "在线玩家: {0}",
@@ -2100,7 +2100,7 @@
"el_GR": "Συνολικός χρόνος παιχνιδιού: {0}",
"en_US": "Total Play Time: {0}",
"es_ES": "Tiempo total de juego: {0}",
- "fr_FR": "Temps de jeu total: {0}",
+ "fr_FR": "Temps de Jeu Total: {0}",
"he_IL": "",
"it_IT": "Tempo totale di gioco: {0}",
"ja_JP": "",
@@ -2108,9 +2108,9 @@
"no_NO": "",
"pl_PL": "Całkowity czas gry: {0}",
"pt_BR": "Tempo total de jogo: {0}",
- "ru_RU": "",
+ "ru_RU": "Общее время игры: {0}",
"sv_SE": "Total speltid: {0}",
- "th_TH": "",
+ "th_TH": "เวลาที่เล่นทั้งหมด: {0}",
"tr_TR": "Toplam Oyun Süresi: {0}",
"uk_UA": "Всього зіграно: {0}",
"zh_CN": "总游戏时间: {0}",
@@ -2125,7 +2125,7 @@
"el_GR": "Άνοιγμα Τοποθεσίας Αποθήκευσης Χρήστη",
"en_US": "Open User Save Directory",
"es_ES": "Abrir carpeta de guardado de este usuario",
- "fr_FR": "Ouvrir le dossier de sauvegarde utilisateur",
+ "fr_FR": "Ouvrir le Dossier de Sauvegarde Utilisateur",
"he_IL": "פתח את תקיית השמור של המשתמש",
"it_IT": "Apri la cartella dei salvataggi dell'utente",
"ja_JP": "セーブディレクトリを開く",
@@ -2133,9 +2133,9 @@
"no_NO": "Åpne bruker lagrings mappe",
"pl_PL": "Otwórz katalog zapisów użytkownika",
"pt_BR": "Abrir Diretório de Saves do Usuário",
- "ru_RU": "Открыть папку с сохранениями",
+ "ru_RU": "Открыть папку сохранений",
"sv_SE": "Öppna användarkatalog för sparningar",
- "th_TH": "เปิดไดเร็กทอรี่บันทึกของผู้ใช้",
+ "th_TH": "เปิดโฟลเดอร์บันทึกข้อมูลผู้ใช้",
"tr_TR": "Kullanıcı Kayıt Dosyası Dizinini Aç",
"uk_UA": "Відкрити теку збережень користувача",
"zh_CN": "打开用户存档目录",
@@ -2150,7 +2150,7 @@
"el_GR": "Άνοιγμα Τοποθεσίας Συσκευής Χρήστη",
"en_US": "Open Device Save Directory",
"es_ES": "Abrir carpeta de guardado del sistema para el usuario actual",
- "fr_FR": "Ouvrir le dossier de sauvegarde de l’appareil",
+ "fr_FR": "Ouvrir le Dossier de Sauvegarde de l’Appareil",
"he_IL": "פתח את תקיית השמור של המכשיר",
"it_IT": "Apri la cartella dei salvataggi del dispositivo",
"ja_JP": "デバイスディレクトリを開く",
@@ -2158,7 +2158,7 @@
"no_NO": "Åpne lagringsmappe for enheten",
"pl_PL": "Otwórz katalog zapisów urządzenia",
"pt_BR": "Abrir Diretório de Saves de Dispositivo do Usuário",
- "ru_RU": "Открыть папку сохраненных устройств",
+ "ru_RU": "Открыть папку сохранений устройства",
"sv_SE": "Öppna enhetens katalog för sparade spel",
"th_TH": "เปิดไดเร็กทอรี่บันทึกของอุปกรณ์",
"tr_TR": "Kullanıcı Cihaz Dizinini Aç",
@@ -2175,7 +2175,7 @@
"el_GR": "Άνοιγμα Τοποθεσίας BCAT",
"en_US": "Open BCAT Save Directory",
"es_ES": "Abrir carpeta de guardado BCAT del usuario",
- "fr_FR": "Ouvrir le dossier de sauvegarde BCAT",
+ "fr_FR": "Ouvrir le Dossier de Sauvegarde BCAT",
"he_IL": "פתח את תקיית השמור של ה-BCAT",
"it_IT": "Apri la cartella del salvataggio BCAT",
"ja_JP": "BCATディレクトリを開く",
@@ -2183,7 +2183,7 @@
"no_NO": "Åpne BCAT lagringsmappe",
"pl_PL": "Otwórz katalog zapisu BCAT obecnego użytkownika",
"pt_BR": "Abrir Diretório de Saves BCAT do Usuário",
- "ru_RU": "Открыть папку сохраненных BCAT",
+ "ru_RU": "Открыть папку сохранений BCAT",
"sv_SE": "Öppna katalog för BCAT-sparningar",
"th_TH": "เปิดไดเรกทอรี่บันทึกของ BCAT",
"tr_TR": "Kullanıcı BCAT Dizinini Aç",
@@ -2200,7 +2200,7 @@
"el_GR": "Διαχείριση Ενημερώσεων Παιχνιδιού",
"en_US": "Manage Title Updates",
"es_ES": "Gestionar actualizaciones del juego",
- "fr_FR": "Gérer les mises à jour du titre",
+ "fr_FR": "Gérer les Mises à Jour du Titre",
"he_IL": "מנהל עדכוני משחקים",
"it_IT": "Gestisci aggiornamenti del gioco",
"ja_JP": "アップデートを管理",
@@ -2235,7 +2235,7 @@
"pt_BR": "Gerenciar DLCs",
"ru_RU": "Управление DLC",
"sv_SE": "Hantera DLC",
- "th_TH": "จัดการ DLC",
+ "th_TH": "จัดการเนื้อหาเสริม (DLC)",
"tr_TR": "DLC'leri Yönet",
"uk_UA": "Керування DLC",
"zh_CN": "管理 DLC",
@@ -2250,7 +2250,7 @@
"el_GR": "Διαχείριση Προσωρινής Μνήμης",
"en_US": "Cache Management",
"es_ES": "Gestión de caché ",
- "fr_FR": "Gestion des caches",
+ "fr_FR": "Gestion des Caches",
"he_IL": "ניהול מטמון",
"it_IT": "Gestione della cache",
"ja_JP": "キャッシュ管理",
@@ -2275,7 +2275,7 @@
"el_GR": "Εκκαθάριση Προσωρινής Μνήμης PPTC",
"en_US": "Queue PPTC Rebuild",
"es_ES": "Reconstruir PPTC en cola",
- "fr_FR": "Reconstruire le cache PPTC",
+ "fr_FR": "Reconstruire le Cache PPTC",
"he_IL": "הוסף PPTC לתור בנייה מחדש",
"it_IT": "Accoda rigenerazione della cache PPTC",
"ja_JP": "PPTC を再構築",
@@ -2283,9 +2283,9 @@
"no_NO": "Start PPTC gjenoppbygging",
"pl_PL": "Zakolejkuj rekompilację PPTC",
"pt_BR": "Reconstruir Cache PPTC",
- "ru_RU": "Перестроить очередь PPTC",
+ "ru_RU": "Перестроить PPTC",
"sv_SE": "Kölägg PPTC Rebuild",
- "th_TH": "เพิ่มคิวการสร้าง PPTC ใหม่",
+ "th_TH": "เพิ่มงานสร้าง PPTC ใหม่ลงในคิว",
"tr_TR": "PPTC Yeniden Yapılandırmasını Başlat",
"uk_UA": "Додати до черги перекомпіляцію PPTC",
"zh_CN": "清除 PPTC 缓存文件",
@@ -2300,7 +2300,7 @@
"el_GR": "Διαγράφει την προσωρινή μνήμη PPTC της εφαρμογής",
"en_US": "Trigger PPTC to rebuild at boot time on the next game launch",
"es_ES": "Elimina la caché de PPTC de esta aplicación",
- "fr_FR": "Déclencher la reconstruction du cache PPTC au prochain démarrage du jeu",
+ "fr_FR": "Déclenche la reconstruction du cache PPTC au prochain démarrage du jeu",
"he_IL": "גרום ל-PPTC להבנות מחדש בפתיחה הבאה של המשחק",
"it_IT": "Esegue la rigenerazione della cache PPTC al prossimo avvio del gioco",
"ja_JP": "次回のゲーム起動時に PPTC を再構築します",
@@ -2325,7 +2325,7 @@
"el_GR": "",
"en_US": "Purge PPTC Cache",
"es_ES": "",
- "fr_FR": "Purger le cache PPTC",
+ "fr_FR": "Purger le Cache PPTC",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -2335,38 +2335,13 @@
"pt_BR": "Limpar Cache PPTC",
"ru_RU": "Очистить кэш PPTC",
"sv_SE": "Rensa PPTC-cache",
- "th_TH": "",
+ "th_TH": "ล้างแคช PPTC",
"tr_TR": "",
"uk_UA": "Очистити кеш PPTC",
"zh_CN": "清理 PPTC 缓存",
"zh_TW": "清除 PPTC"
}
},
- {
- "ID": "GameListContextMenuCacheManagementNukePptcToolTip",
- "Translations": {
- "ar_SA": "",
- "de_DE": "",
- "el_GR": "",
- "en_US": "Deletes all PPTC cache files for the Application",
- "es_ES": "",
- "fr_FR": "Supprime tous les fichiers de cache PPTC de l’application",
- "he_IL": "",
- "it_IT": "",
- "ja_JP": "",
- "ko_KR": "앱의 모든 PPTC 캐시 파일 삭제",
- "no_NO": "Sletter alle PPTC-cache-filer for applikasjonen",
- "pl_PL": "",
- "pt_BR": "Apaga os arquivos de cache PPTC do aplicativo",
- "ru_RU": "Удаляет все файлы кэша PPTC для приложения",
- "sv_SE": "Tar bort alla PPTC-cachefiler för applikationen",
- "th_TH": "",
- "tr_TR": "",
- "uk_UA": "Видаляє всі файли кешу PPTC для застосунку",
- "zh_CN": "删除应用程序的所有 PPTC 缓存",
- "zh_TW": "清除應用程式的 PPTC"
- }
- },
{
"ID": "GameListContextMenuCacheManagementPurgeShaderCache",
"Translations": {
@@ -2375,7 +2350,7 @@
"el_GR": "Εκκαθάριση Προσωρινής Μνήμης Shader",
"en_US": "Purge Shader Cache",
"es_ES": "Limpiar caché de sombreadores",
- "fr_FR": "Purger le cache des shaders",
+ "fr_FR": "Purger le Cache des Shaders",
"he_IL": "ניקוי מטמון הצללות",
"it_IT": "Elimina la cache degli shader",
"ja_JP": "シェーダーキャッシュを破棄",
@@ -2385,38 +2360,13 @@
"pt_BR": "Limpar Cache de Shader",
"ru_RU": "Очистить кэш шейдеров",
"sv_SE": "Töm shader cache",
- "th_TH": "ล้างแคช แสงเงา",
+ "th_TH": "ล้างแคชเชเดอร์",
"tr_TR": "Shader Önbelleğini Temizle",
"uk_UA": "Очистити кеш шейдерів",
"zh_CN": "清除着色器缓存文件",
"zh_TW": "清除著色器快取"
}
},
- {
- "ID": "GameListContextMenuCacheManagementPurgeShaderCacheToolTip",
- "Translations": {
- "ar_SA": "يحذف ذاكرة مرشحات الفيديو المؤقتة الخاصة بالتطبيق",
- "de_DE": "Löscht den Shader-Cache der Anwendung",
- "el_GR": "Διαγράφει την προσωρινή μνήμη Shader της εφαρμογής",
- "en_US": "Deletes Application's shader cache",
- "es_ES": "Eliminar la caché de sombreadores de esta aplicación",
- "fr_FR": "Supprime le cache des shaders de l’application",
- "he_IL": "מוחק את מטמון ההצללות של היישום",
- "it_IT": "Elimina la cache degli shader dell'applicazione",
- "ja_JP": "アプリケーションのシェーダーキャッシュを破棄します",
- "ko_KR": "앱의 셰이더 캐시 삭제",
- "no_NO": "Sletter applikasjonens shader cache",
- "pl_PL": "Usuwa pamięć podręczną cieni danej aplikacji",
- "pt_BR": "Deleta o cache de Shader do jogo armazenado em disco",
- "ru_RU": "Удаляет кеш шейдеров приложения",
- "sv_SE": "Tar bort applikationens shader cache",
- "th_TH": "ลบแคช แสงเงา ของแอปพลิเคชัน",
- "tr_TR": "Uygulamanın shader önbelleğini temizler",
- "uk_UA": "Видаляє кеш шейдерів застосунку (гри)",
- "zh_CN": "删除游戏的着色器缓存文件,下次启动游戏时重新生成着色器缓存文件",
- "zh_TW": "清除應用程式的著色器快取檔案"
- }
- },
{
"ID": "GameListContextMenuCacheManagementOpenPptcDirectory",
"Translations": {
@@ -2425,7 +2375,7 @@
"el_GR": "Άνοιγμα Τοποθεσίας PPTC",
"en_US": "Open PPTC Directory",
"es_ES": "Abrir carpeta de PPTC",
- "fr_FR": "Ouvrir le dossier PPTC",
+ "fr_FR": "Ouvrir le Dossier PPTC",
"he_IL": "פתח את תקיית PPTC",
"it_IT": "Apri la cartella della cache PPTC",
"ja_JP": "PPTC ディレクトリを開く",
@@ -2435,7 +2385,7 @@
"pt_BR": "Abrir Diretório de Cache PPTC",
"ru_RU": "Открыть папку PPTC",
"sv_SE": "Öppna PPTC-katalog",
- "th_TH": "เปิดไดเรกทอรี่ PPTC",
+ "th_TH": "เปิดไดเรกทอรี PPTC",
"tr_TR": "PPTC Dizinini Aç",
"uk_UA": "Відкрити теку PPTC",
"zh_CN": "打开 PPTC 缓存目录",
@@ -2450,7 +2400,7 @@
"el_GR": "Άνοιγμα τοποθεσίας προσωρινής μνήμης Shader",
"en_US": "Open Shader Cache Directory",
"es_ES": "Abrir carpeta de caché de sombreadores",
- "fr_FR": "Ouvrir le dossier du cache des shaders",
+ "fr_FR": "Ouvrir le Dossier du Cache des Shaders",
"he_IL": "פתח את תקיית המטמון של ההצללות",
"it_IT": "Apri la cartella della cache degli shader",
"ja_JP": "シェーダーキャッシュディレクトリを開く",
@@ -2460,7 +2410,7 @@
"pt_BR": "Abrir Diretório do Cache de Shaders",
"ru_RU": "Открыть папку с кэшем шейдеров",
"sv_SE": "Öppna katalog för shader cache",
- "th_TH": "เปิดไดเรกทอรี่ แคช แสงเงา",
+ "th_TH": "เปิดไดเรกทอรีแคชเชเดอร์",
"tr_TR": "Shader Önbelleği Dizinini Aç",
"uk_UA": "Відкрити теку з кешем шейдерів",
"zh_CN": "打开着色器缓存目录",
@@ -2475,7 +2425,7 @@
"el_GR": "Εξαγωγή Δεδομένων",
"en_US": "Extract Data",
"es_ES": "Extraer datos",
- "fr_FR": "Extraire les données",
+ "fr_FR": "Extraire les Données",
"he_IL": "חילוץ נתונים",
"it_IT": "Estrai dati",
"ja_JP": "データを展開",
@@ -2485,7 +2435,7 @@
"pt_BR": "Extrair Dados",
"ru_RU": "Извлечь данные",
"sv_SE": "Extrahera data",
- "th_TH": "แยกส่วนข้อมูล",
+ "th_TH": "แยกข้อมูลออกมา",
"tr_TR": "Veriyi Ayıkla",
"uk_UA": "Видобути дані",
"zh_CN": "提取数据",
@@ -2525,7 +2475,7 @@
"el_GR": "Εξαγωγή της ενότητας ExeFS από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)",
"en_US": "Extract the ExeFS section from Application's current config (including updates)",
"es_ES": "Extraer la sección ExeFS de la configuración actual de la aplicación (incluyendo actualizaciones)",
- "fr_FR": "Extraire la section ExeFS de la configuration actuelle de l’application (mises à jour incluses)",
+ "fr_FR": "Extrait la section ExeFS de la configuration actuelle de l’Application (mises à jour incluses)",
"he_IL": "חלץ את קטע ה-ExeFS מתצורת היישום הנוכחית (כולל עדכונים)",
"it_IT": "Estrae la sezione ExeFS dall'attuale configurazione dell'applicazione (inclusi gli aggiornamenti)",
"ja_JP": "現在のアプリケーション設定(アップデート含む)から ExeFS セクションを展開します",
@@ -2533,9 +2483,9 @@
"no_NO": "Pakk ut ExeFS seksjonen fra Programmets gjeldende konfigurasjon (inkludert oppdateringer)",
"pl_PL": "Wyodrębnij sekcję ExeFS z bieżącej konfiguracji aplikacji (w tym aktualizacje)",
"pt_BR": "Extrai a seção ExeFS do jogo (incluindo atualizações)",
- "ru_RU": "Извлечение раздела ExeFS из текущих настроек приложения (включая обновления)",
+ "ru_RU": "Извлекает раздел ExeFS из текущей конфигурации приложения (включая обновления)",
"sv_SE": "Extrahera ExeFS-sektionen från applikationens aktuella konfiguration (inkl uppdateringar)",
- "th_TH": "แยกส่วน ExeFS ออกจากการตั้งค่าปัจจุบันของแอปพลิเคชัน (รวมถึงอัปเดต)",
+ "th_TH": "แยกข้อมูลส่วน ExeFS จากคอนฟิกปัจจุบันของแอป (รวมถึงอัปเดต)",
"tr_TR": "Uygulamanın geçerli yapılandırmasından ExeFS kısmını ayıkla (Güncellemeler dahil)",
"uk_UA": "Видобуває розділ ExeFS із поточної конфігурації програми (включаючи оновлення)",
"zh_CN": "从游戏的当前状态中提取 ExeFS 分区 (包括更新)",
@@ -2575,7 +2525,7 @@
"el_GR": "Εξαγωγή της ενότητας RomFS από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)",
"en_US": "Extract the RomFS section from Application's current config (including updates)",
"es_ES": "Extraer la sección RomFS de la configuración actual de la aplicación (incluyendo actualizaciones)",
- "fr_FR": "Extraire la section RomFS de la configuration actuelle de l’application (mises à jour incluses)",
+ "fr_FR": "Extrait la section RomFS de la configuration actuelle de l’Application (mises à jour incluses)",
"he_IL": "חלץ את קטע ה-RomFS מתצורת היישום הנוכחית (כולל עדכונים)",
"it_IT": "Estrae la sezione RomFS dall'attuale configurazione dell'applicazione (inclusi gli aggiornamenti)",
"ja_JP": "現在のアプリケーション設定(アップデート含む)から RomFS セクションを展開します",
@@ -2583,9 +2533,9 @@
"no_NO": "Pakk ut RomFS seksjonen fra applikasjonens gjeldende konfigurasjon (inkludert oppdateringer)",
"pl_PL": "Wyodrębnij sekcję RomFS z bieżącej konfiguracji aplikacji (w tym aktualizacje)",
"pt_BR": "Extrai a seção RomFS do jogo (incluindo atualizações)",
- "ru_RU": "Извлечение раздела RomFS из текущих настроек приложения (включая обновления)",
+ "ru_RU": "Извлекает раздела RomFS из текущих настроек приложения (включая обновления)",
"sv_SE": "Extrahera RomFS-sektionen från applikationens aktuella konfiguration (inkl uppdateringar)",
- "th_TH": "แยกส่วน RomFS ออกจากการตั้งค่าปัจจุบันของแอปพลิเคชัน (รวมถึงอัพเดต)",
+ "th_TH": "แยกข้อมูลส่วน RomFS จากคอนฟิกปัจจุบันของแอป (รวมถึงอัปเดต)",
"tr_TR": "Uygulamanın geçerli yapılandırmasından RomFS kısmını ayıkla (Güncellemeler dahil)",
"uk_UA": "Видобуває розділ RomFS із поточної конфігурації застосунку (включно з оновленнями)",
"zh_CN": "从游戏的当前状态中提取 RomFS 分区 (包括更新)",
@@ -2608,13 +2558,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -2625,7 +2575,7 @@
"el_GR": "",
"en_US": "Extract the RomFS from a selected DLC file",
"es_ES": "",
- "fr_FR": "Extraire la RomFS du fichier DLC sélectionné",
+ "fr_FR": "Extrait la RomFS du fichier DLC sélectionné",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -2635,7 +2585,7 @@
"pt_BR": "Extraia o RomFS de um arquivo DLC selecionado",
"ru_RU": "Извлекает файлы RomFS из выбранного файла DLC",
"sv_SE": "Extrahera RomFS från en vald DLC-fil",
- "th_TH": "",
+ "th_TH": "แยกข้อมูล RomFS จากไฟล์ DLC ที่เลือก",
"tr_TR": "",
"uk_UA": "Витягти RomFS з обраного файлу DLC",
"zh_CN": "从选定的 DLC 文件中解压 RomFS",
@@ -2650,7 +2600,7 @@
"el_GR": "Λογότυπο",
"en_US": "Logo",
"es_ES": "Logotipo",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "ロゴ",
@@ -2658,7 +2608,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "Logotipo",
- "ru_RU": "Лого",
+ "ru_RU": "Логотип",
"sv_SE": "Logotyp",
"th_TH": "โลโก้",
"tr_TR": "Simge",
@@ -2675,7 +2625,7 @@
"el_GR": "Εξαγωγή της ενότητας Logo από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)",
"en_US": "Extract the Logo section from Application's current config (including updates)",
"es_ES": "Extraer la sección Logo de la configuración actual de la aplicación (incluyendo actualizaciones)",
- "fr_FR": "Extraire la section Logo de la configuration actuelle de l’application (mises à jour incluses)",
+ "fr_FR": "Extrait la section Logo de la configuration actuelle de l’application (mises à jour incluses)",
"he_IL": "חלץ את קטע ה-Logo מתצורת היישום הנוכחית (כולל עדכונים)",
"it_IT": "Estrae la sezione Logo dall'attuale configurazione dell'applicazione (inclusi gli aggiornamenti)",
"ja_JP": "現在のアプリケーション設定(アップデート含む)からロゴセクションを展開します",
@@ -2683,9 +2633,9 @@
"no_NO": "Pakk ut Logo-seksjonen fra applikasjonens gjeldende konfigurasjon (inkludert oppdateringer)",
"pl_PL": "Wyodrębnij sekcję z logiem z bieżącej konfiguracji aplikacji (w tym aktualizacje)",
"pt_BR": "Extrai a seção Logo do jogo (incluindo atualizações)",
- "ru_RU": "Извлечение раздела с логотипом из текущих настроек приложения (включая обновления)",
+ "ru_RU": "Извлекает раздел с логотипом из текущих настроек приложения (включая обновления)",
"sv_SE": "Extrahera Logo-sektionen från applikationens aktuella konfiguration (inkl uppdateringar)",
- "th_TH": "แยกส่วน โลโก้ ออกจากการตั้งค่าปัจจุบันของแอปพลิเคชัน (รวมถึงอัปเดต)",
+ "th_TH": "แยกข้อมูลส่วนโลโก้จากคอนฟิกปัจจุบันของแอป (รวมถึงอัปเดต)",
"tr_TR": "Uygulamanın geçerli yapılandırmasından Logo kısmını ayıkla (Güncellemeler dahil)",
"uk_UA": "Видобуває розділ логотипу з поточної конфігурації програми (включаючи оновлення)",
"zh_CN": "从游戏的当前状态中提取图标 (包括更新)",
@@ -2700,7 +2650,7 @@
"el_GR": "Δημιουργία Συντόμευσης Εφαρμογής",
"en_US": "Create Application Shortcut",
"es_ES": "Crear acceso directo de aplicación",
- "fr_FR": "Créer un raccourci de l’application",
+ "fr_FR": "Créer un Raccourci de l’Application",
"he_IL": "ליצור קיצור דרך לאפליקציה",
"it_IT": "Crea collegamento",
"ja_JP": "アプリケーションのショートカットを作成",
@@ -2708,7 +2658,7 @@
"no_NO": "Lag programsnarvei",
"pl_PL": "Utwórz skrót aplikacji",
"pt_BR": "Criar Atalho da Aplicação",
- "ru_RU": "Создать ярлык приложения",
+ "ru_RU": "Создать ярлык",
"sv_SE": "Skapa genväg till applikation",
"th_TH": "สร้างทางลัดของแอปพลิเคชัน",
"tr_TR": "Uygulama Kısayolu Oluştur",
@@ -2725,7 +2675,7 @@
"el_GR": "Δημιουργία συντόμευσης επιφάνειας εργασίας που ανοίγει την επιλεγμένη εφαρμογή",
"en_US": "Create a Desktop Shortcut that launches the selected Application",
"es_ES": "Crear un acceso directo en el escritorio que lance la aplicación seleccionada",
- "fr_FR": "Créer un raccourci sur le bureau qui lance l’application sélectionnée",
+ "fr_FR": "Crée un Raccourci sur le Bureau qui lance l’Application sélectionnée",
"he_IL": "ליצור קיצור דרך בשולחן העבודה שיפתח את אפליקציה זו",
"it_IT": "Crea un collegamento sul desktop che avvia l'applicazione selezionata",
"ja_JP": "選択したアプリケーションを起動するデスクトップショートカットを作成します",
@@ -2733,9 +2683,9 @@
"no_NO": "Lag en snarvei på skrivebordet som starter den valgte Applikasjonen",
"pl_PL": "Utwórz skrót na pulpicie, który uruchamia wybraną aplikację",
"pt_BR": "Criar um atalho na área de trabalho que inicia o aplicativo selecionado",
- "ru_RU": "Создает ярлык на рабочем столе, с помощью которого можно запустить игру или приложение",
+ "ru_RU": "Создаёт ярлык на рабочем столе для запуска выбранного приложения",
"sv_SE": "Skapa en skrivbordsgenväg som startar vald applikation",
- "th_TH": "สร้างทางลัดบนเดสก์ท็อปสำหรับใช้แอปพลิเคชันที่เลือก",
+ "th_TH": "สร้างทางลัดบนเดสก์ท็อปเพื่อเปิดแอปพลิเคชันที่เลือก",
"tr_TR": "Seçilmiş uygulamayı çalıştıracak bir masaüstü kısayolu oluştur",
"uk_UA": "Створити ярлик на робочому столі, який запускатиме вибраний застосунок (гру)",
"zh_CN": "创建一个直接启动此游戏的桌面快捷方式",
@@ -2750,7 +2700,7 @@
"el_GR": "",
"en_US": "Create Custom Configuration",
"es_ES": "",
- "fr_FR": "Créer une configuration personnalisée",
+ "fr_FR": "Créer une Configuration Personnalisée",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -2758,9 +2708,9 @@
"no_NO": "Opprett egendefinert konfigurasjon",
"pl_PL": "",
"pt_BR": "Criar Configuração Custumizada",
- "ru_RU": "Задать индивидуальные параметры",
+ "ru_RU": "Создать индивидуальную конфигурацию",
"sv_SE": "Skapa anpassad konfiguration",
- "th_TH": "",
+ "th_TH": "สร้างการตั้งค่าที่กำหนดเอง",
"tr_TR": "",
"uk_UA": "Створити користувацьку конфігурацію",
"zh_CN": "创建自定义设置",
@@ -2775,7 +2725,7 @@
"el_GR": "",
"en_US": "Edit Custom Configuration",
"es_ES": "",
- "fr_FR": "Modifier la configuration personnalisée",
+ "fr_FR": "Modifier la Configuration Personnalisée",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -2783,9 +2733,9 @@
"no_NO": "Rediger egendefinert konfigurasjon",
"pl_PL": "",
"pt_BR": "Editar Configuração Customizada",
- "ru_RU": "Изменить индивидуальные параметры",
+ "ru_RU": "Изменить индивидуальную конфигурацию",
"sv_SE": "Redigera anpassad konfiguration",
- "th_TH": "",
+ "th_TH": "แก้ไขการตั้งค่าที่กำหนดเอง",
"tr_TR": "",
"uk_UA": "Редагувати користувацьку конфігурацію",
"zh_CN": "编辑自定义设置",
@@ -2800,7 +2750,7 @@
"el_GR": "",
"en_US": "Create a shortcut in macOS's Applications folder that launches the selected Application",
"es_ES": "Crea un acceso directo en la carpeta de Aplicaciones de macOS que inicie la Aplicación seleccionada",
- "fr_FR": "Créer un raccourci dans le dossier Applications de macOS qui lance l’application sélectionnée",
+ "fr_FR": "Crée un raccourci dans le dossier Applications de macOS qui lance l’Application sélectionnée",
"he_IL": "ליצור קיצור דרך בתיקיית האפליקציות של macOS שיפתח את אפליקציה זו",
"it_IT": "Crea un collegamento nella cartella Applicazioni di macOS che avvia l'applicazione selezionata",
"ja_JP": "選択したアプリケーションを起動する ショートカットを macOS の Applications フォルダに作成します",
@@ -2808,15 +2758,65 @@
"no_NO": "Lag snarvei i macOSs Program-mappen som starter det valgte programmet",
"pl_PL": "Utwórz skrót w folderze 'Aplikacje' w systemie macOS, który uruchamia wybraną aplikację",
"pt_BR": "Crie um atalho na pasta Aplicativos do macOS que abre o Aplicativo selecionado",
- "ru_RU": "Создает ярлык игры или приложения в папке Программы macOS",
+ "ru_RU": "Создаёт ярлык в папке Программы macOS, который запускает выбранное приложение",
"sv_SE": "Skapa en genväg i macOS-programmapp som startar vald applikation",
- "th_TH": "สร้างทางลัดในโฟลเดอร์ Applications ของ macOS สำหรับใช้แอปพลิเคชันที่เลือก",
+ "th_TH": "สร้างทางลัดในโฟลเดอร์ Applications ของ macOS เพื่อเปิดแอปพลิเคชันที่เลือก",
"tr_TR": "",
"uk_UA": "Створити ярлик у каталозі програм macOS, що запускатиме обраний застосунок (гру)",
"zh_CN": "在 macOS 的应用程序目录中创建一个直接启动此游戏的快捷方式",
"zh_TW": "在 macOS 的應用程式資料夾中建立捷徑,啟動選取的應用程式"
}
},
+ {
+ "ID": "GameListContextMenuShowCompatEntry",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Show Compatibility Entry",
+ "es_ES": "",
+ "fr_FR": "Afficher l’Entrée de Compatibilité",
+ "he_IL": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "호환성 항목 표시",
+ "no_NO": "Vis kompatibilitetsoppføring",
+ "pl_PL": "",
+ "pt_BR": "Mostrar Dados de Compatibilidade",
+ "ru_RU": "Запись о совместимости",
+ "sv_SE": "Visa kompatibilitetspost",
+ "th_TH": "แสดงรายการความเข้ากันได้",
+ "tr_TR": "",
+ "uk_UA": "Iнформація про сумісність",
+ "zh_CN": "显示兼容性项目",
+ "zh_TW": "顯示相容性資訊"
+ }
+ },
+ {
+ "ID": "GameListContextMenuShowCompatEntryToolTip",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Show the selected game in the Compatibility List you can normally access 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": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "일반적으로 도움말 메뉴를 통해 접근할 수 있는 호환성 목록에 선택한 게임을 표시합니다.",
+ "no_NO": "Vis det valgte spillet i kompatibilitetslisten, som du vanligvis får tilgang til via Hjelp-menyen.",
+ "pl_PL": "",
+ "pt_BR": "Exibe o jogo selecionado na Lista de Compatibilidade, que normalmente pode ser acessada pelo menu Ajuda.",
+ "ru_RU": "Отобразить выбранную игру в списке совместимости, которой обычно доступен через меню Помощь.",
+ "sv_SE": "Visa valt spel i kompatibilitetslistan som du normalt sett kan komma åt via hjälpmenyn.",
+ "th_TH": "แสดงเกมที่เลือกในรายการความเข้ากันได้ ซึ่งปกติคุณสามารถเข้าถึงได้ผ่านเมนูช่วยเหลือ",
+ "tr_TR": "",
+ "uk_UA": "Показати цю гру в Списку Сумісності. Список сумісності також можна зайти в меню Довідки.",
+ "zh_CN": "在兼容性列表中显示选定的游戏,您通常可以通过帮助菜单访问。",
+ "zh_TW": "在相容性列表中顯示已選擇的遊戲。你也可以透過「說明」選單開啟。"
+ }
+ },
{
"ID": "CreateCustomConfigurationToolTip",
"Translations": {
@@ -2833,7 +2833,7 @@
"no_NO": "Oppretter en uavhengig konfigurasjon for det gjeldende spillet",
"pl_PL": "Tworzy niezależną konfigurację dla bieżącej gry",
"pt_BR": "Cria uma configuração independente para o jogo atual",
- "ru_RU": "Создает независимую конфигурацию для текущей игры",
+ "ru_RU": "Создаёт независимую конфигурацию для выбранной игры",
"sv_SE": "Skapar en oberoende konfiguration för det aktuella spelet",
"th_TH": "สร้างการกำหนดค่าที่เป็นอิสระสำหรับเกมปัจจุบัน",
"tr_TR": "Mevcut oyun için bağımsız bir yapılandırma oluşturur",
@@ -2850,7 +2850,7 @@
"el_GR": "",
"en_US": "Edit your existing independent configuration for the selected game",
"es_ES": "",
- "fr_FR": "Modifier votre configuration indépendante existante pour le jeu sélectionné",
+ "fr_FR": "Modifie votre configuration indépendante existante pour le jeu sélectionné",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -2858,65 +2858,15 @@
"no_NO": "Rediger din eksisterende uavhengige konfigurasjon for det valgte spillet",
"pl_PL": "",
"pt_BR": "Editar sua configuração independente existente para o jogo selecionado",
- "ru_RU": "Отредактировать существующие независимые параметры для выбранной игры.",
+ "ru_RU": "Изменить существующую независимую конфигурацию выбранной игры",
"sv_SE": "Redigera din befintliga oberoende konfiguration för det valda spelet",
- "th_TH": "",
+ "th_TH": "แสดงรายละเอียดเกม",
"tr_TR": "",
"uk_UA": "Відредагувати наявну індивідуальну конфігурацію для цієї гри.",
"zh_CN": "编辑选定游戏的现存独立配置",
"zh_TW": "為已選擇的遊戲編輯遊戲獨立自訂 (game-specific) 的設定檔"
}
},
- {
- "ID": "GameListContextMenuShowCompatEntry",
- "Translations": {
- "ar_SA": "",
- "de_DE": "",
- "el_GR": "",
- "en_US": "Show Compatibility Entry",
- "es_ES": "",
- "fr_FR": "Afficher l’entrée de compatibilité",
- "he_IL": "",
- "it_IT": "",
- "ja_JP": "",
- "ko_KR": "호환성 항목 표시",
- "no_NO": "Vis kompatibilitetsoppføring",
- "pl_PL": "",
- "pt_BR": "Mostrar Dados de Compatibilidade",
- "ru_RU": "Показать записи о совместимости",
- "sv_SE": "Visa kompatibilitetspost",
- "th_TH": "",
- "tr_TR": "",
- "uk_UA": "Iнформація про сумісність",
- "zh_CN": "显示兼容性项目",
- "zh_TW": "顯示相容性資訊"
- }
- },
- {
- "ID": "GameListContextMenuShowCompatEntryToolTip",
- "Translations": {
- "ar_SA": "",
- "de_DE": "",
- "el_GR": "",
- "en_US": "Show the selected game in the Compatibility List you can normally access via the Help menu.",
- "es_ES": "",
- "fr_FR": "Afficher le jeu sélectionné dans la liste de compatibilité accessible normalement via le menu Aide.",
- "he_IL": "",
- "it_IT": "",
- "ja_JP": "",
- "ko_KR": "일반적으로 도움말 메뉴를 통해 접근할 수 있는 호환성 목록에 선택한 게임을 표시합니다.",
- "no_NO": "Vis det valgte spillet i kompatibilitetslisten, som du vanligvis får tilgang til via Hjelp-menyen.",
- "pl_PL": "",
- "pt_BR": "Exibe o jogo selecionado na Lista de Compatibilidade, que normalmente pode ser acessada pelo menu Ajuda.",
- "ru_RU": "Отобразить выбранную игру в списке совместимости, доступ к которому вы обычно можете получить через меню Справки.",
- "sv_SE": "Visa valt spel i kompatibilitetslistan som du normalt sett kan komma åt via hjälpmenyn.",
- "th_TH": "",
- "tr_TR": "",
- "uk_UA": "Показати цю гру в Списку Сумісності. Список сумісності також можна зайти в меню Довідки.",
- "zh_CN": "在兼容性列表中显示选定的游戏,您通常可以通过帮助菜单访问。",
- "zh_TW": "在相容性列表中顯示已選擇的遊戲。你也可以透過「說明」選單開啟。"
- }
- },
{
"ID": "GameListContextMenuShowGameData",
"Translations": {
@@ -2925,7 +2875,7 @@
"el_GR": "",
"en_US": "Show Game Info",
"es_ES": "",
- "fr_FR": "Afficher les informations du jeu",
+ "fr_FR": "Afficher les Informations du Jeu",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -2933,9 +2883,9 @@
"no_NO": "Vis Spill Info",
"pl_PL": "",
"pt_BR": "Mostrar Informações do Jogo",
- "ru_RU": "Показать информацию об игре",
+ "ru_RU": "Информация об игре",
"sv_SE": "Visa spelinformation",
- "th_TH": "",
+ "th_TH": "แสดงสถิติและรายละเอียดของเกมที่เลือกอยู่ในขณะนี้",
"tr_TR": "",
"uk_UA": "Інформація про гру",
"zh_CN": "显示游戏信息",
@@ -2950,7 +2900,7 @@
"el_GR": "",
"en_US": "Open Mods Directory",
"es_ES": "Abrir Directorio de Mods",
- "fr_FR": "Ouvrir le dossier des mods",
+ "fr_FR": "Ouvrir le Dossier des Mods",
"he_IL": "פתח תיקיית מודים",
"it_IT": "Apri la cartella delle mod",
"ja_JP": "Modディレクトリを開く",
@@ -2975,7 +2925,7 @@
"el_GR": "",
"en_US": "Open Atmosphere Mods Directory",
"es_ES": "Abrir Directorio de Mods de Atmosphere",
- "fr_FR": "Ouvrir le dossier des mods 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 ディレクトリを開く",
@@ -3000,7 +2950,7 @@
"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.",
+ "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 データに有用です.",
@@ -3008,9 +2958,9 @@
"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-карте, которая содержит моды для приложений и игр. Полезно для модов, сделанных для реальной консоли.",
+ "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 สำรองซึ่งมี Mods ของแอปพลิเคชัน ซึ่งมีประโยชน์สำหรับ Mods ที่บรรจุมากับฮาร์ดแวร์จริง",
+ "th_TH": "เปิดโฟลเดอร์ Atmosphere บนการ์ด SD ทางเลือกที่เก็บม็อดของแอปพลิเคชัน ใช้สำหรับม็อดที่จัดเตรียมมาเพื่อฮาร์ดแวร์จริง",
"tr_TR": "",
"uk_UA": "Відкриває альтернативну теку SD-карти Atmosphere, що містить модифікації до застосунків або ігор. Корисно для модифікацій, зроблених для реального обладнання.",
"zh_CN": "打开存放适用于大气层系统的游戏 MOD 的目录,对于为真实硬件打包的 MOD 非常有用",
@@ -3025,7 +2975,7 @@
"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",
+ "fr_FR": "Vérifier et Réduire le Fichier XCI",
"he_IL": "",
"it_IT": "Controlla e riduci la dimensione del file XCI",
"ja_JP": "",
@@ -3035,7 +2985,7 @@
"pt_BR": "Verificar e Reduzir o Arquivo XCI",
"ru_RU": "Проверить и обрезать XCI файл",
"sv_SE": "Kontrollera och optimera XCI-fil",
- "th_TH": "",
+ "th_TH": "ตรวจสอบและลดขนาดไฟล์ XCI",
"tr_TR": "",
"uk_UA": "Перевірка та нарізка XCI Файлу",
"zh_CN": "检查并瘦身 XCI 文件",
@@ -3050,7 +3000,7 @@
"el_GR": "",
"en_US": "Check and Trim XCI File to Save Disk Space",
"es_ES": "Verificar y recortar archivo XCI para ahorrar espacio en disco",
- "fr_FR": "Vérifier et réduire le fichier XCI pour économiser de l’espace disque",
+ "fr_FR": "Vérifier et Réduire le Fichier XCI pour Économiser de l’Espace Disque",
"he_IL": "",
"it_IT": "Controlla e riduci la dimensione del file XCI per risparmiare spazio su disco",
"ja_JP": "",
@@ -3058,9 +3008,9 @@
"no_NO": "Kontroller og trimm XCI-filen for å spare diskplass",
"pl_PL": "",
"pt_BR": "Verifique e reduza o arquivo XCI para economizar espaço em disco",
- "ru_RU": "Проверить и обрезать XCI файл для уменьшения его размера",
+ "ru_RU": "Проверить и обрезать XCI файл для экономии места на диске",
"sv_SE": "Kontrollera och optimera XCI-fil för att spara diskutrymme",
- "th_TH": "",
+ "th_TH": "ตรวจสอบและลดขนาดไฟล์ XCI เพื่อประหยัดเนื้อที่เก็บข้อมูล",
"tr_TR": "",
"uk_UA": "Перевірити та обрізати XCI Файл задля збереження місця на диску",
"zh_CN": "检查并瘦身 XCI 文件以节约磁盘空间",
@@ -3075,7 +3025,7 @@
"el_GR": "{0}/{1} Φορτωμένα Παιχνίδια",
"en_US": "{0}/{1} Games Loaded",
"es_ES": "{0}/{1} juegos cargados",
- "fr_FR": "{0}/{1} Jeux chargés",
+ "fr_FR": "{0}/{1} Jeux Chargés",
"he_IL": "{1}/{0} משחקים נטענו",
"it_IT": "{0}/{1} giochi caricati",
"ja_JP": "{0}/{1} ゲーム",
@@ -3085,7 +3035,7 @@
"pt_BR": "{0}/{1} Jogos Carregados",
"ru_RU": "{0}/{1} игр загружено",
"sv_SE": "{0}/{1} spel inlästa",
- "th_TH": "เกมส์โหลดแล้ว {0}/{1}",
+ "th_TH": "โหลดเกมแล้ว {0} จากทั้งหมด {1} เกม",
"tr_TR": "{0}/{1} Oyun Yüklendi",
"uk_UA": "{0}/{1} ігор завантажено",
"zh_CN": "{0}/{1} 游戏加载完成",
@@ -3100,7 +3050,7 @@
"el_GR": "",
"en_US": "Firmware Version: {0}",
"es_ES": "",
- "fr_FR": "Version du firmware: {0}",
+ "fr_FR": "Version du Firmware: {0}",
"he_IL": "",
"it_IT": "Versione firmware: {0}",
"ja_JP": "",
@@ -3110,7 +3060,7 @@
"pt_BR": "Versão do Firmware: {0}",
"ru_RU": "Версия прошивки: {0}",
"sv_SE": "Firmware-version: {0}",
- "th_TH": "",
+ "th_TH": "เวอร์ชันเฟิร์มแวร์: {0}",
"tr_TR": "",
"uk_UA": "Версія прошивки: {0}",
"zh_CN": "系统固件版本:{0}",
@@ -3125,7 +3075,7 @@
"el_GR": "",
"en_US": "Trimming XCI File '{0}'",
"es_ES": "Recortando el siguiente archivo XCI: '{0}'",
- "fr_FR": "Réduction du fichier XCI '{0}'",
+ "fr_FR": "Réduction du Fichier XCI '{0}'",
"he_IL": "",
"it_IT": "Riduzione della dimensione del file XCI '{0}'",
"ja_JP": "",
@@ -3135,7 +3085,7 @@
"pt_BR": "Reduzindo o Arquivo XCI '{0}'",
"ru_RU": "Обрезается XCI файл '{0}'",
"sv_SE": "Optimerar XCI-filen '{0}'",
- "th_TH": "",
+ "th_TH": "กำลังลดขนาดไฟล์ XCI '{0}'",
"tr_TR": "",
"uk_UA": "Обрізається XCI Файлів '{0}'",
"zh_CN": "正在瘦身 XCI 文件 '{0}'",
@@ -3158,9 +3108,9 @@
"no_NO": "Lav grense for minnetildelinger oppdaget",
"pl_PL": "Wykryto niski limit dla przypisań pamięci",
"pt_BR": "Detectado limite baixo para mapeamentos de memória",
- "ru_RU": "Обнаружен низкий лимит разметки памяти",
+ "ru_RU": "Обнаружен низкий предел для отображений памяти",
"sv_SE": "Låg gräns för minnesmappningar upptäcktes",
- "th_TH": "การตั้งค่าหน่วยความถึงขีดจำกัดต่ำสุดแล้ว",
+ "th_TH": "ตรวจพบขีดจำกัดต่ำสำหรับการแมปหน่วยความจำ",
"tr_TR": "Bellek Haritaları İçin Düşük Limit Tespit Edildi ",
"uk_UA": "Виявлено низьку межу для відображення памʼяті",
"zh_CN": "检测到操作系统内存映射最大数量被设置的过低",
@@ -3183,9 +3133,9 @@
"no_NO": "Ønsker du å øke verdien av vm.max_map_count til {0}",
"pl_PL": "Czy chcesz zwiększyć wartość vm.max_map_count do {0}",
"pt_BR": "Você gostaria de aumentar o valor de vm.max_map_count para {0}",
- "ru_RU": "Хотите увеличить значение vm.max_map_count до {0}",
+ "ru_RU": "Хотите увеличить значение vm.max_map_count до {0}?",
"sv_SE": "Vill du öka värdet för vm.max_map_count till {0}",
- "th_TH": "คุณต้องเพิ่มค่า vm.max_map_count ไปยัง {0}",
+ "th_TH": "คุณต้องการเพิ่มค่าของ vm.max_map_count เป็น {0} หรือไม่?",
"tr_TR": "vm.max_map_count değerini {0} sayısına yükseltmek ister misiniz",
"uk_UA": "Бажаєте збільшити значення vm.max_map_count до {0}",
"zh_CN": "你想要将操作系统 vm.max_map_count 的值增加到 {0} 吗",
@@ -3208,9 +3158,9 @@
"no_NO": "Noen spill kan prøve å lage flere minnekartlegging enn det som er tillatt. Ryujinx vil krasjes så snart denne grensen overskrides.",
"pl_PL": "Niektóre gry mogą próbować przypisać sobie więcej pamięci niż obecnie, jest to dozwolone. Ryujinx ulegnie awarii, gdy limit zostanie przekroczony.",
"pt_BR": "Alguns jogos podem tentar criar mais mapeamentos de memória do que o atualmente permitido. Ryujinx irá falhar assim que este limite for excedido.",
- "ru_RU": "Некоторые игры могут создавать большую разметку памяти, чем разрешено на данный момент по умолчанию. Ryujinx вылетит при превышении этого лимита.",
+ "ru_RU": "Некоторые игры могут пытаться создавать больше отображений памяти, чем разрешено в данный момент. Ryujinx аварийно завершит работу, как только этот предел будет превышен.",
"sv_SE": "Vissa spel kan försöka att skapa fler minnesmappningar än vad som tillåts. Ryujinx kommer att krascha så snart som denna gräns överstigs.",
- "th_TH": "บางเกมอาจพยายามใช้งานหน่วยความจำมากกว่าที่ได้รับอนุญาตในปัจจุบัน Ryujinx จะปิดตัวลงเมื่อเกินขีดจำกัดนี้",
+ "th_TH": "บางเกมอาจพยายามสร้างการแมปหน่วยความจำมากกว่าที่ระบบอนุญาตในขณะนี้ หากเกินขีดจำกัดนี้ Ryujinx จะหยุดทำงานทันที",
"tr_TR": "Bazı oyunlar şu an izin verilen bellek haritası limitinden daha fazlasını yaratmaya çalışabilir. Ryujinx bu limitin geçildiği takdirde kendini kapatıcaktır.",
"uk_UA": "Деякі ігри можуть спробувати створити більше відображень памʼяті, ніж це дозволено зараз. Ryujinx закриється (крашнеться), щойно цей ліміт буде перевищено.",
"zh_CN": "有些游戏可能会尝试创建超过当前系统允许的内存映射最大数量,若超过当前最大数量,Ryujinx 模拟器将会闪退。",
@@ -3235,7 +3185,7 @@
"pt_BR": "Sim, até a próxima reinicialização",
"ru_RU": "Да, до следующего перезапуска",
"sv_SE": "Ja, tills nästa omstart",
- "th_TH": "ใช่, จนกว่าจะรีสตาร์ทครั้งถัดไป",
+ "th_TH": "ใช่, จนกว่าจะรีสตาร์ทเครื่องครั้งถัดไป",
"tr_TR": "Evet, bir sonraki yeniden başlatmaya kadar",
"uk_UA": "Так, до наст. перезапуску",
"zh_CN": "确定,临时保存(重启后失效)",
@@ -3260,7 +3210,7 @@
"pt_BR": "Sim, permanentemente",
"ru_RU": "Да, постоянно",
"sv_SE": "Ja, permanent",
- "th_TH": "ใช่, อย่างถาวร",
+ "th_TH": "ใช่, ตลอดไป",
"tr_TR": "Evet, kalıcı olarak",
"uk_UA": "Так, постійно",
"zh_CN": "确定,永久保存",
@@ -3283,9 +3233,9 @@
"no_NO": "Den maksimale mengden Minnetilordninger er lavere enn anbefalt.",
"pl_PL": "Maksymalna ilość przypisanej pamięci jest mniejsza niż zalecana.",
"pt_BR": "A quantidade máxima de mapeamentos de memória é menor que a recomendada.",
- "ru_RU": "Максимальная разметка памяти меньше, чем рекомендуется.",
+ "ru_RU": "Максимальное количество отображений памяти ниже рекомендуемого.",
"sv_SE": "Maximal mängd minnesmappningar är lägre än rekommenderat.",
- "th_TH": "จำนวนสูงสุดของการจัดการหน่วยความจำ ต่ำกว่าที่แนะนำ",
+ "th_TH": "ขีดจำกัดสูงสุดของการแมปหน่วยความจำ ต่ำกว่าค่าที่แนะนำ",
"tr_TR": "İzin verilen maksimum bellek haritası değeri tavsiye edildiğinden daha düşük. ",
"uk_UA": "Максимальний обсяг виділеної пам'яті менший за рекомендований.",
"zh_CN": "内存映射的最大数量低于推荐值。",
@@ -3308,9 +3258,9 @@
"no_NO": "Gjeldende verdi av vm.max_map_count ({0}) er lavere enn {1}. Noen spill kan prøve å lage flere minnedelinger enn det som er tillatt. Ryujinx vil kræsje så snart denne grensen overskrides.\n\nDet kan hende du ønsker å enten øke grensen eller installere pkexec manuelt, slik at Ryujinx kan hjelpe til med det.",
"pl_PL": "Obecna wartość vm.max_map_count ({0}) jest mniejsza niż {1}. Niektóre gry mogą próbować stworzyć więcej mapowań pamięci niż obecnie jest to dozwolone. Ryujinx napotka crash, gdy dojdzie do takiej sytuacji.\n\nMożesz chcieć ręcznie zwiększyć limit lub zainstalować pkexec, co pozwala Ryujinx na pomoc w tym zakresie.",
"pt_BR": "O valor atual de vm.max_map_count ({0}) é menor que {1}. Alguns jogos podem tentar criar mais mapeamentos de memória do que o permitido no momento. Ryujinx vai falhar assim que este limite for excedido.\n\nTalvez você queira aumentar o limite manualmente ou instalar pkexec, o que permite que Ryujinx ajude com isso.",
- "ru_RU": "Текущее значение vm.max_map_count ({0}) меньше, чем {1}. Некоторые игры могут попытаться создать большую разметку памяти, чем разрешено в данный момент. Ryujinx вылетит как только этот лимит будет превышен.\n\nВозможно, вам потребуется вручную увеличить лимит или установить pkexec, что позволит Ryujinx помочь справиться с превышением лимита.",
+ "ru_RU": "Текущее значение vm.max_map_count ({0}) меньше чем {1}. Некоторые игры могут пытаться создавать больше отображений памяти, чем разрешено в данный момент. Ryujinx аварийно завершит работу, как только этот лимит будет превышен.\n\nВы можете либо вручную увеличить этот лимит, либо установить pkexec, который позволит Ryujinx помочь с этим.",
"sv_SE": "Det aktuella värdet för vm.max_map_count ({0}) är lägre än {1}. Vissa spel kan försöka att skapa fler minnesmappningar än vad som tillåts. Ryujinx kommer att krascha så snart som denna gräns överstigs.\n\nDu kanske vill manuellt öka gränsen eller installera pkexec, vilket tillåter att Ryujinx hjälper till med det.",
- "th_TH": "ค่าปัจจุบันของ vm.max_map_count ({0}) มีค่าต่ำกว่า {1} บางเกมอาจพยายามใช้หน่วยความจำมากกว่าที่ได้รับอนุญาตในปัจจุบัน Ryujinx จะปิดตัวลงเมื่อเกินขีดจำกัดนี้\n\nคุณอาจต้องการตั้งค่าเพิ่มขีดจำกัดด้วยตนเองหรือติดตั้ง pkexec ซึ่งอนุญาตให้ Ryujinx ช่วยเหลือคุณได้",
+ "th_TH": "ค่าปัจจุบันของ vm.max_map_count ({0}) ต่ำกว่า {1} บางเกมอาจพยายามสร้างการแมปหน่วยความจำมากกว่าที่ระบบอนุญาตไว้ในขณะนี้ หากเกินขีดจำกัดนี้ Ryujinx จะเกิดข้อผิดพลาดและปิดตัวเองทันที คุณอาจต้องเพิ่มค่าขีดจำกัดนี้ด้วยตนเอง หรือจะติดตั้งโปรแกรม pkexec เพื่อให้ Ryujinx ช่วยจัดการให้ก็ได้",
"tr_TR": "Şu anki vm.max_map_count değeri {0}, bu {1} değerinden daha az. Bazı oyunlar şu an izin verilen bellek haritası limitinden daha fazlasını yaratmaya çalışabilir. Ryujinx bu limitin geçildiği takdirde kendini kapatıcaktır.\n\nManuel olarak bu limiti arttırmayı deneyebilir ya da pkexec'i yükleyebilirsiniz, bu da Ryujinx'in yardımcı olmasına izin verir.",
"uk_UA": "Поточне значення vm.max_map_count ({0}) менше за {1}. Деякі ігри можуть спробувати створити більше відображень пам’яті, ніж дозволено наразі. Ryujinx закриється (крашнеться), щойно цей ліміт буде перевищено.\n\nВи можете збільшити ліміт власноруч або встановити pkexec, який допоможе Ryujinx впоратися з перевищенням ліміту.",
"zh_CN": "vm.max_map_count ({0}) 的当前值小于 {1}。 有些游戏可能会尝试创建超过当前系统允许的内存映射最大数量,若超过当前最大数量,Ryujinx 模拟器将会闪退。\n\n你可以手动增加内存映射最大数量,或者安装 pkexec,它可以辅助 Ryujinx 完成内存映射最大数量的修改操作。",
@@ -3385,7 +3335,7 @@
"pt_BR": "Interface do Usuário",
"ru_RU": "Интерфейс",
"sv_SE": "Användargränssnitt",
- "th_TH": "หน้าจอผู้ใช้",
+ "th_TH": "อินเทอร์เฟซผู้ใช้",
"tr_TR": "Kullancı Arayüzü",
"uk_UA": "Інтерфейс",
"zh_CN": "用户界面",
@@ -3408,7 +3358,7 @@
"no_NO": "Generelt",
"pl_PL": "Ogólne",
"pt_BR": "Geral",
- "ru_RU": "Общее",
+ "ru_RU": "Общие",
"sv_SE": "Allmänt",
"th_TH": "ทั่วไป",
"tr_TR": "Genel",
@@ -3433,7 +3383,7 @@
"no_NO": "Aktiver Discord Rik Tilstedeværelse",
"pl_PL": "Włącz Bogatą Obecność Discord",
"pt_BR": "Habilitar Presença no Discord",
- "ru_RU": "Статус активности в Discord",
+ "ru_RU": "Включить cтатус активности в Discord",
"sv_SE": "Aktivera Discord Rich Presence",
"th_TH": "เปิดใช้งาน Discord Rich Presence",
"tr_TR": "Discord Zengin İçerik'i Etkinleştir",
@@ -3450,7 +3400,7 @@
"el_GR": "",
"en_US": "Check for Updates:",
"es_ES": "",
- "fr_FR": "Vérifier les mises à jour : ",
+ "fr_FR": "Vérifier les Mises à Jour : ",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -3458,9 +3408,9 @@
"no_NO": "Se etter Oppdateringer:",
"pl_PL": "",
"pt_BR": "Verificar Atualizações:",
- "ru_RU": "Проверка наличия обновлений",
+ "ru_RU": "Проверка обновлений:",
"sv_SE": "Leta efter uppdateringar:",
- "th_TH": "",
+ "th_TH": "ตรวจสอบการอัปเดต:",
"tr_TR": "",
"uk_UA": "Перевірка оновлень:",
"zh_CN": "检查更新",
@@ -3485,7 +3435,7 @@
"pt_BR": "Desligado",
"ru_RU": "Отключить",
"sv_SE": "Av",
- "th_TH": "",
+ "th_TH": "ปิด",
"tr_TR": "",
"uk_UA": "Вимкнути",
"zh_CN": "关闭",
@@ -3500,7 +3450,7 @@
"el_GR": "",
"en_US": "Prompt",
"es_ES": "",
- "fr_FR": "Au démarrage",
+ "fr_FR": "Demande",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -3510,7 +3460,7 @@
"pt_BR": "Ao Abrir",
"ru_RU": "При запуске",
"sv_SE": "Fråga",
- "th_TH": "",
+ "th_TH": "คำสั่ง",
"tr_TR": "",
"uk_UA": "Запитувати щоразу",
"zh_CN": "提示",
@@ -3535,7 +3485,7 @@
"pt_BR": "2° Plano",
"ru_RU": "В фоне",
"sv_SE": "Bakgrund",
- "th_TH": "",
+ "th_TH": "พื้นหลัง",
"tr_TR": "",
"uk_UA": "Оновлювати в фоні",
"zh_CN": "背景",
@@ -3550,7 +3500,7 @@
"el_GR": "",
"en_US": "On Emulator Focus Lost:",
"es_ES": "",
- "fr_FR": "Lorsque l’émulateur perd le focus :",
+ "fr_FR": "Lorsque l’Émulateur Perd le Focus :",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -3558,9 +3508,9 @@
"no_NO": "På Emulator Fokus Tapt:",
"pl_PL": "",
"pt_BR": "Ao Perder o Foco:",
- "ru_RU": "При выходе эмулятора из фокуса",
+ "ru_RU": "Потеря фокуса эмулятора:",
"sv_SE": "När emulatorn tappar fokus:",
- "th_TH": "",
+ "th_TH": "เมื่อโปรแกรมจำลองไม่ถูกเลือก (สูญเสียโฟกัส):",
"tr_TR": "",
"uk_UA": "При втраті фокуса емулятором:",
"zh_CN": "当模拟器在后台时:",
@@ -3575,7 +3525,7 @@
"el_GR": "",
"en_US": "Do Nothing",
"es_ES": "",
- "fr_FR": "Ne rien faire",
+ "fr_FR": "Ne Rien Faire",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -3585,7 +3535,7 @@
"pt_BR": "Não Fazer Nada",
"ru_RU": "Ничего не делать",
"sv_SE": "Gör ingenting",
- "th_TH": "",
+ "th_TH": "ไม่ตอบสนอง",
"tr_TR": "",
"uk_UA": "Нічого не робити",
"zh_CN": "什么事情也不做",
@@ -3600,7 +3550,7 @@
"el_GR": "",
"en_US": "Block Input",
"es_ES": "",
- "fr_FR": "Bloquer la saisie",
+ "fr_FR": "Bloquer la Saisie",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -3610,7 +3560,7 @@
"pt_BR": "Bloquear Controles",
"ru_RU": "Блокировать управление",
"sv_SE": "Blockera inmatning",
- "th_TH": "",
+ "th_TH": "ป้องกันการป้อนข้อมูล",
"tr_TR": "",
"uk_UA": "Блокувати введення",
"zh_CN": "禁用输入",
@@ -3625,7 +3575,7 @@
"el_GR": "",
"en_US": "Mute Volume",
"es_ES": "",
- "fr_FR": "Couper le son",
+ "fr_FR": "Couper le Son",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -3635,7 +3585,7 @@
"pt_BR": "Ficar Mudo",
"ru_RU": "Отключить звук",
"sv_SE": "Stäng av ljudet",
- "th_TH": "",
+ "th_TH": "ปิดเสียง",
"tr_TR": "",
"uk_UA": "Вимкнути звук",
"zh_CN": "静音",
@@ -3650,7 +3600,7 @@
"el_GR": "",
"en_US": "Block Input & Mute Volume",
"es_ES": "",
- "fr_FR": "Bloquer la saisie & couper le son",
+ "fr_FR": "Bloquer la Saisie & Couper le Son",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -3660,10 +3610,10 @@
"pt_BR": "Bloquear Controles & Ficar Mudo",
"ru_RU": "Блокировать управление и отключить звук",
"sv_SE": "Blockera inmatningar och stäng av ljudet",
- "th_TH": "",
+ "th_TH": "ป้องกันการป้อนข้อมูลและปิดเสียง",
"tr_TR": "",
"uk_UA": "Блокувати введення та Вимкнути звук",
- "zh_CN": "阻止输入且静音",
+ "zh_CN": "阻止输入并静音",
"zh_TW": "停用輸入且靜音"
}
},
@@ -3675,7 +3625,7 @@
"el_GR": "",
"en_US": "Pause Emulation",
"es_ES": "",
- "fr_FR": "Mettre l’émulation en pause",
+ "fr_FR": "Pauser l'Émulation",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -3685,7 +3635,7 @@
"pt_BR": "Pausar a Emulação",
"ru_RU": "Поставить паузу",
"sv_SE": "Pausa emuleringen",
- "th_TH": "",
+ "th_TH": "พักการจำลอง",
"tr_TR": "",
"uk_UA": "Поставити на паузу",
"zh_CN": "暂停模拟",
@@ -3700,7 +3650,7 @@
"el_GR": "Εμφάνιση διαλόγου \"Επιβεβαίωση Εξόδου\".",
"en_US": "Show \"Confirm Exit\" Dialog",
"es_ES": "Mostrar diálogo de confirmación al cerrar",
- "fr_FR": "Afficher le message de \"Confirmation de sortie\"",
+ "fr_FR": "Afficher le Message de \"Confirmation de sortie\"",
"he_IL": "הראה דיאלוג \"אשר יציאה\"",
"it_IT": "Mostra dialogo \"Conferma Uscita\"",
"ja_JP": "\"終了を確認\" ダイアログを表示する",
@@ -3708,7 +3658,7 @@
"no_NO": "Vis \"Bekreft Avslutt\" vinduet",
"pl_PL": "Pokazuj okno dialogowe \"Potwierdź wyjście\"",
"pt_BR": "Exibir \"Diálogo de confirmação\" ao Sair",
- "ru_RU": "Подтверждать выход из приложения",
+ "ru_RU": "Подтверждать выход из игры",
"sv_SE": "Visa \"Bekräfta avslut\"-dialog",
"th_TH": "แสดง \"ปุ่มยืนยันการออก\" เมื่อออกเกม",
"tr_TR": "\"Çıkışı Onayla\" Diyaloğunu Göster",
@@ -3725,7 +3675,7 @@
"el_GR": "",
"en_US": "Remember Window Size/Position",
"es_ES": "Recordar Tamaño/Posición de la Ventana",
- "fr_FR": "Mémoriser la taille/position de la fenêtre",
+ "fr_FR": "Mémoriser la Taille/Position de la Fenêtre",
"he_IL": "",
"it_IT": "Ricorda la dimensione e la posizione della finestra",
"ja_JP": "",
@@ -3750,7 +3700,7 @@
"el_GR": "",
"en_US": "Disable Input when Out of Focus",
"es_ES": "",
- "fr_FR": "Désactiver la saisie en cas de perte de focus",
+ "fr_FR": "Désactiver la Saisie en cas de Perte de Focus",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -3758,9 +3708,9 @@
"no_NO": "Deaktiver inndata når vinduet er ute av fokus",
"pl_PL": "",
"pt_BR": "Desativar Controles Quando Estiver Fora de Foco",
- "ru_RU": "Отключает управление при выходе из фокуса",
+ "ru_RU": "Отключить ввод при потере фокуса",
"sv_SE": "Inaktivera inmatning när fokus tappas",
- "th_TH": "",
+ "th_TH": "ปิดการพิมพ์เมื่อไม่ได้เลือกช่องอินพุต ไม่ให้กรอกข้อมูลเมื่อช่องอินพุตไม่อยู่ในโฟกัส",
"tr_TR": "",
"uk_UA": "Вимкнути введення, якщо вікно неактивне",
"zh_CN": "在后台时禁用输入",
@@ -3775,7 +3725,7 @@
"el_GR": "",
"en_US": "Show Original UI Style (Requires Restart)",
"es_ES": "",
- "fr_FR": "Afficher le style d’interface original (redémarrage requis)",
+ "fr_FR": "Afficher le Style d’Interface Utilisateur Original (Redémarrage requis)",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -3783,9 +3733,9 @@
"no_NO": "Vis original UI-stil (krever omstart)",
"pl_PL": "",
"pt_BR": "Mostrar Estilo Original da Interface (Requer Reinicialização)",
- "ru_RU": "Включить оригинальный интерфейса (требуется перезагрузка)",
+ "ru_RU": "Оригинальный интерфейс (требуется перезагрузка)",
"sv_SE": "Visa ursprunglig gränssnittsstil (kräver omstart)",
- "th_TH": "",
+ "th_TH": "แสดงรูปแบบอินเทอร์เฟซเดิม (ต้องเริ่มโปรแกรมใหม่)",
"tr_TR": "",
"uk_UA": "Показати оригінальний UI (Потрібен перезапуск)",
"zh_CN": "显示原始 UI 样式 (需要重启)",
@@ -3808,9 +3758,9 @@
"no_NO": "Vis det eldre Avalonia Ryujinx-grensesnittet som minner om Ryujinx 1.1.1403. Dette er aktivert som standard på plattformer som ikke er Windows.\n\nTittellinjen i klassisk stil er tilbake, og store omarbeidinger av vindusoppsettet er reversert, for eksempel plasseringen av innstillingsnavigasjonen over dette verktøytipset.",
"pl_PL": "",
"pt_BR": "Mostrar a Interface Avalonia antiga do Ryujinx 1.1.1403. Esta versão é ativada por padrão nas plataformas que não sejam Windows.\n\nO estilo clássico da Barra de Título retorna e grande parte das mudanças do Layout de janela são revertidas; assim como as configurações de posicionamento da navegação acima dessa descrição.",
- "ru_RU": "Показать старый пользовательский интерфейс Avalonia Ryujinx, напоминающий Ryujinx 1.1.1403. Включено по умолчанию на платформах, отличных от Windows.\n\nСтрока заголовка в классическом стиле вернётся на место, а основные изменения в оформлении окна будут отменены; например, расположение навигации по настройкам над этой всплывающей подсказкой.",
+ "ru_RU": "Показать старый пользовательский интерфейс Avalonia Ryujinx, напоминающий Ryujinx 1.1.1403. Включено по умолчанию на платформах, отличных от Windows.\n\nКлассическая панель заголовка возвращается, а основные изменения в расположении окон отменяются — например, навигация по настройкам — снова расположена выше этой подсказки.",
"sv_SE": "Visa det gamla Ryuijinx-gränssnittet baserat på Avalonia som påminner om version 1.1.1403. Detta är aktiverat som standard på plattformat som inte är Windows.\n\nDen klassiska titelfältet är tillbaka och de stora omarbetningarna av fönsterlayouten är omvända, till exempel placeringen av inställningsnavigeringen ovanför detta verktygstips.",
- "th_TH": "",
+ "th_TH": "แสดง UI แบบเก่าของ Avalonia Ryujinx ที่คล้ายกับเวอร์ชัน 1.1.1403 (เปิดใช้งานโดยอัตโนมัติในระบบที่ไม่ใช่ Windows)\n\nแถบชื่อหน้าต่างแบบดั้งเดิมกลับมาแล้ว และการจัดวางหน้าต่างที่เคยเปลี่ยนไปก็ถูกปรับกลับ เช่น ตำแหน่งของเมนูการตั้งค่าเหนือข้อความนี้",
"tr_TR": "",
"uk_UA": "Показати старий інтерфейс Avalonia Ryujinx, який був у Ryujinx 1.1.1403. Ця опція активна за замовчуванням на всіх інших, окрім Windows платформах.\n\nПовернеться класична панель заголовка, а всі суттєві зміни інтерфейсу будуть скасовані, зокрема горизонтальне розміщення навігації в налаштуваннях.",
"zh_CN": "显示旧的类似 Ryujinx 1.1.1403 的 Avalonia Ryujinx UI。在非 Windows 平台上默认启用此选项。\n\n经典样式的标题栏已回归并且恢复了对窗口布局的重大重构;例如在工具提示上方放置设置导航。",
@@ -3833,7 +3783,7 @@
"no_NO": "Skjul musepeker:",
"pl_PL": "Ukryj kursor:",
"pt_BR": "Esconder Cursor do Mouse:",
- "ru_RU": "Скрывать курсор",
+ "ru_RU": "Скрывать курсор:",
"sv_SE": "Dölj markör:",
"th_TH": "ซ่อน เคอร์เซอร์:",
"tr_TR": "İşaretçiyi Gizle:",
@@ -3875,7 +3825,7 @@
"el_GR": "Απόκρυψη Δρομέα στην Αδράνεια",
"en_US": "On Idle",
"es_ES": "Ocultar cursor cuando esté inactivo",
- "fr_FR": "Si inactif",
+ "fr_FR": "Si Inactif",
"he_IL": "במצב סרק",
"it_IT": "Quando è inattivo",
"ja_JP": "アイドル時",
@@ -3883,7 +3833,7 @@
"no_NO": "Når inaktiv",
"pl_PL": "Gdy bezczynny",
"pt_BR": "Quando Ocioso",
- "ru_RU": "В простое",
+ "ru_RU": "При бездействии",
"sv_SE": "Vid overksam",
"th_TH": "เมื่อไม่ได้ใช้งาน",
"tr_TR": "Hareketsiz Durumda",
@@ -3925,7 +3875,7 @@
"el_GR": "Τοποθεσίες παιχνιδιών",
"en_US": "Game Directories",
"es_ES": "Carpetas de juegos",
- "fr_FR": "Dossiers des jeux",
+ "fr_FR": "Dossiers des Jeux",
"he_IL": "תקיות משחקים",
"it_IT": "Cartelle dei giochi",
"ja_JP": "ゲームディレクトリ",
@@ -3950,7 +3900,7 @@
"el_GR": "",
"en_US": "Autoload DLC/Updates Directories",
"es_ES": "Carpetas de DLC/Actualizaciones para Carga Automática",
- "fr_FR": "Charger automatiquement les dossiers de DLC/mises à jour",
+ "fr_FR": "Dossiers des DLC/Mises à Jour",
"he_IL": "",
"it_IT": "Cartelle di caricamento automatico di DLC/aggiornamenti",
"ja_JP": "",
@@ -3958,7 +3908,7 @@
"no_NO": "Autoload DLC/Updates-mapper",
"pl_PL": "",
"pt_BR": "Carregar Automaticamente Pasta de DLC e Atualizações",
- "ru_RU": "Автозагрузка папки с DLC/Обновлениями",
+ "ru_RU": "Автозагрузка папок с DLC/Обновлениями",
"sv_SE": "Läs automatiskt in DLC/speluppdateringar",
"th_TH": "โหลดไดเรกทอรี DLC/ไฟล์อัปเดต อัตโนมัติ",
"tr_TR": "",
@@ -3975,7 +3925,7 @@
"el_GR": "",
"en_US": "DLC and Updates which refer to missing files will be unloaded automatically",
"es_ES": "DLC y Actualizaciones que hacen referencia a archivos ausentes serán desactivado automáticamente",
- "fr_FR": "Les DLC et mises à jour faisant référence à des fichiers manquants seront déchargés automatiquement.",
+ "fr_FR": "Les DLC et les Mises à Jour faisant référence aux fichiers manquants seront automatiquement déchargés.",
"he_IL": "",
"it_IT": "Aggiornamenti e DLC che fanno riferimento a file mancanti verranno disabilitati automaticamente",
"ja_JP": "",
@@ -3983,9 +3933,9 @@
"no_NO": "DLC og oppdateringer som henviser til manglende filer, vil bli lastet ned automatisk",
"pl_PL": "",
"pt_BR": "DLCs e Atualizações que se referem a arquivos ausentes serão desabilitados automaticamente",
- "ru_RU": "DLC и обновления, которые ссылаются на отсутствующие файлы, будут выгружаться автоматически",
+ "ru_RU": "DLC и обновления, ссылающиеся на отсутствующие файлы, будут автоматически выгружены",
"sv_SE": "DLC och speluppdateringar som refererar till saknade filer kommer inte att läsas in automatiskt",
- "th_TH": "",
+ "th_TH": "DLC และอัปเดตที่มีการอ้างอิงถึงไฟล์ที่ไม่มีอยู่ จะถูกปิดการใช้งานโดยอัตโนมัติ",
"tr_TR": "",
"uk_UA": "DLC та Оновлення, які посилаються на відсутні файли, будуть автоматично вимкнуті.",
"zh_CN": "DLC 及 游戏更新 可自动加载和卸载",
@@ -4075,7 +4025,7 @@
"el_GR": "Πυρήνας",
"en_US": "Core",
"es_ES": "Núcleo",
- "fr_FR": "Paramètres généraux",
+ "fr_FR": "Paramètres Généraux",
"he_IL": "ליבה",
"it_IT": "Principale",
"ja_JP": "コア",
@@ -4083,7 +4033,7 @@
"no_NO": "Kjerne",
"pl_PL": "Główne",
"pt_BR": "Principal",
- "ru_RU": "Основные настройки",
+ "ru_RU": "Основные",
"sv_SE": "Kärna",
"th_TH": "แกนกลาง",
"tr_TR": "Çekirdek",
@@ -4100,7 +4050,7 @@
"el_GR": "Περιοχή Συστήματος:",
"en_US": "System Region:",
"es_ES": "Región del sistema:",
- "fr_FR": "Région du système :",
+ "fr_FR": "Région du Système :",
"he_IL": "אזור מערכת:",
"it_IT": "Regione del sistema:",
"ja_JP": "地域:",
@@ -4108,7 +4058,7 @@
"no_NO": "System region:",
"pl_PL": "Region systemu:",
"pt_BR": "Região do Sistema:",
- "ru_RU": "Регион прошивки:",
+ "ru_RU": "Регион системы:",
"sv_SE": "Systemregion:",
"th_TH": "ภูมิภาคของระบบ:",
"tr_TR": "Sistem Bölgesi:",
@@ -4175,7 +4125,7 @@
"el_GR": "Ευρώπη",
"en_US": "Europe",
"es_ES": "Europa",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "אירופה",
"it_IT": "Europa",
"ja_JP": "ヨーロッパ",
@@ -4300,7 +4250,7 @@
"el_GR": "Γλώσσα Συστήματος:",
"en_US": "System Language:",
"es_ES": "Idioma del sistema:",
- "fr_FR": "Langue du système :",
+ "fr_FR": "Langue du Système :",
"he_IL": "שפת המערכת:",
"it_IT": "Lingua del sistema:",
"ja_JP": "言語:",
@@ -4750,7 +4700,7 @@
"el_GR": "Ζώνη Ώρας Συστήματος:",
"en_US": "System Time Zone:",
"es_ES": "Zona horaria del sistema:",
- "fr_FR": "Fuseau horaire du système\u00A0:",
+ "fr_FR": "Fuseau Horaire du Système :",
"he_IL": "אזור זמן מערכת:",
"it_IT": "Fuso orario del sistema:",
"ja_JP": "タイムゾーン:",
@@ -4775,7 +4725,7 @@
"el_GR": "Ώρα Συστήματος:",
"en_US": "System Time:",
"es_ES": "Hora del sistema:",
- "fr_FR": "Heure du système :",
+ "fr_FR": "Heure du Système :",
"he_IL": "זמן מערכת:",
"it_IT": "Data e ora del sistema:",
"ja_JP": "時刻:",
@@ -4783,7 +4733,7 @@
"no_NO": "System tid:",
"pl_PL": "Czas systemu:",
"pt_BR": "Data e Hora do Sistema:",
- "ru_RU": "Системное время:",
+ "ru_RU": "Время системы:",
"sv_SE": "Systemtid:",
"th_TH": "เวลาของระบบ:",
"tr_TR": "Sistem Saati:",
@@ -4808,7 +4758,7 @@
"no_NO": "Match systemtid",
"pl_PL": "",
"pt_BR": "Sincronizar com o Sistema PC",
- "ru_RU": "Соответствовать времени в системе",
+ "ru_RU": "Соответствовать времени устройства",
"sv_SE": "Matcha systemtid",
"th_TH": "",
"tr_TR": "",
@@ -4850,7 +4800,7 @@
"el_GR": "",
"en_US": "Low-Power PPTC",
"es_ES": "PPTC de bajo consumo",
- "fr_FR": "PPTC de faible puissance",
+ "fr_FR": "PPTC de Faible Puissance",
"he_IL": "",
"it_IT": "PPTC a basso consumo energetico",
"ja_JP": "",
@@ -4858,7 +4808,7 @@
"no_NO": "PPTC med lavt strømforbruk",
"pl_PL": "",
"pt_BR": "PPTC com Baixo Consumo de Energia",
- "ru_RU": "PPTC с низким электропотреблением",
+ "ru_RU": "Маломощный PPTC",
"sv_SE": "PPTC med låg strömförbrukning",
"th_TH": "PPTC แบบพลังงานตํ่า",
"tr_TR": "",
@@ -4883,9 +4833,9 @@
"no_NO": "Multiplikator i turbomodus:",
"pl_PL": "",
"pt_BR": "Multiplicador do Modo Turbo",
- "ru_RU": "",
+ "ru_RU": "Множитель режима Турбо:",
"sv_SE": "Multiplikator för turboläge:",
- "th_TH": "",
+ "th_TH": "ระดับความแรงของโหมดเทอร์โบ:",
"tr_TR": "",
"uk_UA": "Множник Турборежиму:",
"zh_CN": "涡轮模式倍数:",
@@ -4908,9 +4858,9 @@
"no_NO": "Målverdien for multiplikatoren i turbomodus. \n\nLa syå på 200 hvis du er usikker.",
"pl_PL": "",
"pt_BR": "O valor do Multiplicador do Modo Turbo. Deixe em 200 se não tiver certeza.",
- "ru_RU": "",
+ "ru_RU": "Целевое значение множителя режима Turbo.\n\nРекомендуется оставить 200.",
"sv_SE": "Målvärdet för multiplikatorn i turboläget. \n\nLämna den på 200 om du är osäker.",
- "th_TH": "",
+ "th_TH": "กำหนดค่าตัวคูณสำหรับโหมดเทอร์โบ\n\n(หากไม่แน่ใจ ให้ปล่อยไว้ที่ค่าเริ่มต้น 200)",
"tr_TR": "",
"uk_UA": "Цільове значення коефіцієнта Турборежиму.\n\nЗалиште 200, якщо не впевнені",
"zh_CN": "涡轮模式倍数的目标值。\n\n如果不确定请保留为 200。",
@@ -4933,9 +4883,9 @@
"no_NO": "Turbo-modus er en emulatorfunksjon som effektivt øker eller senker hastigheten når et spill ikke er følsom for bildefrekvens.\nDu kan slå på denne funksjonen i spillet med en hurtigtast, som kan konfigureres i Ryujinx Keyboard Hotkeys-innstillingene.\n\nLa den stå på 200 hvis du er usikker.",
"pl_PL": "",
"pt_BR": "O Modo Turbo é um recurso do emulador que efetivamente aumenta ou dimimui a velocidade de um jogo quando o mesmo não é sensivel à taxa de quadros. \nVocê pode ativar esse recurso dentro do jogo com uma tecla de atalho, configurável nas Configurações de Teclas de Atalho do Ryujinx. \n\nDeixe em 200 se não tiver certeza.",
- "ru_RU": "",
+ "ru_RU": "Режим Турбо — это функция эмулятора, которая позволяет ускорять или замедлять игру, если она не чувствительна к частоте кадров.\nВы можете включать или отключать этот режим во время игры с помощью горячей клавиши, которую можно настроить в разделе «Горячие клавиши» Ryujinx.\n\nРекомендуется оставить 200.",
"sv_SE": "Turboläget är en emulatorfunktion som effektivt ökar eller sänker hastigheten när ett spel inte är känsligt för bildfrekvens.\nDu kan växla denna funktion i spelet med en snabbtangent, konfigurerbar i Ryujinx inställningar för snabbtangenter.\n\nLämna den på 200 om du är osäker.",
- "th_TH": "",
+ "th_TH": "โหมดเทอร์โบเป็นฟีเจอร์ของอีมูเลเตอร์ ที่ช่วยเร่งหรือชะลอความเร็วของเกม ในกรณีที่เกมไม่ไวต่ออัตราเฟรม\nคุณสามารถเปิดหรือปิดฟีเจอร์นี้ขณะเล่นเกมได้ด้วยปุ่มลัด ซึ่งสามารถตั้งค่าได้ในเมนู Ryujinx > การตั้งค่าปุ่มลัดบนคีย์บอร์ด\n\n(หากไม่แน่ใจ แนะนำให้ปล่อยค่าที่ 200)",
"tr_TR": "",
"uk_UA": "Турборежим (Turbo mode) – функція емулятора, що ефективно прискорює або сповільнює гру, якщо та не чутлива до частоти кадрів. Цю функцію можна ввімкнути/вимкнути безпосередньо під час гри за допомогою гарячої клавіші, яку можна прив'язати в меню \"Гарячі клавіші\" в налаштуваннях.",
"zh_CN": "涡轮模式是一种模拟器功能当游戏对帧率不敏感时它可以有效地导致加速或降速。\n您可以在游戏中使用热键切换此功能,它可以在 Ryujinx 的键盘热键设置进行设置。\n\n如果不确定则保留为 200。",
@@ -4950,7 +4900,7 @@
"el_GR": "Ενεργοποίηση Ελέγχων Ακεραιότητας FS",
"en_US": "FS Integrity Checks",
"es_ES": "Comprobar integridad de los archivos",
- "fr_FR": "Vérification de l’intégrité du système de fichiers (FS)",
+ "fr_FR": "Vérification de l’Intégrité du Système de Fichiers (FS)",
"he_IL": "FS בדיקות תקינות",
"it_IT": "Attiva controlli d'integrità FS",
"ja_JP": "ファイルシステム整合性チェック",
@@ -4958,7 +4908,7 @@
"no_NO": "FS Integritetssjekk",
"pl_PL": "Sprawdzanie integralności systemu plików",
"pt_BR": "Verificações de Integridade do FS",
- "ru_RU": "Проверка целостности файловой системы",
+ "ru_RU": "Проверять целостность файловой системы (FS)",
"sv_SE": "Integritetskontroller av filsystem",
"th_TH": "ตรวจสอบความถูกต้องของ FS",
"tr_TR": "FS Bütünlük Kontrolleri",
@@ -5100,7 +5050,7 @@
"el_GR": "Μικροδιορθώσεις",
"en_US": "Hacks",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "האצות",
"it_IT": "Espedienti",
"ja_JP": "ハック",
@@ -5158,7 +5108,7 @@
"no_NO": "DRAM Mengde",
"pl_PL": "Użyj alternatywnego układu pamięci (Deweloperzy)",
"pt_BR": "Tamanho da DRAM:",
- "ru_RU": "Использовать альтернативный макет памяти (для разработчиков)",
+ "ru_RU": "Размер DRAM:",
"sv_SE": "DRAM-storlek:",
"th_TH": "ใช้หน่วยความจำสำรอง (โหมดนักพัฒนา)",
"tr_TR": "Alternatif bellek düzeni kullan (Geliştirici)",
@@ -5185,11 +5135,11 @@
"pt_BR": "4GB",
"ru_RU": "4ГиБ",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "4 กิบบิไบต์",
"tr_TR": "",
"uk_UA": "4Гб",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -5210,11 +5160,11 @@
"pt_BR": "6GB",
"ru_RU": "6ГиБ",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "6 กิบบิไบต์",
"tr_TR": "",
"uk_UA": "6Гб",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -5235,11 +5185,11 @@
"pt_BR": "8GB",
"ru_RU": "8ГиБ",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "8 กิบบิไบต์",
"tr_TR": "",
"uk_UA": "8Гб",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -5260,11 +5210,11 @@
"pt_BR": "12GB",
"ru_RU": "12ГиБ",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "12 กิบบิไบต์",
"tr_TR": "",
"uk_UA": "12Гб",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -5275,7 +5225,7 @@
"el_GR": "Αγνόηση υπηρεσιών που λείπουν",
"en_US": "Ignore Missing Services",
"es_ES": "Ignorar servicios no implementados",
- "fr_FR": "Ignorer les services manquants",
+ "fr_FR": "Ignorer les Services Manquants",
"he_IL": "התעלם משירותים חסרים",
"it_IT": "Ignora servizi mancanti",
"ja_JP": "未実装サービスを無視する",
@@ -5283,7 +5233,7 @@
"no_NO": "Ignorer manglende tjenester",
"pl_PL": "Ignoruj Brakujące Usługi",
"pt_BR": "Ignorar Serviços Ausentes",
- "ru_RU": "Игнорировать отсутствующие службы",
+ "ru_RU": "Игнорировать отсутствующие сервисы",
"sv_SE": "Ignorera saknade tjänster",
"th_TH": "เมินเฉยบริการที่หายไป",
"tr_TR": "Eksik Servisleri Görmezden Gel",
@@ -5300,7 +5250,7 @@
"el_GR": "",
"en_US": "Ignore Controller Applet",
"es_ES": "",
- "fr_FR": "Ignorer l’applet de contrôleur",
+ "fr_FR": "Ignorer l’Applet de Manette",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -5308,7 +5258,7 @@
"no_NO": "Ignorer Kontroller-applet",
"pl_PL": "",
"pt_BR": "Ignorar Applet do Controlador",
- "ru_RU": "Игнорировать апплет контроллера",
+ "ru_RU": "Игнорировать окно контроллера",
"sv_SE": "Ignorera kontroller-applet",
"th_TH": "",
"tr_TR": "",
@@ -5325,7 +5275,7 @@
"el_GR": "Παράκαμψη διαλόγου 'Διαχείριση Προφίλ _Χρηστών'",
"en_US": "Skip Dialog 'Manage User Profiles'",
"es_ES": "Omitir el diálogo 'Gestionar perfiles de usuario'",
- "fr_FR": "Ignorer la boîte de dialogue « Gérer les profils utilisateur »",
+ "fr_FR": "Ignorer la boîte de dialogue « Gérer les Profils d'Utilisateurs »",
"he_IL": "דילוג על הדיאלוג 'נהל פרופילי משתמש'",
"it_IT": "Salta la finestra di dialogo 'Gestisci i profili utente'",
"ja_JP": "「ユーザプロファイルを管理」ダイアログをスキップ",
@@ -5333,7 +5283,7 @@
"no_NO": "Hopp over dialogen 'Administrere Brukerprofiler'",
"pl_PL": "Pomiń okno dialogowe 'Zarządzaj profilami użytkowników'",
"pt_BR": "Ignorar a caixa de diálogo 'Gerenciar Perfis de Usuário'",
- "ru_RU": "Пропустить диалог 'Менеджер учётных записей'",
+ "ru_RU": "Пропускать окно 'Управление профилями'",
"sv_SE": "Hoppa över dialogen 'Hantera användarprofiler'",
"th_TH": "ข้ามหน้าต่างโต้ตอบ 'จัดการโปรไฟล์ผู้ใช้งาน'",
"tr_TR": "'Kullanıcı Profillerini Yönet' iletişim kutusunu atla",
@@ -5388,7 +5338,7 @@
"th_TH": "API กราฟฟิก & การเพิ่มประสิทธิภาพ",
"tr_TR": "Grafikler API & Optimizasyon",
"uk_UA": "Графічний API & Оптимізація",
- "zh_CN": "图形 API & 优化",
+ "zh_CN": "图形 API 与优化",
"zh_TW": "圖形 API & 優化"
}
},
@@ -5400,7 +5350,7 @@
"el_GR": "Ενεργοποίηση Προσωρινής Μνήμης Shader",
"en_US": "Enable Shader Cache",
"es_ES": "Habilitar caché de sombreadores",
- "fr_FR": "Activer le cache des shaders",
+ "fr_FR": "Activer le Cache des Shaders",
"he_IL": "הפעל מטמון הצללות",
"it_IT": "Attiva la cache degli shader",
"ja_JP": "シェーダーキャッシュを有効にする",
@@ -5425,7 +5375,7 @@
"el_GR": "Ανισότροπο Φιλτράρισμα:",
"en_US": "Anisotropic Filtering:",
"es_ES": "Filtro anisotrópico:",
- "fr_FR": "Filtrage anisotrope :",
+ "fr_FR": "Filtrage Anisotrope :",
"he_IL": "סינון אניסוטרופי:",
"it_IT": "Filtro anisotropico:",
"ja_JP": "異方性フィルタリング:",
@@ -5450,7 +5400,7 @@
"el_GR": "Αυτόματο",
"en_US": "Auto",
"es_ES": "Automático",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "אוטומטי",
"it_IT": "Automatico",
"ja_JP": "自動",
@@ -5458,7 +5408,7 @@
"no_NO": "Automatisk",
"pl_PL": "Automatyczne",
"pt_BR": "Automático",
- "ru_RU": "Автоматически",
+ "ru_RU": "Автоматическая",
"sv_SE": "Automatiskt",
"th_TH": "อัตโนมัติ",
"tr_TR": "Otomatik",
@@ -5483,9 +5433,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "คูณ 2",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -5508,9 +5458,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "คูณ 4",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -5533,9 +5483,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "คูณ 8",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -5558,9 +5508,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "คูณ 16",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -5575,7 +5525,7 @@
"el_GR": "Κλίμακα Ανάλυσης:",
"en_US": "Resolution Scale:",
"es_ES": "Escala de resolución:",
- "fr_FR": "Échelle de résolution :",
+ "fr_FR": "Échelle de Résolution :",
"he_IL": "קנה מידה של רזולוציה:",
"it_IT": "Scala della risoluzione:",
"ja_JP": "解像度:",
@@ -5600,7 +5550,7 @@
"el_GR": "Προσαρμοσμένο (Δεν συνιστάται)",
"en_US": "Custom (Not Recommended)",
"es_ES": "Personalizada (no recomendado)",
- "fr_FR": "Personnalisée (non recommandée)",
+ "fr_FR": "Personnalisée (Non Recommandée)",
"he_IL": "מותאם אישית (לא מומלץ)",
"it_IT": "Personalizzata (Non raccomandata)",
"ja_JP": "カスタム (非推奨)",
@@ -5633,7 +5583,7 @@
"no_NO": "Naturlig (720p/1080p)",
"pl_PL": "Natywna (720p/1080p)",
"pt_BR": "Nativa (720p/1080p)",
- "ru_RU": "Нативное (720p/1080p)",
+ "ru_RU": "Изходное (720p/1080p)",
"sv_SE": "Inbyggd (720p/1080p)",
"th_TH": "พื้นฐานระบบ (720p/1080p)",
"tr_TR": "Yerel (720p/1080p)",
@@ -5658,9 +5608,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "คูณ 2 (1440p/2160p)",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "2 倍 (1440p/2160p)",
@@ -5683,9 +5633,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "คูณ 3 (2160p/3240p)",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "3 倍 (2160p/3240p)",
@@ -5700,7 +5650,7 @@
"el_GR": "",
"en_US": "4x (2880p/4320p) (Not Recommended)",
"es_ES": "4x (2880p/4320p) (no recomendado)",
- "fr_FR": "x4 (2880p/4320p) (non recommandé)",
+ "fr_FR": "x4 (2880p/4320p) (Non Recommandé)",
"he_IL": "4x (2880p/4320p) (לא מומלץ)",
"it_IT": "4x (2880p/4320p) (Non consigliato)",
"ja_JP": "4x (2880p/4320p) (非推奨)",
@@ -5710,7 +5660,7 @@
"pt_BR": "4x (2880p/4320p) (Não recomendado)",
"ru_RU": "4x (2880p/4320p) (не рекомендуется)",
"sv_SE": "4x (2880p/4320p) (rekommenderas inte)",
- "th_TH": "4x (2880p/4320p) (ไม่แนะนำ)",
+ "th_TH": "คูณ 4 (2880p/4320p) (ไม่แนะนำ)",
"tr_TR": "4x (2880p/4320p) (Tavsiye Edilmez)",
"uk_UA": "4x (2880p/4320p) (Не рекомендується)",
"zh_CN": "4 倍 (2880p/4320p) (不推荐)",
@@ -5725,7 +5675,7 @@
"el_GR": "Αναλογία Απεικόνισης:",
"en_US": "Aspect Ratio:",
"es_ES": "Relación de aspecto:",
- "fr_FR": "Format d'image :",
+ "fr_FR": "Format d'Affichage :",
"he_IL": "יחס גובה-רוחב:",
"it_IT": "Rapporto d'aspetto:",
"ja_JP": "アスペクト比:",
@@ -5875,7 +5825,7 @@
"el_GR": "Έκταση σε όλο το παράθυρο",
"en_US": "Stretch to Fit Window",
"es_ES": "Estirar a la ventana",
- "fr_FR": "Ajuster à la taille de la fenêtre",
+ "fr_FR": "Ajuster à la Taille de la Fenêtre",
"he_IL": "מתח לגודל חלון",
"it_IT": "Adatta alla finestra",
"ja_JP": "ウインドウサイズに合わせる",
@@ -5883,7 +5833,7 @@
"no_NO": "Strekk for og Tilpasse vindu",
"pl_PL": "Rozciągnij do Okna",
"pt_BR": "Esticar até Caber",
- "ru_RU": "Растянуть до размеров окна",
+ "ru_RU": "Растянуть до размера окна",
"sv_SE": "Sträck ut för att passa fönster",
"th_TH": "ยืดภาพเพื่อให้พอดีกับหน้าต่าง",
"tr_TR": "Pencereye Sığdırmak İçin Genişlet",
@@ -5900,7 +5850,7 @@
"el_GR": "Επιλογές Προγραμματιστή",
"en_US": "Developer Options",
"es_ES": "Opciones de desarrollador",
- "fr_FR": "Options pour les développeurs",
+ "fr_FR": "Options pour les Développeurs",
"he_IL": "אפשרויות מפתח",
"it_IT": "Opzioni per sviluppatori",
"ja_JP": "開発者向けオプション",
@@ -5925,7 +5875,7 @@
"el_GR": "Τοποθεσία Shaders Γραφικών:",
"en_US": "Graphics Shader Dump Path:",
"es_ES": "Directorio de volcado de sombreadores:",
- "fr_FR": "Chemin de vidage des shaders graphiques :",
+ "fr_FR": "Chemin du Dossier de Copie des Shaders :",
"he_IL": "",
"it_IT": "Percorso di dump degli shader:",
"ja_JP": "グラフィックス シェーダー ダンプパス:",
@@ -5933,7 +5883,7 @@
"no_NO": "Grafikk Shader Dump bane:",
"pl_PL": "Ścieżka do zgranych cieni graficznych:",
"pt_BR": "Diretório para Despejo de Shaders:",
- "ru_RU": "Путь дампа графических шейдеров",
+ "ru_RU": "Путь сброса графических шейдеров:",
"sv_SE": "Sökväg för Graphics Shader Dump:",
"th_TH": "ที่เก็บ ดัมพ์ไฟล์ แสงเงา:",
"tr_TR": "Grafik Shader Döküm Yolu:",
@@ -5950,7 +5900,7 @@
"el_GR": "Καταγραφή",
"en_US": "Logging",
"es_ES": "Registros",
- "fr_FR": "Journalisation",
+ "fr_FR": "Journaux",
"he_IL": "רישום",
"it_IT": "Log",
"ja_JP": "ロギング",
@@ -5975,7 +5925,7 @@
"el_GR": "Καταγραφή",
"en_US": "Logging",
"es_ES": "Registros",
- "fr_FR": "Journalisation",
+ "fr_FR": "Journaux",
"he_IL": "רישום",
"it_IT": "Log",
"ja_JP": "ロギング",
@@ -6000,7 +5950,7 @@
"el_GR": "Ενεργοποίηση Καταγραφής Αρχείου",
"en_US": "Enable Logging to File",
"es_ES": "Habilitar registro a archivo",
- "fr_FR": "Activer la journalisation dans un fichier",
+ "fr_FR": "Activer la Sauvegarde des Journaux vers un Fichier",
"he_IL": "אפשר רישום לקובץ",
"it_IT": "Salva i log su file",
"ja_JP": "ファイルへのロギングを有効にする",
@@ -6025,7 +5975,7 @@
"el_GR": "Ενεργοποίηση Καταγραφής Stub",
"en_US": "Enable Stub Logs",
"es_ES": "Habilitar registros de Stub",
- "fr_FR": "Activer les journaux stub",
+ "fr_FR": "Activer les Journaux Stub",
"he_IL": "אפשר רישום בדל",
"it_IT": "Attiva log di stub",
"ja_JP": "Stub ログを有効にする",
@@ -6033,7 +5983,7 @@
"no_NO": "Aktiver Stub-logger",
"pl_PL": "Wlącz Skróty Logów",
"pt_BR": "Habilitar Logs de Stub",
- "ru_RU": "Включить журнал-заглушку",
+ "ru_RU": "Включить журналы-заглушки",
"sv_SE": "Aktivera stubbloggar",
"th_TH": "เปิดใช้งานการบันทึกประวัติ",
"tr_TR": "Stub Loglarını Etkinleştir",
@@ -6050,7 +6000,7 @@
"el_GR": "Ενεργοποίηση Καταγραφής Πληροφοριών",
"en_US": "Enable Info Logs",
"es_ES": "Habilitar registros de Info",
- "fr_FR": "Activer les journaux d'informations",
+ "fr_FR": "Activer les Journaux d'Informations",
"he_IL": "אפשר רישום מידע",
"it_IT": "Attiva log di informazioni",
"ja_JP": "Info ログを有効にする",
@@ -6058,7 +6008,7 @@
"no_NO": "Aktiver informasjonslogger",
"pl_PL": "Włącz Logi Informacyjne",
"pt_BR": "Habilitar Logs de Informação",
- "ru_RU": "Включить информационный журнал",
+ "ru_RU": "Включить информационный журналы",
"sv_SE": "Aktivera informationsloggar",
"th_TH": "เปิดใช้งานการบันทึกประวัติการใช้งาน",
"tr_TR": "Bilgi Loglarını Etkinleştir",
@@ -6075,7 +6025,7 @@
"el_GR": "Ενεργοποίηση Καταγραφής Προειδοποίησης",
"en_US": "Enable Warning Logs",
"es_ES": "Habilitar registros de Advertencia",
- "fr_FR": "Activer les journaux d'avertissements",
+ "fr_FR": "Activer les Journaux d'Avertissements",
"he_IL": "אפשר רישום אזהרות",
"it_IT": "Attiva log di avviso",
"ja_JP": "Warning ログを有効にする",
@@ -6083,7 +6033,7 @@
"no_NO": "Aktiver varsellogger",
"pl_PL": "Włącz Logi Ostrzeżeń",
"pt_BR": "Habilitar Logs de Alerta",
- "ru_RU": "Включить журнал предупреждений",
+ "ru_RU": "Включить журналы предупреждений",
"sv_SE": "Aktivera varningsloggar",
"th_TH": "เปิดใช้งานการบันทึกประวัติคำเตือน",
"tr_TR": "Uyarı Loglarını Etkinleştir",
@@ -6100,7 +6050,7 @@
"el_GR": "Ενεργοποίηση Καταγραφής Σφαλμάτων",
"en_US": "Enable Error Logs",
"es_ES": "Habilitar registros de Error",
- "fr_FR": "Activer les journaux d'erreurs",
+ "fr_FR": "Activer les Journaux d'Erreurs",
"he_IL": "אפשר רישום שגיאות",
"it_IT": "Attiva log di errore",
"ja_JP": "Error ログを有効にする",
@@ -6108,7 +6058,7 @@
"no_NO": "Aktiver feillogger",
"pl_PL": "Włącz Logi Błędów",
"pt_BR": "Habilitar Logs de Erro",
- "ru_RU": "Включить журнал ошибок",
+ "ru_RU": "Включить журналы ошибок",
"sv_SE": "Aktivera felloggar",
"th_TH": "เปิดใช้งานการบันทึกประวัติข้อผิดพลาด",
"tr_TR": "Hata Loglarını Etkinleştir",
@@ -6125,7 +6075,7 @@
"el_GR": "Ενεργοποίηση Καταγραφής Ιχνών",
"en_US": "Enable Trace Logs",
"es_ES": "Habilitar registros de Rastro",
- "fr_FR": "Activer les journaux de trace",
+ "fr_FR": "Activer les Journaux de Trace",
"he_IL": "הפעל רישום מעקבי",
"it_IT": "Attiva log di trace",
"ja_JP": "Trace ログを有効にする",
@@ -6133,7 +6083,7 @@
"no_NO": "Aktiver spor logger",
"pl_PL": "Włącz Logi Śledzenia",
"pt_BR": "Habilitar Logs de Rastreamento",
- "ru_RU": "Включить журнал трассировки",
+ "ru_RU": "Включить журналы трассировки",
"sv_SE": "Aktivera spårloggar",
"th_TH": "เปิดใช้งานการบันทึกประวัติการติดตาม",
"tr_TR": "Trace Loglarını Etkinleştir",
@@ -6150,7 +6100,7 @@
"el_GR": "Ενεργοποίηση Καταγραφής Επισκεπτών",
"en_US": "Enable Guest Logs",
"es_ES": "Habilitar registros de Guest",
- "fr_FR": "Activer les journaux invités",
+ "fr_FR": "Activer les Journaux Invités",
"he_IL": "הפעל רישום מארח",
"it_IT": "Attiva log del guest",
"ja_JP": "Guest ログを有効にする",
@@ -6175,7 +6125,7 @@
"el_GR": "",
"en_US": "Enable UI Logs",
"es_ES": "",
- "fr_FR": "Activer les journaux UI",
+ "fr_FR": "Activer les Journaux de l'Interface Utilisateur",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -6183,7 +6133,7 @@
"no_NO": "Aktivere UI-logger",
"pl_PL": "",
"pt_BR": "Habilitar Logs da IU",
- "ru_RU": "Включить журнал интерфейса",
+ "ru_RU": "Включить журналы интерфейса",
"sv_SE": "Aktivera gränssnittsloggar",
"th_TH": "",
"tr_TR": "",
@@ -6199,8 +6149,8 @@
"de_DE": "Aktiviere Fs Zugriff-Logs",
"el_GR": "Ενεργοποίηση Καταγραφής Πρόσβασης FS",
"en_US": "Enable Fs Access Logs",
- "es_ES": "Habilitar registros de Fs Access",
- "fr_FR": "Activer les journaux d'accès au système de fichiers",
+ "es_ES": "Habilitar registros de FS Access",
+ "fr_FR": "Activer les Journaux d'Accès au Système de Fichiers",
"he_IL": "אפשר רישום גישת קבצי מערכת",
"it_IT": "Attiva log di accesso FS",
"ja_JP": "Fs アクセスログを有効にする",
@@ -6225,7 +6175,7 @@
"el_GR": "Λειτουργία Καταγραφής Καθολικής Πρόσβασης FS:",
"en_US": "Fs Global Access Log Mode:",
"es_ES": "Modo de registros Fs Global Access:",
- "fr_FR": "Mode global des journaux d’accès FS",
+ "fr_FR": "Mode Global des Journaux d’Accès FS",
"he_IL": "מצב רישום גלובלי של גישת קבצי מערכת",
"it_IT": "Modalità log di accesso globale FS:",
"ja_JP": "Fs グローバルアクセスログモード:",
@@ -6233,7 +6183,7 @@
"no_NO": "Fs Global Access-logg-modus:",
"pl_PL": "Tryb globalnego dziennika zdarzeń systemu plików:",
"pt_BR": "Modo de Log de Acesso Global Fs:",
- "ru_RU": "Режим журнала глобального доступа файловой системы:",
+ "ru_RU": "Режим журнала глобального доступа FS:",
"sv_SE": "Loggläge för global filsystemsåtkomst:",
"th_TH": "โหมด การเข้าถึงประวัติส่วนกลาง:",
"tr_TR": "Fs Evrensel Erişim Log Modu:",
@@ -6250,7 +6200,7 @@
"el_GR": "Επιλογές Προγραμματιστή (ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Η απόδοση Θα μειωθεί)",
"en_US": "Developer Options",
"es_ES": "Opciones de desarrollador (ADVERTENCIA: empeorarán el rendimiento)",
- "fr_FR": "Options pour les développeurs",
+ "fr_FR": "Options pour les Développeurs",
"he_IL": "אפשרויות מפתח",
"it_IT": "Opzioni per sviluppatori",
"ja_JP": "開発者オプション",
@@ -6275,7 +6225,7 @@
"el_GR": "ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Θα μειώσει την απόδοση",
"en_US": "WARNING: Will Reduce Performance",
"es_ES": "ADVERTENCIA: Reducirá el rendimiento",
- "fr_FR": "ATTENTION : Réduira les performances",
+ "fr_FR": "ATTENTION : Réduira la Performance",
"he_IL": "אזהרה: יפחית ביצועים",
"it_IT": "ATTENZIONE: ridurranno le prestazioni",
"ja_JP": "警告: パフォーマンスを低下させます",
@@ -6283,7 +6233,7 @@
"no_NO": "Advarsel: Vil redusere ytelsen",
"pl_PL": "UWAGA: Pogrorszy wydajność",
"pt_BR": "AVISO: Reduzirá o desempenho",
- "ru_RU": "ВНИМАНИЕ: эти настройки снижают производительность",
+ "ru_RU": "ВНИМАНИЕ: Снижают производительность",
"sv_SE": "VARNING: Kommer att reducera prestandan",
"th_TH": "คำเตือน: จะทำให้ประสิทธิภาพลดลง",
"tr_TR": "UYARI: Oyun performansı azalacak",
@@ -6300,7 +6250,7 @@
"el_GR": "Επίπεδο Καταγραφής Διεπαφής Γραφικών:",
"en_US": "Graphics Backend Log Level:",
"es_ES": "Nivel de registro de backend gráficos:",
- "fr_FR": "Niveau de journalisation du backend graphique :",
+ "fr_FR": "Niveau du Journal de la Backend Graphique :",
"he_IL": "רישום גרפיקת קצה אחורי:",
"it_IT": "Livello di log del backend grafico:",
"ja_JP": "グラフィックスバックエンド ログレベル:",
@@ -6425,7 +6375,7 @@
"el_GR": "Ενεργοποίηση Αρχείων Καταγραφής Εντοπισμού Σφαλμάτων",
"en_US": "Enable Debug Logs",
"es_ES": "Habilitar registros de debug",
- "fr_FR": "Activer les journaux de débogage",
+ "fr_FR": "Activer les Journaux de Débogage",
"he_IL": "אפשר רישום ניפוי באגים",
"it_IT": "Attiva log di debug",
"ja_JP": "デバッグログを有効にする",
@@ -6433,7 +6383,7 @@
"no_NO": "Aktiver feilsøkingslogger",
"pl_PL": "Włącz dzienniki zdarzeń do debugowania",
"pt_BR": "Habilitar Logs de Depuração",
- "ru_RU": "Включить журнал отладки",
+ "ru_RU": "Включить журналы отладки",
"sv_SE": "Aktivera felsökningsloggar",
"th_TH": "เปิดใช้งาน ประวัติข้อบกพร่อง",
"tr_TR": "Hata Ayıklama Loglarını Etkinleştir",
@@ -6500,7 +6450,7 @@
"el_GR": "Ενεργοποίηση Docked Mode",
"en_US": "Docked Mode",
"es_ES": "Modo dock/TV",
- "fr_FR": "Mode Docké",
+ "fr_FR": "Mode Station d'Accueil",
"he_IL": "מצב עגינה",
"it_IT": "Attiva modalità TV",
"ja_JP": "ドッキングモード",
@@ -6508,7 +6458,7 @@
"no_NO": "Forankret modus",
"pl_PL": "Tryb zadokowany",
"pt_BR": "Modo TV",
- "ru_RU": "Стационарный режим",
+ "ru_RU": "Режим Док-Станции",
"sv_SE": "Dockat läge",
"th_TH": "ด็อกโหมด",
"tr_TR": "Docked Modu Etkinleştir",
@@ -6525,7 +6475,7 @@
"el_GR": "Άμεση Πρόσβαση στο Πληκτρολόγιο",
"en_US": "Direct Keyboard Access",
"es_ES": "Acceso directo al teclado",
- "fr_FR": "Accès direct au clavier",
+ "fr_FR": "Accès Direct au Clavier",
"he_IL": "גישה ישירה למקלדת",
"it_IT": "Accesso diretto alla tastiera",
"ja_JP": "キーボード直接アクセス",
@@ -6533,7 +6483,7 @@
"no_NO": "Direkte tastaturtilgang",
"pl_PL": "Bezpośredni dostęp do klawiatury",
"pt_BR": "Acesso Direto ao Teclado",
- "ru_RU": "Прямой ввод клавиатуры",
+ "ru_RU": "Прямой Ввод Клавиатуры",
"sv_SE": "Direkt tangentbordsåtkomst",
"th_TH": "เข้าถึงคีย์บอร์ดโดยตรง",
"tr_TR": "Doğrudan Klavye Erişimi",
@@ -6600,7 +6550,7 @@
"el_GR": "",
"en_US": "Reset Settings",
"es_ES": "",
- "fr_FR": "Réinitialiser les paramètres",
+ "fr_FR": "Réinitialiser les Paramètres",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -6650,7 +6600,7 @@
"el_GR": "",
"en_US": "OK",
"es_ES": "Aceptar",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "אישור",
"it_IT": "",
"ja_JP": "",
@@ -6658,7 +6608,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "Ok",
"th_TH": "ตกลง",
"tr_TR": "Tamam",
@@ -7000,7 +6950,7 @@
"el_GR": "",
"en_US": "Configuration found:\n\nName:\t{0}\nGUID:\t{1}\n\n Waiting for controller connection...",
"es_ES": "",
- "fr_FR": "Configuration trouvée:\n\nNom:\t{0}\nGUID:\t{1}\n\nEn attente de la connexion de la manette...",
+ "fr_FR": "Configuration trouvée:\n\nNom:\t{0}\nGUID:\t{1}\n\n En attente de connexion de la manette...",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -7008,7 +6958,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "Configuração encontrada:\n\nNome:\t{0}\nGUID:\t{1}\n\n Aguardando conexão do controle...",
- "ru_RU": "",
+ "ru_RU": "Конфигурация найдена:\n\nИмя:\t{0}\nGUID:\t{1}\n\nОжидание подключения контроллера...",
"sv_SE": "Konfiguration hittad:\n\nNamn:\t{0}\nGUID:\t{1}\n\n Väntar på anslutning till kontroller...",
"th_TH": "",
"tr_TR": "",
@@ -7075,7 +7025,7 @@
"el_GR": "Τύπος Χειριστηρίου",
"en_US": "Controller Type",
"es_ES": "Tipo de Mando",
- "fr_FR": "Type de manette",
+ "fr_FR": "Type de Manette",
"he_IL": "סוג שלט",
"it_IT": "Tipo di controller",
"ja_JP": "コントローラ種別",
@@ -7133,7 +7083,7 @@
"no_NO": "",
"pl_PL": "Pro Kontroler",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "Pro Контроллер",
"sv_SE": "",
"th_TH": "โปรคอนโทรลเลอร์",
"tr_TR": "Profesyonel Kumanda",
@@ -7600,7 +7550,7 @@
"el_GR": "Κατευθυντικό Pad",
"en_US": "Directional Pad",
"es_ES": "Pad direccional",
- "fr_FR": "Croix directionnelle",
+ "fr_FR": "Croix Directionnelle",
"he_IL": "כפתורי כיוונים",
"it_IT": "Croce direzionale",
"ja_JP": "十字キー",
@@ -7608,7 +7558,7 @@
"no_NO": "Retningsfelt",
"pl_PL": "Krzyżak (D-Pad)",
"pt_BR": "Direcional (D-Pad)",
- "ru_RU": "Кнопки направления (D-pad)",
+ "ru_RU": "Крестовина (D-Pad)",
"sv_SE": "Riktningsknappar",
"th_TH": "ปุ่มลูกศร",
"tr_TR": "Yön Tuşları",
@@ -7733,7 +7683,7 @@
"no_NO": "Knapp",
"pl_PL": "Przycisk",
"pt_BR": "Botão",
- "ru_RU": "Нажатие на стик",
+ "ru_RU": "Нажатие",
"sv_SE": "Knapp",
"th_TH": "ปุ่ม",
"tr_TR": "Tuş",
@@ -7875,7 +7825,7 @@
"el_GR": "Αντιστροφή Μοχλού X",
"en_US": "Invert Stick X",
"es_ES": "Invertir eje X",
- "fr_FR": "Inverser l'axe X",
+ "fr_FR": "Inverser l'Axe X",
"he_IL": "הפיכת הX של הסטיק",
"it_IT": "Inverti levetta X",
"ja_JP": "X軸を反転",
@@ -7900,7 +7850,7 @@
"el_GR": "Αντιστροφή Μοχλού Y",
"en_US": "Invert Stick Y",
"es_ES": "Invertir eje Y",
- "fr_FR": "Inverser l'axe Y",
+ "fr_FR": "Inverser l'Axe Y",
"he_IL": "הפיכת הY של הסטיק",
"it_IT": "Inverti levetta Y",
"ja_JP": "Y軸を反転",
@@ -7925,7 +7875,7 @@
"el_GR": "Νεκρή Ζώνη:",
"en_US": "Deadzone:",
"es_ES": "Zona muerta:",
- "fr_FR": "Zone morte :",
+ "fr_FR": "Zone Morte :",
"he_IL": "שטח מת:",
"it_IT": "Zona morta:",
"ja_JP": "遊び:",
@@ -8400,7 +8350,7 @@
"el_GR": "Κατώφλι Σκανδάλης:",
"en_US": "Trigger Threshold:",
"es_ES": "Límite de gatillos:",
- "fr_FR": "Seuil de déclenchement :",
+ "fr_FR": "Seuil de Gachettes :",
"he_IL": "סף הדק:",
"it_IT": "Sensibilità dei grilletti:",
"ja_JP": "トリガーしきい値:",
@@ -8475,7 +8425,7 @@
"el_GR": "Υποδοχή Χειριστηρίου:",
"en_US": "Controller Slot:",
"es_ES": "Puerto del mando:",
- "fr_FR": "Contrôleur ID :",
+ "fr_FR": "Manette ID :",
"he_IL": "מיקום שלט",
"it_IT": "Slot del controller:",
"ja_JP": "コントローラ スロット:",
@@ -8500,7 +8450,7 @@
"el_GR": "Καθρεπτισμός Χειρισμού",
"en_US": "Mirror Input",
"es_ES": "Paralelizar derecho e izquierdo",
- "fr_FR": "Inverser les contrôles",
+ "fr_FR": "Inverser les Contrôles",
"he_IL": "קלט מראה",
"it_IT": "Input specchiato",
"ja_JP": "入力反転",
@@ -8550,7 +8500,7 @@
"el_GR": "Κεντρικός Υπολογιστής Διακομιστή:",
"en_US": "Server Host:",
"es_ES": "Host del servidor:",
- "fr_FR": "Serveur d'hébergement :",
+ "fr_FR": "Serveur d'Hébergement :",
"he_IL": "מארח השרת:",
"it_IT": "Server:",
"ja_JP": "サーバ:",
@@ -8575,7 +8525,7 @@
"el_GR": "Ευαισθησία Γυροσκοπίου:",
"en_US": "Gyro Sensitivity:",
"es_ES": "Sensibilidad de Gyro:",
- "fr_FR": "Sensibilitée du gyroscope :",
+ "fr_FR": "Sensibilitée du Gyroscope :",
"he_IL": "רגישות ג'ירוסקופ:",
"it_IT": "Sensibilità del giroscopio:",
"ja_JP": "ジャイロ感度:",
@@ -8600,7 +8550,7 @@
"el_GR": "Νεκρή Ζώνη Γυροσκοπίου:",
"en_US": "Gyro Deadzone:",
"es_ES": "Zona muerta de Gyro:",
- "fr_FR": "Zone morte du gyroscope :",
+ "fr_FR": "Zone Morte du Gyroscope :",
"he_IL": "שטח מת של הג'ירוסקופ:",
"it_IT": "Zona morta del giroscopio:",
"ja_JP": "ジャイロ遊び:",
@@ -8625,7 +8575,7 @@
"el_GR": "",
"en_US": "LED",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -8633,13 +8583,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "LED-подсветка",
+ "ru_RU": "LED-Подсветка",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ตั้งค่าไฟ LED",
"tr_TR": "",
"uk_UA": "LED-підсвітка",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -8660,7 +8610,7 @@
"pt_BR": "Desabilitar",
"ru_RU": "Отключить",
"sv_SE": "Inaktivera",
- "th_TH": "",
+ "th_TH": "ปิดการใช้งาน",
"tr_TR": "",
"uk_UA": "Вимкнути",
"zh_CN": "关闭",
@@ -8683,9 +8633,9 @@
"no_NO": "Regnbue",
"pl_PL": "",
"pt_BR": "Arco-íris",
- "ru_RU": "Радужная",
+ "ru_RU": "Радуга",
"sv_SE": "Regnbåge",
- "th_TH": "",
+ "th_TH": "สีรุ้ง",
"tr_TR": "",
"uk_UA": "Веселка",
"zh_CN": "彩虹",
@@ -8700,7 +8650,7 @@
"el_GR": "",
"en_US": "Rainbow Speed",
"es_ES": "",
- "fr_FR": "Vitesse des couleurs",
+ "fr_FR": "Vitesse de l'Arc-en-ciel",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -8710,7 +8660,7 @@
"pt_BR": "Velocidade do Arco-íris",
"ru_RU": "Скорость переливания",
"sv_SE": "Regnbågshastighet",
- "th_TH": "",
+ "th_TH": "ความเร็วของสีรุ้ง",
"tr_TR": "",
"uk_UA": "Швидкість зміни кольорів",
"zh_CN": "彩虹滚动速度",
@@ -8735,7 +8685,7 @@
"pt_BR": "Cor",
"ru_RU": "Цвет",
"sv_SE": "Färg",
- "th_TH": "",
+ "th_TH": "สี",
"tr_TR": "",
"uk_UA": "Колір",
"zh_CN": "颜色",
@@ -8835,7 +8785,7 @@
"pt_BR": "Shift Esquerdo",
"ru_RU": "Левый Shift",
"sv_SE": "Skift vänster",
- "th_TH": "",
+ "th_TH": "Shift ซ้าย",
"tr_TR": "Sol Shift",
"uk_UA": "Shift Лівий",
"zh_CN": "左侧Shift",
@@ -8860,7 +8810,7 @@
"pt_BR": "Shift Direito",
"ru_RU": "Правый Shift",
"sv_SE": "Skift höger",
- "th_TH": "",
+ "th_TH": "Shift ขวา",
"tr_TR": "Sağ Shift",
"uk_UA": "Shift Правий",
"zh_CN": "右侧Shift",
@@ -8885,7 +8835,7 @@
"pt_BR": "Ctrl Esquerdo",
"ru_RU": "Левый Ctrl",
"sv_SE": "Ctrl vänster",
- "th_TH": "",
+ "th_TH": "Ctrl ซ้าย",
"tr_TR": "Sol Ctrl",
"uk_UA": "Ctrl Лівий",
"zh_CN": "左侧Ctrl",
@@ -8910,7 +8860,7 @@
"pt_BR": "⌃ Esquerda",
"ru_RU": "Левый ⌃",
"sv_SE": "^ Vänster",
- "th_TH": "",
+ "th_TH": "^ ซ้าย",
"tr_TR": "⌃ Sol",
"uk_UA": "⌃ Лівий",
"zh_CN": "左侧⌃",
@@ -8935,7 +8885,7 @@
"pt_BR": "Ctrl Direito",
"ru_RU": "Правый Ctrl",
"sv_SE": "Ctrl höger",
- "th_TH": "",
+ "th_TH": "Ctrl ขวา",
"tr_TR": "Sağ Control",
"uk_UA": "Ctrl Правий",
"zh_CN": "右侧Ctrl",
@@ -8960,7 +8910,7 @@
"pt_BR": "⌃ Direito",
"ru_RU": "Правый ⌃",
"sv_SE": "^ Höger",
- "th_TH": "",
+ "th_TH": "⌃ ขวา",
"tr_TR": "⌃ Sağ",
"uk_UA": "⌃ Правий",
"zh_CN": "右侧⌃",
@@ -8985,7 +8935,7 @@
"pt_BR": "Alt Esquerdo",
"ru_RU": "Левый Alt",
"sv_SE": "Alt vänster",
- "th_TH": "",
+ "th_TH": "Alt ซ้าย",
"tr_TR": "Sol Alt",
"uk_UA": "Alt Лівий",
"zh_CN": "左侧Alt",
@@ -9010,7 +8960,7 @@
"pt_BR": "⌥ Esquerda",
"ru_RU": "Левый ⌥",
"sv_SE": "⌥ vänster",
- "th_TH": "",
+ "th_TH": "⌥ ซ้าย",
"tr_TR": "⌥ Sol",
"uk_UA": "⌥ Лівий",
"zh_CN": "左侧⌥",
@@ -9035,7 +8985,7 @@
"pt_BR": "Alt Direito",
"ru_RU": "Правый Alt",
"sv_SE": "Alt höger",
- "th_TH": "",
+ "th_TH": "Alt ขวา",
"tr_TR": "Sağ Alt",
"uk_UA": "Alt Правий",
"zh_CN": "右侧Alt",
@@ -9060,7 +9010,7 @@
"pt_BR": "⌥ Direito",
"ru_RU": "Правый ⌥",
"sv_SE": "⌥ höger",
- "th_TH": "",
+ "th_TH": "⌥ ขวา",
"tr_TR": "⌥ Sağ",
"uk_UA": "⌥ Правий",
"zh_CN": "右侧⌥",
@@ -9085,7 +9035,7 @@
"pt_BR": "⊞ Esquerdo",
"ru_RU": "Левый ⊞",
"sv_SE": "⊞ vänster",
- "th_TH": "",
+ "th_TH": "⊞ ซ้าย",
"tr_TR": "⊞ Sol",
"uk_UA": "⊞ Лівий",
"zh_CN": "左侧⊞",
@@ -9110,7 +9060,7 @@
"pt_BR": "⌘ Esquerdo",
"ru_RU": "Левый ⌘",
"sv_SE": "⌘ vänster",
- "th_TH": "",
+ "th_TH": "⌘ ซ้าย",
"tr_TR": "⌘ Sol",
"uk_UA": "⌘ Лівий",
"zh_CN": "左侧⌘",
@@ -9135,7 +9085,7 @@
"pt_BR": "⊞ Direito",
"ru_RU": "Правый ⊞",
"sv_SE": "⊞ höger",
- "th_TH": "",
+ "th_TH": "⊞ ขวา",
"tr_TR": "⊞ Sağ",
"uk_UA": "⊞ Правий",
"zh_CN": "右侧⊞",
@@ -9160,7 +9110,7 @@
"pt_BR": "⌘ Direito",
"ru_RU": "Правый ⌘",
"sv_SE": "⌘ höger",
- "th_TH": "",
+ "th_TH": "⌘ ขวา",
"tr_TR": "⌘ Sağ",
"uk_UA": "⌘ Правий",
"zh_CN": "右侧⌘",
@@ -9175,7 +9125,7 @@
"el_GR": "",
"en_US": "Menu",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "Menù",
"ja_JP": "",
@@ -9185,7 +9135,7 @@
"pt_BR": "",
"ru_RU": "Меню",
"sv_SE": "Meny",
- "th_TH": "",
+ "th_TH": "เมนู",
"tr_TR": "Menü",
"uk_UA": "Меню",
"zh_CN": "菜单键",
@@ -9210,7 +9160,7 @@
"pt_BR": "Cima",
"ru_RU": "Вверх",
"sv_SE": "Upp",
- "th_TH": "",
+ "th_TH": "ขึ้น",
"tr_TR": "Yukarı",
"uk_UA": "Вгору ↑",
"zh_CN": "上",
@@ -9235,7 +9185,7 @@
"pt_BR": "Baixo",
"ru_RU": "Вниз",
"sv_SE": "Ner",
- "th_TH": "",
+ "th_TH": "ลง",
"tr_TR": "Aşağı",
"uk_UA": "Вниз ↓",
"zh_CN": "下",
@@ -9260,7 +9210,7 @@
"pt_BR": "Esquerda",
"ru_RU": "Влево",
"sv_SE": "Vänster",
- "th_TH": "",
+ "th_TH": "ซ้าย",
"tr_TR": "Sol",
"uk_UA": "Вліво ←",
"zh_CN": "左",
@@ -9285,7 +9235,7 @@
"pt_BR": "Direita",
"ru_RU": "Вправо",
"sv_SE": "Höger",
- "th_TH": "",
+ "th_TH": "ขวา",
"tr_TR": "Sağ",
"uk_UA": "Вправо →",
"zh_CN": "右",
@@ -9308,9 +9258,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Enter",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "回车键",
@@ -9333,9 +9283,9 @@
"no_NO": "Esc-tast",
"pl_PL": "",
"pt_BR": "Esc",
- "ru_RU": "Esc",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Escape",
"tr_TR": "Esc",
"uk_UA": "Esc",
"zh_CN": "Esc",
@@ -9360,7 +9310,7 @@
"pt_BR": "Espaço",
"ru_RU": "Пробел",
"sv_SE": "Blanksteg",
- "th_TH": "",
+ "th_TH": "ปุ่ม Spacebar",
"tr_TR": "",
"uk_UA": "Пробіл",
"zh_CN": "空格键",
@@ -9375,7 +9325,7 @@
"el_GR": "",
"en_US": "Tab",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -9383,9 +9333,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Tab",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9408,9 +9358,9 @@
"no_NO": "Tilbaketast",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Backspace",
"tr_TR": "Geri tuşu",
"uk_UA": "",
"zh_CN": "退格键",
@@ -9433,9 +9383,9 @@
"no_NO": "Sett inn",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Insert",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9458,9 +9408,9 @@
"no_NO": "Slett",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Delete",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9475,7 +9425,7 @@
"el_GR": "",
"en_US": "Page Up",
"es_ES": "",
- "fr_FR": "Pg.Préc",
+ "fr_FR": "Pg.Suiv",
"he_IL": "",
"it_IT": "Pag. Su",
"ja_JP": "",
@@ -9483,9 +9433,9 @@
"no_NO": "Side opp",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Page Up",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9500,7 +9450,7 @@
"el_GR": "",
"en_US": "Page Down",
"es_ES": "",
- "fr_FR": "Pg.Suiv",
+ "fr_FR": "Pg.Préc",
"he_IL": "",
"it_IT": "Pag. Giù",
"ja_JP": "",
@@ -9508,9 +9458,9 @@
"no_NO": "Side ned",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Page Down",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9525,7 +9475,7 @@
"el_GR": "",
"en_US": "Home",
"es_ES": "",
- "fr_FR": "Home (⤒)",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "Inizio",
"ja_JP": "",
@@ -9533,9 +9483,9 @@
"no_NO": "Hjem",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Home",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9558,9 +9508,9 @@
"no_NO": "Avslutt",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม End",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9583,9 +9533,9 @@
"no_NO": "Skiftelås",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Caps Lock",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9608,9 +9558,9 @@
"no_NO": "Rullelås",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Scroll Lock",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9633,9 +9583,9 @@
"no_NO": "Skjermbilde",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Print Screen",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9650,7 +9600,7 @@
"el_GR": "",
"en_US": "Pause",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "Pausa",
"ja_JP": "",
@@ -9658,9 +9608,9 @@
"no_NO": "Stans midlertidig",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Pause",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9683,9 +9633,9 @@
"no_NO": "Numerisk Lås",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม Num Lock",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
@@ -9708,9 +9658,9 @@
"no_NO": "Tøm",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "Töm",
- "th_TH": "",
+ "th_TH": "ล้าง",
"tr_TR": "",
"uk_UA": "Очистити",
"zh_CN": "清除键",
@@ -9733,9 +9683,9 @@
"no_NO": "Numerisk 0",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "0 (цифровий блок)",
+ "ru_RU": "Блок цифр 0",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม 0 บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "Блок цифр 0",
"zh_CN": "小键盘0",
@@ -9760,7 +9710,7 @@
"pt_BR": "",
"ru_RU": "Блок цифр 1",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม 1 บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "Блок цифр 1",
"zh_CN": "小键盘1",
@@ -9785,7 +9735,7 @@
"pt_BR": "",
"ru_RU": "Блок цифр 2",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม 2 บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "2 (цифровий блок)",
"zh_CN": "小键盘2",
@@ -9810,7 +9760,7 @@
"pt_BR": "",
"ru_RU": "Блок цифр 3",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม 3 บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "3 (цифровий блок)",
"zh_CN": "小键盘3",
@@ -9835,7 +9785,7 @@
"pt_BR": "",
"ru_RU": "Блок цифр 4",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม 4 บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "4 (цифровий блок)",
"zh_CN": "小键盘4",
@@ -9860,7 +9810,7 @@
"pt_BR": "",
"ru_RU": "Блок цифр 5",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม 5 บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "5 (цифровий блок)",
"zh_CN": "小键盘5",
@@ -9885,7 +9835,7 @@
"pt_BR": "",
"ru_RU": "Блок цифр 6",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม 6 บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "6 (цифровий блок)",
"zh_CN": "小键盘6",
@@ -9910,7 +9860,7 @@
"pt_BR": "",
"ru_RU": "Блок цифр 7",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม 7 บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "7 (цифровий блок)",
"zh_CN": "小键盘7",
@@ -9935,7 +9885,7 @@
"pt_BR": "",
"ru_RU": "Блок цифр 8",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม 8 บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "8 (цифровий блок)",
"zh_CN": "小键盘8",
@@ -9960,7 +9910,7 @@
"pt_BR": "",
"ru_RU": "Блок цифр 9",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม 9 บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "9 (цифровий блок)",
"zh_CN": "小键盘9",
@@ -9985,7 +9935,7 @@
"pt_BR": "",
"ru_RU": "/ (блок цифр)",
"sv_SE": "Keypad /",
- "th_TH": "",
+ "th_TH": "ปุ่ม / บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "/ (цифровий блок)",
"zh_CN": "小键盘/",
@@ -10010,7 +9960,7 @@
"pt_BR": "",
"ru_RU": "* (блок цифр)",
"sv_SE": "Keypad *",
- "th_TH": "",
+ "th_TH": "ปุ่ม * บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "* (цифровий блок)",
"zh_CN": "小键盘*",
@@ -10035,7 +9985,7 @@
"pt_BR": "",
"ru_RU": "- (блок цифр)",
"sv_SE": "Keypad -",
- "th_TH": "",
+ "th_TH": "ปุ่ม - บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "- (цифровий блок)",
"zh_CN": "小键盘-",
@@ -10060,7 +10010,7 @@
"pt_BR": "",
"ru_RU": "+ (блок цифр)",
"sv_SE": "Keypad +",
- "th_TH": "",
+ "th_TH": "ปุ่ม + บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "+ (цифровий блок)",
"zh_CN": "小键盘+",
@@ -10085,7 +10035,7 @@
"pt_BR": "",
"ru_RU": ". (блок цифр)",
"sv_SE": "Keypad ,",
- "th_TH": "",
+ "th_TH": "ปุ่ม . บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": ". (цифровий блок)",
"zh_CN": "小键盘.",
@@ -10110,7 +10060,7 @@
"pt_BR": "",
"ru_RU": "Enter (блок цифр)",
"sv_SE": "Enter (numerisk)",
- "th_TH": "",
+ "th_TH": "ปุ่ม Enter บนแป้นตัวเลข",
"tr_TR": "",
"uk_UA": "Enter (цифровий блок)",
"zh_CN": "小键盘回车键",
@@ -10125,7 +10075,7 @@
"el_GR": "",
"en_US": "0",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "à",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10133,13 +10083,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10150,7 +10100,7 @@
"el_GR": "",
"en_US": "1",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "&",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10158,13 +10108,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10175,7 +10125,7 @@
"el_GR": "",
"en_US": "2",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "é",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10183,13 +10133,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10200,7 +10150,7 @@
"el_GR": "",
"en_US": "3",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "\"",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10208,13 +10158,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10225,7 +10175,7 @@
"el_GR": "",
"en_US": "4",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "'",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10233,13 +10183,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10250,7 +10200,7 @@
"el_GR": "",
"en_US": "5",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "(",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10258,13 +10208,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10275,7 +10225,7 @@
"el_GR": "",
"en_US": "6",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "-",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10283,13 +10233,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10300,7 +10250,7 @@
"el_GR": "",
"en_US": "7",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "è",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10308,13 +10258,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10325,7 +10275,7 @@
"el_GR": "",
"en_US": "8",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "_",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10333,13 +10283,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10350,7 +10300,7 @@
"el_GR": "",
"en_US": "9",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "ç",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10358,13 +10308,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10375,7 +10325,7 @@
"el_GR": "",
"en_US": "~",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "ù",
"he_IL": "",
"it_IT": "ò",
"ja_JP": "",
@@ -10383,13 +10333,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10400,7 +10350,7 @@
"el_GR": "",
"en_US": "`",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10408,13 +10358,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10425,7 +10375,7 @@
"el_GR": "",
"en_US": "-",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10433,13 +10383,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10450,7 +10400,7 @@
"el_GR": "",
"en_US": "+",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "=",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10458,13 +10408,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10475,7 +10425,7 @@
"el_GR": "",
"en_US": "[",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": ")",
"he_IL": "",
"it_IT": "'",
"ja_JP": "",
@@ -10483,13 +10433,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10500,7 +10450,7 @@
"el_GR": "",
"en_US": "]",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "^",
"he_IL": "",
"it_IT": "ì",
"ja_JP": "",
@@ -10508,13 +10458,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10525,7 +10475,7 @@
"el_GR": "",
"en_US": ";",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "$",
"he_IL": "",
"it_IT": "è",
"ja_JP": "",
@@ -10533,13 +10483,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10550,7 +10500,7 @@
"el_GR": "",
"en_US": "\"",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "²",
"he_IL": "",
"it_IT": "à",
"ja_JP": "",
@@ -10558,13 +10508,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10575,7 +10525,7 @@
"el_GR": "",
"en_US": ",",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10583,13 +10533,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10600,7 +10550,7 @@
"el_GR": "",
"en_US": ".",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": ";",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10608,13 +10558,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10625,7 +10575,7 @@
"el_GR": "",
"en_US": "/",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": ":",
"he_IL": "",
"it_IT": "ù",
"ja_JP": "",
@@ -10633,13 +10583,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10650,7 +10600,7 @@
"el_GR": "",
"en_US": "\\",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "<",
"he_IL": "",
"it_IT": "<",
"ja_JP": "",
@@ -10658,13 +10608,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10685,7 +10635,7 @@
"pt_BR": "Não Atribuído",
"ru_RU": "Не привязано",
"sv_SE": "Obunden",
- "th_TH": "",
+ "th_TH": "ยังไม่กำหนดปุ่ม",
"tr_TR": "",
"uk_UA": "Відв'язати",
"zh_CN": "未分配",
@@ -10710,7 +10660,7 @@
"pt_BR": "Botão Analógico Esquerdo",
"ru_RU": "Кнопка лев. стика",
"sv_SE": "L-spakknapp",
- "th_TH": "",
+ "th_TH": "ปุ่มกดที่แท่งอนาล็อกซ้าย",
"tr_TR": "",
"uk_UA": "L Кнопка Стіку",
"zh_CN": "左摇杆按键",
@@ -10735,7 +10685,7 @@
"pt_BR": "Botão Analógico Direito",
"ru_RU": "Кнопка пр. стика",
"sv_SE": "R-spakknapp",
- "th_TH": "",
+ "th_TH": "ปุ่มกดที่แท่งอนาล็อกขวา",
"tr_TR": "",
"uk_UA": "R Кнопка Стіку",
"zh_CN": "右摇杆按键",
@@ -10754,13 +10704,13 @@
"he_IL": "",
"it_IT": "Pulsante dorsale sinistro",
"ja_JP": "",
- "ko_KR": "좌측 숄더",
+ "ko_KR": "좌측 범퍼",
"no_NO": "Venstre Skulder",
"pl_PL": "",
"pt_BR": "Ombro Esquerdo",
"ru_RU": "Левый бампер",
"sv_SE": "Vänster kantknapp",
- "th_TH": "",
+ "th_TH": "ปุ่ม L (ไหล่ซ้าย)",
"tr_TR": "",
"uk_UA": "Лівий Бампер",
"zh_CN": "左肩键L",
@@ -10779,13 +10729,13 @@
"he_IL": "",
"it_IT": "Pulsante dorsale destro",
"ja_JP": "",
- "ko_KR": "우측 숄더",
+ "ko_KR": "우측 범퍼",
"no_NO": "Høyre Skulder",
"pl_PL": "",
"pt_BR": "Ombro Direito",
"ru_RU": "Правый бампер",
"sv_SE": "Höger kantknapp",
- "th_TH": "",
+ "th_TH": "ปุ่ม R (ไหล่ขวา)",
"tr_TR": "",
"uk_UA": "Правий Бампер",
"zh_CN": "右肩键R",
@@ -10810,7 +10760,7 @@
"pt_BR": "Gatilho Esquerdo",
"ru_RU": "Левый триггер",
"sv_SE": "Vänster avtryckare",
- "th_TH": "",
+ "th_TH": "ปุ่มทริกเกอร์ซ้าย",
"tr_TR": "",
"uk_UA": "Лівий Тригер",
"zh_CN": "左扳机键ZL",
@@ -10835,7 +10785,7 @@
"pt_BR": "Gatilho Direito",
"ru_RU": "Правый триггер",
"sv_SE": "Höger avtryckare",
- "th_TH": "",
+ "th_TH": "ปุ่มทริกเกอร์ขวา",
"tr_TR": "",
"uk_UA": "Правий Тригер",
"zh_CN": "右扳机键ZR",
@@ -10860,7 +10810,7 @@
"pt_BR": "Cima",
"ru_RU": "Вверх",
"sv_SE": "Upp",
- "th_TH": "",
+ "th_TH": "ขึ้น",
"tr_TR": "",
"uk_UA": "Вверх",
"zh_CN": "上键",
@@ -10885,7 +10835,7 @@
"pt_BR": "Baixo",
"ru_RU": "Вниз",
"sv_SE": "Ner",
- "th_TH": "",
+ "th_TH": "ลง",
"tr_TR": "",
"uk_UA": "Вниз",
"zh_CN": "下键",
@@ -10910,7 +10860,7 @@
"pt_BR": "Esquerda",
"ru_RU": "Влево",
"sv_SE": "Vänster",
- "th_TH": "",
+ "th_TH": "ซ้าย",
"tr_TR": "",
"uk_UA": "Вліво",
"zh_CN": "左键",
@@ -10935,7 +10885,7 @@
"pt_BR": "Direita",
"ru_RU": "Вправо",
"sv_SE": "Höger",
- "th_TH": "",
+ "th_TH": "ขวา",
"tr_TR": "Sağ",
"uk_UA": "Вправо",
"zh_CN": "右键",
@@ -10950,7 +10900,7 @@
"el_GR": "",
"en_US": "-",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10958,13 +10908,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม - บนจอยเกม",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "-键",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -10975,7 +10925,7 @@
"el_GR": "",
"en_US": "+",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -10983,13 +10933,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม + บนจอยเกม",
"tr_TR": "4",
"uk_UA": "",
"zh_CN": "+键",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -11000,7 +10950,7 @@
"el_GR": "",
"en_US": "Guide",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "Guida",
"ja_JP": "",
@@ -11010,7 +10960,7 @@
"pt_BR": "Guia",
"ru_RU": "Кнопка меню",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "คู่มือ",
"tr_TR": "Rehber",
"uk_UA": "Меню",
"zh_CN": "主页键",
@@ -11035,7 +10985,7 @@
"pt_BR": "",
"ru_RU": "Прочее",
"sv_SE": "Diverse",
- "th_TH": "",
+ "th_TH": "เบ็ดเตล็ด",
"tr_TR": "Diğer",
"uk_UA": "Інше",
"zh_CN": "截图键",
@@ -11060,7 +11010,7 @@
"pt_BR": "",
"ru_RU": "Доп.кнопка 1",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม พาเดิล 1",
"tr_TR": "Pedal 1",
"uk_UA": "Додаткова кнопка 1",
"zh_CN": "其他按键1",
@@ -11085,7 +11035,7 @@
"pt_BR": "",
"ru_RU": "Доп.кнопка 2",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม พาเดิล 2",
"tr_TR": "Pedal 2",
"uk_UA": "Додаткова кнопка 2",
"zh_CN": "其他按键2",
@@ -11110,7 +11060,7 @@
"pt_BR": "",
"ru_RU": "Доп.кнопка 3",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม พาเดิล 3",
"tr_TR": "Pedal 3",
"uk_UA": "Додаткова кнопка 3",
"zh_CN": "其他按键3",
@@ -11135,7 +11085,7 @@
"pt_BR": "",
"ru_RU": "Доп.кнопка 4",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "ปุ่ม พาเดิล 4",
"tr_TR": "Pedal 4",
"uk_UA": "Додаткова кнопка 4",
"zh_CN": "其他按键4",
@@ -11160,7 +11110,7 @@
"pt_BR": "",
"ru_RU": "Тачпад",
"sv_SE": "Pekplatta",
- "th_TH": "",
+ "th_TH": "ทัชแพด",
"tr_TR": "",
"uk_UA": "Сенсорна панель",
"zh_CN": "触摸板",
@@ -11185,7 +11135,7 @@
"pt_BR": "Gatilho Esquerdo 0",
"ru_RU": "Левый триггер 0",
"sv_SE": "Vänster avtryckare 0",
- "th_TH": "",
+ "th_TH": "ปุ่ม 0 ทริกเกอร์ซ้าย",
"tr_TR": "Sol Tetik 0",
"uk_UA": "Лівий Тригер 0",
"zh_CN": "左扳机0",
@@ -11210,7 +11160,7 @@
"pt_BR": "Gatilho Direito 0",
"ru_RU": "Правый триггер 0",
"sv_SE": "Höger avtryckare 0",
- "th_TH": "",
+ "th_TH": "ปุ่ม 0 ทริกเกอร์ขวา",
"tr_TR": "Sağ Tetik 0",
"uk_UA": "Правий Тригер 0",
"zh_CN": "右扳机0",
@@ -11235,7 +11185,7 @@
"pt_BR": "Gatilho Esquerdo 1",
"ru_RU": "Левый триггер 1",
"sv_SE": "Vänster avtryckare 1",
- "th_TH": "",
+ "th_TH": "ปุ่ม 1 ทริกเกอร์ซ้าย",
"tr_TR": "Sol Tetik 1",
"uk_UA": "Лівий Тригер 1",
"zh_CN": "左扳机1",
@@ -11260,7 +11210,7 @@
"pt_BR": "Gatilho Direito 1",
"ru_RU": "Правый триггер 1",
"sv_SE": "Höger avtryckare 1",
- "th_TH": "",
+ "th_TH": "ปุ่ม 1 ทริกเกอร์ขวา",
"tr_TR": "Sağ Tetik 1",
"uk_UA": "Правий Тригер 1",
"zh_CN": "右扳机1",
@@ -11285,7 +11235,7 @@
"pt_BR": "Analógico Esquerdo",
"ru_RU": "Левый стик",
"sv_SE": "Vänster spak",
- "th_TH": "",
+ "th_TH": "แท่งอนาล็อกซ้าย",
"tr_TR": "Sol Çubuk",
"uk_UA": "Лівий Стік",
"zh_CN": "左摇杆",
@@ -11310,7 +11260,7 @@
"pt_BR": "Analógico Direito",
"ru_RU": "Правый стик",
"sv_SE": "Höger spak",
- "th_TH": "",
+ "th_TH": "แท่งอนาล็อกขวา",
"tr_TR": "Sağ çubuk",
"uk_UA": "Правий Стік",
"zh_CN": "右摇杆",
@@ -11358,7 +11308,7 @@
"no_NO": "Lagre profilnavnet",
"pl_PL": "Zapisz nazwę profilu",
"pt_BR": "Salvar Nome de Perfil",
- "ru_RU": "Сохранить пользовательский профиль",
+ "ru_RU": "Сохранить имя профиля",
"sv_SE": "Spara profilnamn",
"th_TH": "บันทึกชื่อโปรไฟล์",
"tr_TR": "Profil İsmini Kaydet",
@@ -11375,7 +11325,7 @@
"el_GR": "Αλλαγή Εικόνας Προφίλ",
"en_US": "Change Profile Image",
"es_ES": "Cambiar imagen de perfil",
- "fr_FR": "Changer l'image du profil",
+ "fr_FR": "Changer l'Image de Profil",
"he_IL": "שנה תמונת פרופיל",
"it_IT": "Cambia immagine profilo",
"ja_JP": "プロファイル画像を変更",
@@ -11400,7 +11350,7 @@
"el_GR": "Διαθέσιμα Προφίλ Χρηστών:",
"en_US": "Available User Profiles:",
"es_ES": "Perfiles de usuario disponibles:",
- "fr_FR": "Profils utilisateurs disponibles :",
+ "fr_FR": "Profils Utilisateurs Disponibles :",
"he_IL": "פרופילי משתמש זמינים:",
"it_IT": "Profili utente disponibili:",
"ja_JP": "利用可能なユーザプロファイル:",
@@ -11425,7 +11375,7 @@
"el_GR": "Προσθήκη Νέου Προφίλ",
"en_US": "Create Profile",
"es_ES": "Añadir nuevo perfil",
- "fr_FR": "Créer un profil",
+ "fr_FR": "Créer un Profil",
"he_IL": "צור פרופיל",
"it_IT": "Aggiungi nuovo profilo",
"ja_JP": "プロファイルを作成",
@@ -11500,7 +11450,7 @@
"el_GR": "Επιλέξτε ψευδώνυμο",
"en_US": "Choose a Nickname",
"es_ES": "Escoge un apodo",
- "fr_FR": "Choisir un pseudo",
+ "fr_FR": "Choisir un Pseudonyme",
"he_IL": "בחרו כינוי",
"it_IT": "Scegli un soprannome",
"ja_JP": "ニックネームを選択",
@@ -11525,7 +11475,7 @@
"el_GR": "Επιλογή Εικόνας Προφίλ",
"en_US": "Profile Image Selection",
"es_ES": "Selección de imagen de perfil",
- "fr_FR": "Sélection de l'image du profil",
+ "fr_FR": "Sélection de l'Image de Profil",
"he_IL": "בחירת תמונת פרופיל",
"it_IT": "Selezione dell'immagine profilo",
"ja_JP": "プロファイル画像選択",
@@ -11550,7 +11500,7 @@
"el_GR": "Επιλέξτε μία Εικόνα Προφίλ",
"en_US": "Choose a Profile Image",
"es_ES": "Elige una imagen de perfil",
- "fr_FR": "Choisir l'image du profil",
+ "fr_FR": "Choisir l'Image de Profil",
"he_IL": "בחרו תמונת פרופיל",
"it_IT": "Scegli un'immagine profilo",
"ja_JP": "プロファイル画像を選択",
@@ -11625,7 +11575,7 @@
"el_GR": "Επιλέξτε Avatar από Firmware",
"en_US": "Select Firmware Avatar",
"es_ES": "Seleccionar avatar del firmware",
- "fr_FR": "Choisir un avatar du firmware",
+ "fr_FR": "Choisir un Avatar du Firmware",
"he_IL": "בחרו אוואטר קושחה",
"it_IT": "Seleziona avatar dal firmware",
"ja_JP": "ファームウェア内のアバターを選択",
@@ -11650,7 +11600,7 @@
"el_GR": "Διάλογος Εισαγωγής",
"en_US": "Input Dialog",
"es_ES": "Cuadro de diálogo de entrada",
- "fr_FR": "Boîte de saisie",
+ "fr_FR": "Boîte de Saisie",
"he_IL": "דיאלוג קלט",
"it_IT": "Finestra di input",
"ja_JP": "入力ダイアログ",
@@ -11658,7 +11608,7 @@
"no_NO": "Dialogboksen Inndata",
"pl_PL": "Okno Dialogowe Wprowadzania",
"pt_BR": "Diálogo de texto",
- "ru_RU": "Диалоговое окно ввода",
+ "ru_RU": "Окно ввода",
"sv_SE": "Inmatningsdialog",
"th_TH": "กล่องโต้ตอบการป้อนข้อมูล",
"tr_TR": "Giriş Yöntemi Diyaloğu",
@@ -11675,7 +11625,7 @@
"el_GR": "ΟΚ",
"en_US": "OK",
"es_ES": "Aceptar",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "בסדר",
"it_IT": "",
"ja_JP": "",
@@ -11683,7 +11633,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "ОК",
+ "ru_RU": null,
"sv_SE": "Ok",
"th_TH": "ตกลง",
"tr_TR": "Tamam",
@@ -11725,7 +11675,7 @@
"el_GR": "",
"en_US": "Cancelling",
"es_ES": "",
- "fr_FR": "Annulation en cours",
+ "fr_FR": "Annulation en Cours",
"he_IL": "",
"it_IT": "Annullamento in corso",
"ja_JP": "",
@@ -11735,7 +11685,7 @@
"pt_BR": "Cancelando",
"ru_RU": "Отмена",
"sv_SE": "Avbryter",
- "th_TH": "",
+ "th_TH": "กำลังทำการยกเลิก",
"tr_TR": "",
"uk_UA": "Скасування",
"zh_CN": "正在取消",
@@ -11760,7 +11710,7 @@
"pt_BR": "Fechar",
"ru_RU": "Закрыть",
"sv_SE": "Stäng",
- "th_TH": "",
+ "th_TH": "ปิด",
"tr_TR": "",
"uk_UA": "Закрити",
"zh_CN": "关闭",
@@ -11775,7 +11725,7 @@
"el_GR": "Επιλογή Ονόματος Προφίλ",
"en_US": "Choose a Profile Name",
"es_ES": "Introducir nombre de perfil",
- "fr_FR": "Choisir un nom de profil",
+ "fr_FR": "Choisir un Nom de Profil",
"he_IL": "בחרו את שם הפרופיל",
"it_IT": "Scegli il nome del profilo",
"ja_JP": "プロファイル名を選択",
@@ -11800,7 +11750,7 @@
"el_GR": "Εισαγωγή Ονόματος Προφίλ",
"en_US": "Please Enter a Profile Name",
"es_ES": "Por favor elige un nombre de usuario",
- "fr_FR": "Veuillez saisir un nom de profil.",
+ "fr_FR": "Veuillez Saisir un Nom de Profil.",
"he_IL": "אנא הזינו שם לפרופיל",
"it_IT": "Digita un nome profilo",
"ja_JP": "プロファイル名を入力してください",
@@ -11825,7 +11775,7 @@
"el_GR": "(Σύνολο Χαρακτήρων: {0})",
"en_US": "(Max Length: {0})",
"es_ES": "(Máximo de caracteres: {0})",
- "fr_FR": "(Longueur max.: {0})",
+ "fr_FR": "(Longueur Max.: {0})",
"he_IL": "(אורך מרבי: {0})",
"it_IT": "(Lunghezza massima: {0})",
"ja_JP": "(最大長: {0})",
@@ -11850,7 +11800,7 @@
"el_GR": "Επιλογή",
"en_US": "Choose Avatar",
"es_ES": "Escoger",
- "fr_FR": "Choisir un avatar",
+ "fr_FR": "Choisir un Avatar",
"he_IL": "בחרו דמות",
"it_IT": "Scegli",
"ja_JP": "選択",
@@ -11875,7 +11825,7 @@
"el_GR": "Ορισμός Χρώματος Φόντου",
"en_US": "Set Background Color",
"es_ES": "Establecer color de fondo",
- "fr_FR": "Choisir une couleur de fond",
+ "fr_FR": "Choisir une Couleur de Fond",
"he_IL": "הגדר צבע רקע",
"it_IT": "Imposta colore di sfondo",
"ja_JP": "背景色を指定",
@@ -11925,7 +11875,7 @@
"el_GR": "Φόρτωση Προφίλ",
"en_US": "Load Profile",
"es_ES": "Cargar perfil",
- "fr_FR": "Charger un profil",
+ "fr_FR": "Charger un Profil",
"he_IL": "טען פרופיל",
"it_IT": "Carica profilo",
"ja_JP": "プロファイルをロード",
@@ -11960,7 +11910,7 @@
"pt_BR": "Ver Perfil",
"ru_RU": "Показать профиль",
"sv_SE": "Visa profil",
- "th_TH": "",
+ "th_TH": "ดูโปรไฟล์",
"tr_TR": "",
"uk_UA": "Показати профіль",
"zh_CN": "预览配置文件",
@@ -11975,7 +11925,7 @@
"el_GR": "Προσθήκη Προφίλ",
"en_US": "Add Profile",
"es_ES": "Agregar perfil",
- "fr_FR": "Ajouter un profil",
+ "fr_FR": "Ajouter un Profil",
"he_IL": "הוסף פרופיל",
"it_IT": "Aggiungi profilo",
"ja_JP": "プロファイルを追加",
@@ -12000,7 +11950,7 @@
"el_GR": "Κατάργηση Προφίλ",
"en_US": "Remove Profile",
"es_ES": "Eliminar perfil",
- "fr_FR": "Supprimer un profil",
+ "fr_FR": "Supprimer un Profil",
"he_IL": "הסר פרופיל",
"it_IT": "Rimuovi profilo",
"ja_JP": "プロファイルを削除",
@@ -12025,7 +11975,7 @@
"el_GR": "Αποθήκευση Προφίλ",
"en_US": "Save Profile",
"es_ES": "Guardar perfil",
- "fr_FR": "Enregistrer un profil",
+ "fr_FR": "Enregistrer un Profil",
"he_IL": "שמור פרופיל",
"it_IT": "Salva profilo",
"ja_JP": "プロファイルをセーブ",
@@ -12075,7 +12025,7 @@
"el_GR": "Λήψη Στιγμιότυπου",
"en_US": "Take Screenshot",
"es_ES": "Captura de pantalla",
- "fr_FR": "Prendre une capture d'écran",
+ "fr_FR": "Prendre une Capture d'Écran",
"he_IL": "צלם מסך",
"it_IT": "Cattura uno screenshot",
"ja_JP": "スクリーンショットを撮影",
@@ -12100,7 +12050,7 @@
"el_GR": "Απόκρυψη UI",
"en_US": "Hide UI",
"es_ES": "Ocultar interfaz",
- "fr_FR": "Masquer l'interface",
+ "fr_FR": "Masquer l'Interface Utilisateur",
"he_IL": "הסתר ממשק משתמש ",
"it_IT": "Nascondi l'interfaccia",
"ja_JP": "UIを隠す",
@@ -12125,7 +12075,7 @@
"el_GR": "Εκτέλεση Εφαρμογής",
"en_US": "Run Application",
"es_ES": "Ejecutar aplicación",
- "fr_FR": "Démarrer l'application",
+ "fr_FR": "Démarrer l'Application",
"he_IL": "הרץ יישום",
"it_IT": "Esegui applicazione",
"ja_JP": "アプリケーションを実行",
@@ -12133,7 +12083,7 @@
"no_NO": "Kjør programmet",
"pl_PL": "Uruchom aplikację ",
"pt_BR": "Executar Aplicativo",
- "ru_RU": "Запуск приложения",
+ "ru_RU": "Запуск",
"sv_SE": "Kör applikation",
"th_TH": "เปิดใช้งานแอปพลิเคชัน",
"tr_TR": "Uygulamayı Çalıştır",
@@ -12150,7 +12100,7 @@
"el_GR": "Εναλλαγή Αγαπημένου",
"en_US": "Toggle Favorite",
"es_ES": "Marcar favorito",
- "fr_FR": "Basculer favori",
+ "fr_FR": "Basculer Favori",
"he_IL": "למתג העדפה",
"it_IT": "Preferito",
"ja_JP": "お気に入りを切り替え",
@@ -12158,7 +12108,7 @@
"no_NO": "Vis/Skjul favoritter",
"pl_PL": "Przełącz na ulubione",
"pt_BR": "Marcar como Favorito",
- "ru_RU": "Добавить в избранное",
+ "ru_RU": "Добавить/Убрать статус избранного",
"sv_SE": "Växla som favorit",
"th_TH": "สลับรายการโปรด",
"tr_TR": "Favori Ayarla",
@@ -12200,7 +12150,7 @@
"el_GR": "",
"en_US": "Auto",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "Automatico",
"ja_JP": "",
@@ -12325,11 +12275,11 @@
"el_GR": "Ισχυρός Πολλαπλασιαστής Δόνησης",
"en_US": "Strong Rumble Multiplier",
"es_ES": "Multiplicador de vibraciones fuertes",
- "fr_FR": "Multiplicateur de vibrations fortes",
+ "fr_FR": "Multiplicateur de Vibrations Fortes",
"he_IL": "העצמת רטט חזק",
"it_IT": "Moltiplicatore vibrazione forte",
"ja_JP": "強振動の補正値",
- "ko_KR": "강력한 진동 증폭기",
+ "ko_KR": "강진동 보정폭",
"no_NO": "Sterk Vibrasjon multiplikator",
"pl_PL": "Mnożnik mocnych wibracji",
"pt_BR": "Multiplicador de Vibração Forte",
@@ -12350,11 +12300,11 @@
"el_GR": "Αδύναμος Πολλαπλασιαστής Δόνησης",
"en_US": "Weak Rumble Multiplier",
"es_ES": "Multiplicador de vibraciones débiles",
- "fr_FR": "Multiplicateur de vibrations faibles",
+ "fr_FR": "Multiplicateur de Vibrations Faibles",
"he_IL": "מכפיל רטט חלש",
"it_IT": "Moltiplicatore vibrazione debole",
"ja_JP": "弱振動の補正値",
- "ko_KR": "약한 진동 증폭기",
+ "ko_KR": "약진동 보정폭",
"no_NO": "Svak Vibrasjon multiplikator",
"pl_PL": "Mnożnik słabych wibracji",
"pt_BR": "Multiplicador de Vibração Fraca",
@@ -12425,7 +12375,7 @@
"el_GR": "{0} - Επιβεβαίωση",
"en_US": "{0} - Confirmation",
"es_ES": "{0} - Confirmación",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "{0} - אישור",
"it_IT": "{0} - Conferma",
"ja_JP": "{0} - 確認",
@@ -12583,7 +12533,7 @@
"no_NO": "Er du sikker på at du ønsker å lukke Ryujinx?",
"pl_PL": "Czy na pewno chcesz zamknąć Ryujinx?",
"pt_BR": "Tem certeza que deseja fechar o Ryujinx?",
- "ru_RU": "Вы уверены, что хотите выйти из Ryujinx?",
+ "ru_RU": "Вы уверены что хотите завершить Ryujinx?",
"sv_SE": "Är du säker på att du vill avsluta Ryujinx?",
"th_TH": "คุณแน่ใจหรือไม่ว่าต้องการปิด Ryujinx หรือไม่?",
"tr_TR": "Ryujinx'i kapatmak istediğinizden emin misiniz?",
@@ -12608,7 +12558,7 @@
"no_NO": "Alle ulagrede data vil gå tapt!",
"pl_PL": "Wszystkie niezapisane dane zostaną utracone!",
"pt_BR": "Todos os dados que não foram salvos serão perdidos!",
- "ru_RU": "Все несохранённые данные будут потеряны",
+ "ru_RU": "Все несохранённые данные будут потеряны!",
"sv_SE": "Allt data som inte sparats kommer att förloras!",
"th_TH": "ข้อมูลทั้งหมดที่ไม่ได้บันทึกทั้งหมดจะสูญหาย!",
"tr_TR": "Kaydedilmeyen bütün veriler kaybedilecek!",
@@ -12633,7 +12583,7 @@
"no_NO": "Det oppstod en feil under oppretting av den angitte lagredata: {0}",
"pl_PL": "Wystąpił błąd podczas tworzenia określonych zapisanych danych: {0}",
"pt_BR": "Ocorreu um erro ao criar os dados salvos especificados: {0}",
- "ru_RU": "Произошла ошибка при создании указанных данных сохранения: {0}",
+ "ru_RU": "Произошла ошибка при создании указанного сохранения: {0}",
"sv_SE": "Det inträffade ett fel vid skapandet av angivet sparat spel: {0}",
"th_TH": "มีข้อผิดพลาดในการสร้างข้อมูลบันทึกที่ระบุ: {0}",
"tr_TR": "Belirtilen kayıt verisi oluşturulurken bir hata oluştu: {0}",
@@ -12658,7 +12608,7 @@
"no_NO": "Det oppstod en feil under oppretting av den angitte lagredata: {0}",
"pl_PL": "Wystąpił błąd podczas próby znalezienia określonych zapisanych danych: {0}",
"pt_BR": "Ocorreu um erro ao encontrar os dados salvos especificados: {0}",
- "ru_RU": "Произошла ошибка при поиске указанных данных сохранения: {0}",
+ "ru_RU": "Произошла ошибка при поиске указанного сохранения: {0}",
"sv_SE": "Det inträffade ett fel vid sökandet av angivet sparat spel: {0}",
"th_TH": "มีข้อผิดพลาดในการค้นหาข้อมูลบันทึกที่ระบุไว้: {0}",
"tr_TR": "Belirtilen kayıt verisi bulunmaya çalışırken hata: {0}",
@@ -12758,7 +12708,7 @@
"no_NO": "Uttrekksfeil. Hoveddelen av NCA var ikke tilstede i valgt fil.",
"pl_PL": "Niepowodzenie podczas wypakowywania. W wybranym pliku nie było głównego NCA.",
"pt_BR": "Falha na extração. O NCA principal não foi encontrado no arquivo selecionado.",
- "ru_RU": "Ошибка извлечения. Основной NCA не присутствовал в выбранном файле.",
+ "ru_RU": "Ошибка извлечения. Основной NCA отсутствовал в выбранном файле.",
"sv_SE": "Fel vid extrahering. Main NCA hittades inte i vald fil.",
"th_TH": "เกิดความล้มเหลวในการแตกไฟล์เนื่องจากไม่พบ NCA หลักในไฟล์ที่เลือก",
"tr_TR": "Ayıklama hatası. Ana NCA seçilen dosyada bulunamadı.",
@@ -12850,7 +12800,7 @@
"el_GR": "Ακύρωση Ενημέρωσης!",
"en_US": "Update canceled!",
"es_ES": "¡Cancelando actualización!",
- "fr_FR": "Annuler la mise à jour !",
+ "fr_FR": "Mise à Jour annulée !",
"he_IL": "מבטל עדכון!",
"it_IT": "Annullamento dell'aggiornamento in corso!",
"ja_JP": "アップデータをキャンセル中!",
@@ -12858,7 +12808,7 @@
"no_NO": "Avbryter oppdatering!",
"pl_PL": "Anulowanie aktualizacji!",
"pt_BR": "Atualização Cancelada!",
- "ru_RU": "Отмена обновления...",
+ "ru_RU": "Обновление отменено!",
"sv_SE": "Avbryter uppdatering!",
"th_TH": "ยกเลิกการอัพเดต!",
"tr_TR": "Güncelleme iptal ediliyor!",
@@ -12875,7 +12825,7 @@
"el_GR": "Χρησιμοποιείτε ήδη την πιο ενημερωμένη έκδοση του Ryujinx!",
"en_US": "You are already using the latest version of Ryujinx!",
"es_ES": "¡Ya tienes la versión más reciente de Ryujinx!",
- "fr_FR": "Vous utilisez déjà la dernière version de Ryujinx !",
+ "fr_FR": "Vous utilisez déjà la version la plus récente de Ryujinx !",
"he_IL": "אתם כבר משתמשים בגרסה המעודכנת ביותר של ריוג'ינקס!",
"it_IT": "Stai già usando la versione più recente di Ryujinx!",
"ja_JP": "最新バージョンの Ryujinx を使用中です!",
@@ -12883,7 +12833,7 @@
"no_NO": "Du bruker allerede den nyeste versjonen av Ryujinx!",
"pl_PL": "Używasz już najnowszej wersji Ryujinx!",
"pt_BR": "Você já está usando a versão mais recente do Ryujinx!",
- "ru_RU": "Вы используете самую последнюю версию Ryujinx",
+ "ru_RU": "Вы уже используете последнюю версию Ryujinx!",
"sv_SE": "Du använder redan den senaste versionen av Ryujinx!",
"th_TH": "คุณกำลังใช้ Ryujinx เวอร์ชั่นที่อัปเดตล่าสุด!",
"tr_TR": "Zaten Ryujinx'in en güncel sürümünü kullanıyorsunuz!",
@@ -12900,7 +12850,7 @@
"el_GR": "",
"en_US": "Failed to convert the Ryujinx version received from the update server.",
"es_ES": "",
- "fr_FR": "Échec de la conversion de la version de Ryujinx reçue du serveur de mise à jour.",
+ "fr_FR": "Échec de la conversion de la version de Ryujinx reçue du serveur de Mise à Jour.",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -12908,9 +12858,9 @@
"no_NO": "Kunne ikke konvertere Ryujinx-versjonen som ble mottatt fra oppdateringsserveren.",
"pl_PL": "",
"pt_BR": "Falha em atualizar a versão do Ryujinx recebida do servidor de atualização.",
- "ru_RU": "",
+ "ru_RU": "Не удалось преобразовать версию Ryujinx, полученную с сервера обновлений.",
"sv_SE": "Det gick inte att konvertera Ryujinx-versionen som mottogs från uppdateringsservern.",
- "th_TH": "",
+ "th_TH": "ไม่สามารถแปลงเวอร์ชัน Ryujinx ที่ได้รับจากเซิร์ฟเวอร์อัปเดตได้",
"tr_TR": "",
"uk_UA": "Не вдалося конвертувати версію Ryujinx, отриману з сервера оновлень.",
"zh_CN": "无法转换从更新服务器接收的 Ryujinx 版本。",
@@ -12925,7 +12875,7 @@
"el_GR": "Λήψη Ενημέρωσης...",
"en_US": "Downloading Update...",
"es_ES": "Descargando actualización...",
- "fr_FR": "Téléchargement de la mise à jour...",
+ "fr_FR": "Téléchargement de la Mise à Jour...",
"he_IL": "מוריד עדכון...",
"it_IT": "Download dell'aggiornamento...",
"ja_JP": "アップデートをダウンロード中...",
@@ -12954,7 +12904,7 @@
"he_IL": "אנא המתן, המחקה מתארגן מחדש",
"it_IT": "Attendere prego, l'emulatore si sta riavviando",
"ja_JP": "お待ちください、エミュレーターが再起動しています",
- "ko_KR": "잠시만 기다려 주세요, 에뮬레이터가 재시작 중입니다",
+ "ko_KR": "잠시만 기다려 주세요, 에뮬레이터가 다시 시작 중입니다",
"no_NO": "Vennligst vent, emulatoren starter på nytt",
"pl_PL": "Proszę czekać, emulator jest w trakcie ponownego uruchamiania",
"pt_BR": "Por favor, aguarde, o emulador está reiniciando",
@@ -12975,7 +12925,7 @@
"el_GR": "Εξαγωγή Ενημέρωσης...",
"en_US": "Extracting Update...",
"es_ES": "Extrayendo actualización...",
- "fr_FR": "Extraction de la mise à jour…",
+ "fr_FR": "Extraction de la Mise à Jour…",
"he_IL": "מחלץ עדכון...",
"it_IT": "Estrazione dell'aggiornamento...",
"ja_JP": "アップデートを展開中...",
@@ -13000,7 +12950,7 @@
"el_GR": "Μετονομασία Ενημέρωσης...",
"en_US": "Renaming Update...",
"es_ES": "Renombrando actualización...",
- "fr_FR": "Renommage de la mise à jour...",
+ "fr_FR": "Renommage de la Mise à Jour...",
"he_IL": "משנה את שם העדכון...",
"it_IT": "Ridenominazione dell'aggiornamento...",
"ja_JP": "アップデートをリネーム中...",
@@ -13025,11 +12975,11 @@
"el_GR": "Προσθήκη Νέας Ενημέρωσης...",
"en_US": "Adding New Update...",
"es_ES": "Aplicando actualización...",
- "fr_FR": "Ajout d'une nouvelle mise à jour...",
+ "fr_FR": "Ajout d'une nouvelle Mise à Jour...",
"he_IL": "מוסיף עדכון חדש...",
"it_IT": "Aggiunta del nuovo aggiornamento...",
"ja_JP": "新規アップデートを追加中...",
- "ko_KR": "새 업데이트 추가 중...",
+ "ko_KR": "신규 업데이트 추가 중...",
"no_NO": "Legger til ny oppdatering...",
"pl_PL": "Dodawanie Nowej Aktualizacji...",
"pt_BR": "Adicionando Nova Atualização...",
@@ -13060,7 +13010,7 @@
"pt_BR": "Ver Registro de Alterações",
"ru_RU": "Показать список изменений",
"sv_SE": "Visa ändringslogg",
- "th_TH": "",
+ "th_TH": "แสดงบันทึกการเปลี่ยนแปลง",
"tr_TR": "",
"uk_UA": "Показати список змін",
"zh_CN": "显示更新日志",
@@ -13083,7 +13033,7 @@
"no_NO": "Oppdateringen er fullført!",
"pl_PL": "Aktualizacja Zakończona!",
"pt_BR": "Atualização Concluída!",
- "ru_RU": "Обновление завершено",
+ "ru_RU": "Обновление завершено!",
"sv_SE": "Uppdatering färdig!",
"th_TH": "อัปเดตเสร็จสมบูรณ์แล้ว!",
"tr_TR": "Güncelleme Tamamlandı!",
@@ -13133,7 +13083,7 @@
"no_NO": "Du er ikke tilkoblet internett",
"pl_PL": "Nie masz połączenia z Internetem!",
"pt_BR": "Você não está conectado à Internet!",
- "ru_RU": "Вы не подключены к интернету",
+ "ru_RU": "Вы не подключены к интернету!",
"sv_SE": "Du är inte ansluten till internet!",
"th_TH": "คุณไม่ได้เชื่อมต่อกับอินเทอร์เน็ต!",
"tr_TR": "İnternete bağlı değilsiniz!",
@@ -13158,7 +13108,7 @@
"no_NO": "Kontroller at du har en fungerende Internett-tilkobling!",
"pl_PL": "Sprawdź, czy masz działające połączenie internetowe!",
"pt_BR": "Por favor, certifique-se de que você tem uma conexão funcional à Internet!",
- "ru_RU": "Убедитесь, что у вас работает подключение к интернету",
+ "ru_RU": "Убедитесь, что у вас работает подключение к интернету!",
"sv_SE": "Försäkra dig om att du har en fungerande internetanslutning!",
"th_TH": "โปรดตรวจสอบว่าคุณมีการเชื่อมต่ออินเทอร์เน็ตว่ามีการใช้งานได้หรือไม่!",
"tr_TR": "Lütfen aktif bir internet bağlantınız olduğunu kontrol edin!",
@@ -13183,7 +13133,7 @@
"no_NO": "Du kan ikke oppdatere en skitten versjon av Ryujinx!",
"pl_PL": "Nie możesz zaktualizować Dirty wersji Ryujinx!",
"pt_BR": "Você não pode atualizar uma compilação Dirty do Ryujinx!",
- "ru_RU": "Вы не можете обновлять Dirty Build",
+ "ru_RU": "Вы не можете обновить грязную (Dirty) сборку Ryujinx!",
"sv_SE": "Du kan inte uppdatera en Dirty build av Ryujinx!",
"th_TH": "คุณไม่สามารถอัปเดต Dirty build ของ Ryujinx ได้!",
"tr_TR": "Ryujinx'in Dirty build'lerini güncelleyemezsiniz!",
@@ -13208,7 +13158,7 @@
"no_NO": "Vennligst last ned Ryujinx på https://ryujinx.app/download hvis du ser etter en støttet versjon.",
"pl_PL": "Pobierz Ryujinx ze strony https://ryujinx.app/download, jeśli szukasz obsługiwanej wersji.",
"pt_BR": "Por favor, baixe o Ryujinx em https://ryujinx.app/download se está procurando por uma versão suportada.",
- "ru_RU": "Загрузите Ryujinx по адресу https://ryujinx.app/download если вам нужна поддерживаемая версия.",
+ "ru_RU": "Пожалуйста, скачайте Ryujinx с сайта https://ryujinx.app/download, если вы ищете поддерживаемую версию.",
"sv_SE": "Hämta Ryujinx från https://ryujinx.app/download om du letar efter en version som stöds.",
"th_TH": "โปรดดาวน์โหลด Ryujinx ได้ที่ https://ryujinx.app/download หากคุณกำลังมองหาเวอร์ชั่นที่รองรับ",
"tr_TR": "Desteklenen bir sürüm için lütfen Ryujinx'i https://ryujinx.app/download sitesinden indirin.",
@@ -13225,7 +13175,7 @@
"el_GR": "Απαιτείται Επανεκκίνηση",
"en_US": "Restart Required",
"es_ES": "Se necesita reiniciar",
- "fr_FR": "Redémarrage requis",
+ "fr_FR": "Redémarrage Requis",
"he_IL": "אתחול נדרש",
"it_IT": "Riavvio richiesto",
"ja_JP": "再起動が必要",
@@ -13283,7 +13233,7 @@
"no_NO": "Vil du starte på nytt",
"pl_PL": "Czy chcesz uruchomić ponownie?",
"pt_BR": "Deseja reiniciar?",
- "ru_RU": "Выполнить перезапуск?",
+ "ru_RU": "Хотите перезапустить?",
"sv_SE": "Vill du starta om",
"th_TH": "คุณต้องการรีสตาร์ทหรือไม่?",
"tr_TR": "Yeniden başlatmak ister misiniz",
@@ -13350,7 +13300,7 @@
"el_GR": "Δεν έχει εγκατασταθεί Firmware",
"en_US": "No Firmware Installed",
"es_ES": "No hay firmware instalado",
- "fr_FR": "Aucun Firmware installé",
+ "fr_FR": "Aucun Firmware Installé",
"he_IL": "לא מותקנת קושחה",
"it_IT": "Nessun firmware installato",
"ja_JP": "ファームウェアがインストールされていません",
@@ -13408,7 +13358,7 @@
"no_NO": "Filtyper ble installert!",
"pl_PL": "Pomyślnie zainstalowano typy plików!",
"pt_BR": "Tipos de arquivo instalados com sucesso!",
- "ru_RU": "Типы файлов успешно установлены",
+ "ru_RU": "Типы файлов успешно установлены!",
"sv_SE": "Filtyper har installerats!",
"th_TH": "ติดตั้งตามประเภทของไฟล์สำเร็จแล้ว!",
"tr_TR": "Dosya uzantıları başarıyla yüklendi!",
@@ -13458,7 +13408,7 @@
"no_NO": "Filtyper ble avinstallert!",
"pl_PL": "Pomyślnie odinstalowano typy plików!",
"pt_BR": "Tipos de arquivo desinstalados com sucesso!",
- "ru_RU": "Типы файлов успешно удалены",
+ "ru_RU": "Типы файлов успешно удалены!",
"sv_SE": "Filtyper avinstallerades!",
"th_TH": "ถอนการติดตั้งตามประเภทของไฟล์สำเร็จแล้ว!",
"tr_TR": "Dosya uzantıları başarıyla kaldırıldı!",
@@ -13525,7 +13475,7 @@
"el_GR": "",
"en_US": "XCI Trimmer Window",
"es_ES": "Ventana recortador XCI",
- "fr_FR": "Fenêtre de réduction de fichiers XCI",
+ "fr_FR": "Fenêtre de Réduction de Fichiers XCI",
"he_IL": "",
"it_IT": "Riduci dimensioni dei file XCI",
"ja_JP": "",
@@ -13533,9 +13483,9 @@
"no_NO": "XCI Trimmervindu",
"pl_PL": "",
"pt_BR": "Janela de Redução XCI",
- "ru_RU": "Окно триммера XCI",
+ "ru_RU": "Окно XCI триммера",
"sv_SE": "XCI-optimerare",
- "th_TH": "",
+ "th_TH": "หน้าต่างตัดแต่งไฟล์ XCI",
"tr_TR": "",
"uk_UA": "Вікно XCI Тримера",
"zh_CN": "XCI 文件瘦身窗口",
@@ -13550,7 +13500,7 @@
"el_GR": "Applet Χειρισμού",
"en_US": "Controller Applet",
"es_ES": "Applet de mandos",
- "fr_FR": "Programme Manette",
+ "fr_FR": "Applet de Manette",
"he_IL": "יישומון בקר",
"it_IT": "Applet del controller",
"ja_JP": "コントローラアプレット",
@@ -13575,7 +13525,7 @@
"el_GR": "Σφάλμα εμφάνισης του διαλόγου Μηνυμάτων: {0}",
"en_US": "Error displaying Message Dialog: {0}",
"es_ES": "Error al mostrar cuadro de diálogo: {0}",
- "fr_FR": "Erreur lors de l'affichage de la boîte de dialogue : {0}",
+ "fr_FR": "Erreur lors de l'affichage de la Boîte de Dialogue : {0}",
"he_IL": "שגיאה בהצגת דיאלוג ההודעה: {0}",
"it_IT": "Errore nella visualizzazione della finestra di dialogo: {0}",
"ja_JP": "メッセージダイアログ表示エラー: {0}",
@@ -13600,7 +13550,7 @@
"el_GR": "Σφάλμα εμφάνισης Λογισμικού Πληκτρολογίου: {0}",
"en_US": "Error displaying Software Keyboard: {0}",
"es_ES": "Error al mostrar teclado de software: {0}",
- "fr_FR": "Erreur lors de l'affichage du clavier logiciel: {0}",
+ "fr_FR": "Erreur lors de l'affichage du Clavier Logiciel: {0}",
"he_IL": "שגיאה בהצגת תוכנת המקלדת: {0}",
"it_IT": "Errore nella visualizzazione della tastiera software: {0}",
"ja_JP": "ソフトウェアキーボード表示エラー: {0}",
@@ -13625,7 +13575,7 @@
"el_GR": "Σφάλμα εμφάνισης του διαλόγου ErrorApplet: {0}",
"en_US": "Error displaying ErrorApplet Dialog: {0}",
"es_ES": "Error al mostrar díalogo ErrorApplet: {0}",
- "fr_FR": "Erreur lors de l'affichage de la boîte de dialogue ErrorApplet: {0}",
+ "fr_FR": "Erreur lors de l'affichage de la Boîte de Dialogue ErrorApplet: {0}",
"he_IL": "שגיאה בהצגת דיאלוג ErrorApplet: {0}",
"it_IT": "Errore nella visualizzazione della finestra dell'ErrorApplet: {0}",
"ja_JP": "エラーアプレットダイアログ表示エラー: {0}",
@@ -13658,13 +13608,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -13735,11 +13685,11 @@
"pt_BR": "API Amiibo",
"ru_RU": "API Amiibo",
"sv_SE": "Amiibo-API",
- "th_TH": "",
+ "th_TH": "อามิโบ้ API",
"tr_TR": "",
"uk_UA": "API Amiibo",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -13833,7 +13783,7 @@
"no_NO": "Standard profil kan ikke overskrives",
"pl_PL": "Profil Domyślny nie może zostać nadpisany",
"pt_BR": "O perfil Padrão não pode ser substituído",
- "ru_RU": "Профиль по умолчанию не может быть перезаписан",
+ "ru_RU": "Профиль по умолчанию не подлежит перезаписи",
"sv_SE": "Standardprofilen kan inte skrivas över",
"th_TH": "โปรไฟล์เริ่มต้นไม่สามารถเขียนทับได้",
"tr_TR": "Varsayılan Profil'in üstüne yazılamaz",
@@ -13850,7 +13800,7 @@
"el_GR": "Διαγραφή Προφίλ",
"en_US": "Deleting Profile",
"es_ES": "Eliminando perfil",
- "fr_FR": "Suppression du profil",
+ "fr_FR": "Suppression du Profil",
"he_IL": "מוחק פרופיל",
"it_IT": "Eliminazione profilo",
"ja_JP": "プロファイルを削除中",
@@ -13985,7 +13935,7 @@
"pt_BR": "Você está prestes a limpar todos os dados PPTC de:\n\n{0}\n\nTem certeza de que deseja continuar?",
"ru_RU": "Вы собираетесь удалить все данные PPTC из:\n\n{0}\n\nВы уверены, что хотите продолжить?",
"sv_SE": "Du är på väg att ta bort allt PPTC-data från:\n\n{0}\n\nÄr du säker på att du vill fortsätta?",
- "th_TH": "",
+ "th_TH": "คุณกำลังจะล้างข้อมูล PPTC ทั้งหมดจาก:\n\n{0}\n\nคุณแน่ใจหรือไม่ว่าต้องการดำเนินการต่อ?",
"tr_TR": "",
"uk_UA": "Ви збираєтесь видалити всі дані PPTC з:\n\n{0}\n\nБажаєте продовжити цю операцію?",
"zh_CN": "您正要清理 PPTC 数据:\n\n{0}\n\n您确实要继续吗?",
@@ -14083,7 +14033,7 @@
"no_NO": "UI-feil: Det valgte spillet har ikke en gyldig tittel-ID",
"pl_PL": "Błąd UI: Wybrana gra nie miała prawidłowego ID tytułu",
"pt_BR": "Erro de interface: O jogo selecionado não tem um ID de título válido",
- "ru_RU": "Ошибка пользовательского интерфейса: выбранная игра не имеет действительного ID.",
+ "ru_RU": "Ошибка пользовательского интерфейса: выбранная игра не имеет действительного ID",
"sv_SE": "Gränssnittsfel: Angivet spel saknar ett giltigt title ID",
"th_TH": "ข้อผิดพลาดของ UI: เกมที่เลือกไม่มีชื่อ ID ที่ถูกต้อง",
"tr_TR": "Arayüz hatası: Seçilen oyun geçerli bir title ID'ye sahip değil",
@@ -14108,7 +14058,7 @@
"no_NO": "En gyldig systemfastvare ble ikke funnet i {0}.",
"pl_PL": "Nie znaleziono prawidłowego firmware'u systemowego w {0}.",
"pt_BR": "Um firmware de sistema válido não foi encontrado em {0}.",
- "ru_RU": "Валидная системная прошивка не найдена в {0}.",
+ "ru_RU": "Не удалось найти действительную системную прошивку в {0}.",
"sv_SE": "Ett giltigt systemfirmware hittades inte i {0}.",
"th_TH": "ไม่พบเฟิร์มแวร์ของระบบที่ถูกต้อง {0}.",
"tr_TR": "{0} da geçerli bir sistem firmware'i bulunamadı.",
@@ -14225,7 +14175,7 @@
"el_GR": "Εγκατάσταση Firmware...",
"en_US": "Installing firmware...",
"es_ES": "Instalando firmware...",
- "fr_FR": "Installation du firmware...",
+ "fr_FR": "Installation du Firmware...",
"he_IL": "מתקין קושחה...",
"it_IT": "Installazione del firmware...",
"ja_JP": "ファームウェアをインストール中...",
@@ -14275,7 +14225,7 @@
"el_GR": "",
"en_US": "An invalid Keys file was found in {0}",
"es_ES": "Se halló un archivo Keys inválido en {0}",
- "fr_FR": "Un fichier de clés invalide a été trouvé dans {0}",
+ "fr_FR": "Un fichier de Clés invalide a été trouvé dans {0}",
"he_IL": "",
"it_IT": "È stato trovato un file di chiavi non valido in {0}",
"ja_JP": "",
@@ -14283,9 +14233,9 @@
"no_NO": "En ugyldig Keys-fil ble funnet i {0}.",
"pl_PL": "",
"pt_BR": "Um arquivo Chaves inválido foi encontrado em {0}",
- "ru_RU": "В {0} были найдены некорректные ключи",
+ "ru_RU": "В {0} найден некорректный файл ключей",
"sv_SE": "En ogiltig nyckelfil hittades i {0}",
- "th_TH": "",
+ "th_TH": "พบไฟล์ Keys ที่ไม่ถูกต้องใน {0}",
"tr_TR": "",
"uk_UA": "Виявлено неправильний файл ключів у теці {0}",
"zh_CN": "在 {0} 发现了一个无效的密匙文件",
@@ -14300,7 +14250,7 @@
"el_GR": "",
"en_US": "Install Keys",
"es_ES": "Instalar Keys",
- "fr_FR": "Installer des clés",
+ "fr_FR": "Installer des Clés",
"he_IL": "",
"it_IT": "Installa chiavi",
"ja_JP": "",
@@ -14310,7 +14260,7 @@
"pt_BR": "Instalar Chaves",
"ru_RU": "Установить ключи",
"sv_SE": "Installera nycklar",
- "th_TH": "",
+ "th_TH": "ติดตั้งไฟล์ Keys",
"tr_TR": "",
"uk_UA": "Встановлення Ключів",
"zh_CN": "安装密匙",
@@ -14325,7 +14275,7 @@
"el_GR": "",
"en_US": "New Keys file will be installed.",
"es_ES": "Un nuevo archivo Keys será instalado.",
- "fr_FR": "Nouveau fichier de clés sera installé.",
+ "fr_FR": "Nouveau fichier de Clés sera installé.",
"he_IL": "",
"it_IT": "Un nuovo file di chiavi sarà installato.",
"ja_JP": "",
@@ -14335,7 +14285,7 @@
"pt_BR": "O novo arquivo Chaves será instalado",
"ru_RU": "Будут установлены новые ключи.",
"sv_SE": "Ny nyckelfil kommer att installeras.",
- "th_TH": "",
+ "th_TH": "กำลังติดตั้งไฟล์ Keys ใหม่",
"tr_TR": "",
"uk_UA": "Новий файл Ключів буде встановлено",
"zh_CN": "将会安装新密匙文件",
@@ -14350,7 +14300,7 @@
"el_GR": "",
"en_US": "\n\nThis may replace some of the current installed Keys.",
"es_ES": "\n\nEsto puede reemplazar algunas de las Keys actualmente instaladas.",
- "fr_FR": "\n\nCela peut remplacer certaines des clés actuellement installées.",
+ "fr_FR": "\n\nCela peut remplacer certaines des Clés actuellement installées.",
"he_IL": "",
"it_IT": "\n\nAlcune delle chiavi già installate potrebbero essere sovrascritte.",
"ja_JP": "",
@@ -14358,9 +14308,9 @@
"no_NO": "\n\nDette kan erstatte noen av de nåværende installerte nøklene.",
"pl_PL": "",
"pt_BR": "\n\nIsso pode substituir algumas das chaves instaladas atualmente.",
- "ru_RU": "\n\nЭто действие может перезаписать установленные ключи.",
+ "ru_RU": "\n\nЭто может заменить некоторые из текущих установленных ключей.",
"sv_SE": "\n\nDetta kan ersätta några av de redan installerade nycklarna.",
- "th_TH": "",
+ "th_TH": "\n\nสิ่งนี้อาจทำให้ไฟล์ Keys บางส่วนที่ติดตั้งอยู่ถูกแทนที่",
"tr_TR": "",
"uk_UA": "\n\nЦе замінить собою поточні файли Ключів.",
"zh_CN": "\n\n这也许会替换掉一些当前已安装的密匙",
@@ -14385,7 +14335,7 @@
"pt_BR": "\n\nVocê quer continuar?",
"ru_RU": "\n\nХотите продолжить?",
"sv_SE": "\n\nVill du fortsätta?",
- "th_TH": "",
+ "th_TH": "\n\nคุณต้องการดำเนินการต่อหรือไม่?",
"tr_TR": "",
"uk_UA": "\n\nВи хочете продовжити?",
"zh_CN": "\n\n你想要继续吗?",
@@ -14400,7 +14350,7 @@
"el_GR": "",
"en_US": "Installing Keys...",
"es_ES": "Instalando Keys...",
- "fr_FR": "Installation des clés...",
+ "fr_FR": "Installation des Clés...",
"he_IL": "",
"it_IT": "Installazione delle chiavi...",
"ja_JP": "",
@@ -14410,7 +14360,7 @@
"pt_BR": "Instalando Chaves...",
"ru_RU": "Установка ключей...",
"sv_SE": "Installerar nycklar...",
- "th_TH": "",
+ "th_TH": "กำลังดำเนินการติดตั้ง Keys...",
"tr_TR": "",
"uk_UA": "Встановлення Ключів...",
"zh_CN": "安装密匙中。。。",
@@ -14425,7 +14375,7 @@
"el_GR": "",
"en_US": "New Keys file successfully installed.",
"es_ES": "Nuevo archivo Keys instalado con éxito.",
- "fr_FR": "Nouveau fichier de clés a été installé.",
+ "fr_FR": "Nouveau fichier de Clés a été installé.",
"he_IL": "",
"it_IT": "Nuovo file di chiavi installato con successo.",
"ja_JP": "",
@@ -14435,7 +14385,7 @@
"pt_BR": "Novo arquivo de chaves instalado com sucesso.",
"ru_RU": "Новые ключи были успешно установлены.",
"sv_SE": "Ny nyckelfil installerades.",
- "th_TH": "",
+ "th_TH": "การติดตั้งไฟล์ Keys ใหม่เสร็จสมบูรณ์แล้ว",
"tr_TR": "",
"uk_UA": "Нові ключі встановлено.",
"zh_CN": "已成功安装新密匙文件",
@@ -14500,7 +14450,7 @@
"el_GR": "Προσοχή - Μην Αποθηκευμένες Αλλαγές.",
"en_US": "Warning - Unsaved Changes",
"es_ES": "Advertencia - Cambios sin guardar",
- "fr_FR": "Avertissement - Modifications non enregistrées",
+ "fr_FR": "Avertissement - Modifications Non Enregistrées",
"he_IL": "אזהרה - שינויים לא שמורים",
"it_IT": "Attenzione - Modifiche non salvate",
"ja_JP": "警告 - 保存されていない変更",
@@ -14683,7 +14633,7 @@
"no_NO": "Den angitte mappen inneholder ikke en modifikasjon!",
"pl_PL": "Podany katalog nie zawiera modyfikacji!",
"pt_BR": "O diretório especificado não contém um mod!",
- "ru_RU": "Выбранная папка не содержит модов",
+ "ru_RU": "Выбранная папка не содержит модов!",
"sv_SE": "Den angivna katalogen innehåller inte en modd!",
"th_TH": "ไดเร็กทอรีที่ระบุไม่มี ม็อดอยู่!",
"tr_TR": "",
@@ -14700,7 +14650,7 @@
"el_GR": "",
"en_US": "Failed to Delete: Could not find the parent directory for mod \"{0}\"!",
"es_ES": "Error al eliminar: ¡No se pudo encontrar el directorio principal para el mod \"{0}\"!",
- "fr_FR": "Échec de la suppression : impossible de trouver le répertoire parent du mod \"{0} \" !",
+ "fr_FR": "Échec de la suppression : impossible de trouver le répertoire parent du mod \"{0}\" !",
"he_IL": "נכשל למחוק: לא היה ניתן למצוא את תיקיית האב למוד \"{0}\"!\n",
"it_IT": "Eliminazione non riuscita: impossibile trovare la directory superiore per la mod \"{0}\"!",
"ja_JP": "削除に失敗しました: Mod \"{0}\" の親ディレクトリが見つかりませんでした!",
@@ -14708,7 +14658,7 @@
"no_NO": "Kunne ikke slette: Fant ikke overordnet mappe for mod \"{0}\"!",
"pl_PL": "Nie udało się usunąć: Nie można odnaleźć katalogu nadrzędnego dla modyfikacji \"{0}\"!",
"pt_BR": "Falha ao excluir: Não foi possível encontrar o diretório pai do mod \"{0}\"!",
- "ru_RU": "Невозможно удалить: не удалось найти папку мода \"{0}\"",
+ "ru_RU": "Невозможно удалить: не удалось найти папку мода \"{0}\"!",
"sv_SE": "Misslyckades med att ta bort: Kunde inte hitta föräldrakatalogen för modden \"{0}\"!",
"th_TH": "ไม่สามารถลบ: ไม่พบไดเร็กทอรีหลักสำหรับ ม็อด \"{0}\"!",
"tr_TR": "Silme Başarısız: \"{0}\" Modu için üst dizin bulunamadı! ",
@@ -14733,7 +14683,7 @@
"no_NO": "Den angitte filen inneholder ikke en DLC for den valgte tittelen!",
"pl_PL": "Określony plik nie zawiera DLC dla wybranego tytułu!",
"pt_BR": "O arquivo especificado não contém DLCs para o título selecionado!",
- "ru_RU": "Указанный файл не содержит DLC для выбранной игры",
+ "ru_RU": "Указанный файл не содержит DLC для выбранной игры!",
"sv_SE": "Den angivna filen innehåller inte en DLC för angivet spel!",
"th_TH": "ไฟล์ที่ระบุไม่มี DLC สำหรับชื่อที่เลือก!",
"tr_TR": "Belirtilen dosya seçilen oyun için DLC içermiyor!",
@@ -14900,7 +14850,7 @@
"el_GR": "Το αρχείο δεν περιέχει ενημέρωση για τον επιλεγμένο τίτλο!",
"en_US": "The specified file does not contain an update for the selected title!",
"es_ES": "¡Ese archivo no contiene una actualización para el título seleccionado!",
- "fr_FR": "Le fichier spécifié ne contient pas de mise à jour pour le titre sélectionné !",
+ "fr_FR": "Le fichier spécifié ne contient pas de Mise à Jour pour le titre sélectionné !",
"he_IL": "הקובץ שצוין אינו מכיל עדכון עבור המשחק שנבחר!",
"it_IT": "Il file specificato non contiene un aggiornamento per il titolo selezionato!",
"ja_JP": "選択されたファイルはこのタイトル用のアップデートではありません!",
@@ -14908,7 +14858,7 @@
"no_NO": "Den angitte filen inneholder ikke en oppdatering for den valgte tittelen!",
"pl_PL": "Określony plik nie zawiera aktualizacji dla wybranego tytułu!",
"pt_BR": "O arquivo especificado não contém atualizações para o título selecionado!",
- "ru_RU": "Указанный файл не содержит обновлений для выбранного приложения",
+ "ru_RU": "Указанный файл не содержит обновления для выбранного приложения!",
"sv_SE": "Angiven fil innehåller inte en uppdatering för angivet spel!",
"th_TH": "ไฟล์ที่ระบุไม่มีการอัพเดตสำหรับชื่อเรื่องที่เลือก!",
"tr_TR": "Belirtilen dosya seçilen oyun için güncelleme içermiyor!",
@@ -14933,7 +14883,7 @@
"no_NO": "Advarsel - Backend Tråd",
"pl_PL": "Ostrzeżenie — Wątki Backend",
"pt_BR": "Alerta - Enfileiramento do Renderizador Gráfico",
- "ru_RU": "Предупреждение: многопоточность в бэкенде",
+ "ru_RU": "Предупреждение: Многопоточность в бэкенде",
"sv_SE": "Varning - Backend Threading",
"th_TH": "คำเตือน - การทำเธรดแบ็กเอนด์",
"tr_TR": "Uyarı - Backend Threading",
@@ -15075,7 +15025,7 @@
"el_GR": "Αυτόματο",
"en_US": "Auto",
"es_ES": "Automático",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "אוטומטי",
"it_IT": "Automatico",
"ja_JP": "自動",
@@ -15225,7 +15175,7 @@
"el_GR": "Παύση",
"en_US": "Pause",
"es_ES": "Pausar",
- "fr_FR": "",
+ "fr_FR": "Pauser",
"he_IL": "הפסק",
"it_IT": "Metti in pausa",
"ja_JP": "一時停止",
@@ -15233,7 +15183,7 @@
"no_NO": "Stans midlertidig",
"pl_PL": "Pauza",
"pt_BR": "Pausar",
- "ru_RU": "Пауза эмуляции",
+ "ru_RU": "Пауза",
"sv_SE": "Paus",
"th_TH": "หยุดชั่วคราว",
"tr_TR": "Durdur",
@@ -15275,7 +15225,7 @@
"el_GR": "Κάντε κλικ για να ανοίξετε τον ιστότοπο Ryujinx στο προεπιλεγμένο πρόγραμμα περιήγησης.",
"en_US": "Click to open the Ryujinx website in your default browser.",
"es_ES": "Haz clic para abrir el sitio web de Ryujinx en tu navegador predeterminado.",
- "fr_FR": "Cliquez pour ouvrir le site de Ryujinx dans votre navigateur par défaut",
+ "fr_FR": "Cliquez pour ouvrir le site de Ryujinx dans votre navigateur par défaut.",
"he_IL": "לחץ כדי לפתוח את אתר ריוג'ינקס בדפדפן ברירת המחדל שלך.",
"it_IT": "Clicca per aprire il sito web di Ryujinx nel tuo browser predefinito.",
"ja_JP": "クリックするとデフォルトのブラウザで Ryujinx のウェブサイトを開きます.",
@@ -15308,7 +15258,7 @@
"no_NO": "Ryujinx er ikke knyttet til NintendoTM,\neller noen av samarbeidspartnerne sine, på noen som helst måte.",
"pl_PL": "Ryujinx nie jest w żaden sposób powiązany z Nintendo™,\nani z żadnym z jej partnerów.",
"pt_BR": "Ryujinx não é afiliado com a Nintendo™,\nou qualquer um de seus parceiros, de nenhum modo.",
- "ru_RU": "Ryujinx никоим образом не связан ни с Nintendo™, ни с кем-либо из ее партнеров.",
+ "ru_RU": "Ryujinx никоим образом не связан с Nintendo™ или её партнёрами.",
"sv_SE": "Ryujinx har ingen koppling till Nintendo™,\neller någon av dess samarbetspartners.",
"th_TH": "ทางผู้พัฒนาโปรแกรม Ryujinx ไม่มีส่วนเกี่ยวข้องกับทางบริษัท Nintendo™\nหรือพันธมิตรใดๆ ทั้งสิ้น!",
"tr_TR": "Ryujinx, Nintendo™ veya ortaklarıyla herhangi bir şekilde bağlantılı değildir.",
@@ -15435,7 +15385,7 @@
"pt_BR": "Ryujinx é um emulador de Nintendo Switch™ 1.\nReceba todas as últimas notícias em nosso Discord.\nDesenvolvedores interessados em contribuir podem descobrir mais em nosso GitLab ou Discord.",
"ru_RU": "Ryujinx - это эмулятор для Nintendo Switch™ 1.\nПолучайте все последние новости разработки в нашем Discord.\nРазработчики, заинтересованные в участии, могут узнать больше на нашем GitLab или Discord.",
"sv_SE": "Ryujinx är en emulator för Nintendo Switch™ 1.\nFå de senaste nyheterna via vår Discord.\nUtvecklare som är intresserade att bidra kan hitta mer info på vår GitLab eller Discord.",
- "th_TH": "",
+ "th_TH": "Ryujinx เป็นโปรแกรมจำลองสำหรับเครื่อง Nintendo Switch™ 1\nติดตามข่าวสารล่าสุดได้ที่ Discord ของเรา\nนักพัฒนาที่สนใจร่วมพัฒนา สามารถดูข้อมูลเพิ่มเติมได้ทาง GitLab หรือ Discord",
"tr_TR": "",
"uk_UA": "Ryujinx — це емулятор для Nintendo Switch™ 1.\nОстанні новини можна отримати в нашому Discord.\nРозробники, що бажають долучитись до розробки та зробити свій внесок, можуть отримати більше інформації на нашому GitLab або в Discord.",
"zh_CN": "Ryujinx 是一个 Nintendo Switch™ 1 模拟器。\n有兴趣做出贡献的开发者可以在我们的 GitLab 或 Discord 上了解更多信息。\n",
@@ -15458,7 +15408,7 @@
"no_NO": "Vedlikeholdt av:",
"pl_PL": "Utrzymywany Przez:",
"pt_BR": "Mantido por:",
- "ru_RU": "Разработка:",
+ "ru_RU": "Поддерживается:",
"sv_SE": "Underhålls av:",
"th_TH": "ได้รับการดูแลโดย:",
"tr_TR": "Geliştiriciler:",
@@ -15483,9 +15433,9 @@
"no_NO": "Tidligere vedlikeholdt av:",
"pl_PL": "",
"pt_BR": "Anteriormente mantido por:",
- "ru_RU": "Поддержка:",
+ "ru_RU": "Ранее поддерживалось:",
"sv_SE": "Underhölls tidigare av:",
- "th_TH": "",
+ "th_TH": "เคยได้รับการดูแลโดย:",
"tr_TR": "",
"uk_UA": "Минулі розробники:",
"zh_CN": "曾经的维护者:",
@@ -15500,7 +15450,7 @@
"el_GR": "Κάντε κλικ για να ανοίξετε τη σελίδα Συνεισφέροντες στο προεπιλεγμένο πρόγραμμα περιήγησης.",
"en_US": "Click to open the Contributors page in your default browser.",
"es_ES": "Haz clic para abrir la página de contribuidores en tu navegador predeterminado.",
- "fr_FR": "Cliquez pour ouvrir la page Contributeurs dans votre navigateur par défaut.",
+ "fr_FR": "Cliquez pour ouvrir la page de Contributeurs dans votre navigateur par défaut.",
"he_IL": "לחץ כדי לפתוח את דף התורמים בדפדפן ברירת המחדל שלך.",
"it_IT": "Clicca per aprire la pagina dei contributori nel tuo browser predefinito.",
"ja_JP": "クリックするとデフォルトのブラウザで 貢献者のページを開きます.",
@@ -15535,7 +15485,7 @@
"pt_BR": "Franquia Amiibo",
"ru_RU": "Серия Amiibo",
"sv_SE": "Amiibo-serie",
- "th_TH": "",
+ "th_TH": "ชุดซีรีส์ Amiibo",
"tr_TR": "Amiibo Serisi",
"uk_UA": "Серія Amiibo",
"zh_CN": "Amiibo 系列",
@@ -15600,7 +15550,7 @@
"el_GR": "Εμφάνιση όλων των Amiibo",
"en_US": "Show All Amiibo",
"es_ES": "Mostrar todos los Amiibo",
- "fr_FR": "Afficher tous les Amiibo",
+ "fr_FR": "Afficher Tous les Amiibo",
"he_IL": "הצג את כל האמיבואים",
"it_IT": "Mostra tutti gli amiibo",
"ja_JP": "すべての Amiibo を表示",
@@ -15625,7 +15575,7 @@
"el_GR": "Hack: Χρησιμοποιήστε τυχαίο αναγνωριστικό UUID",
"en_US": "Hack: Use Random tag Uuid",
"es_ES": "Hack: usar etiqueta aleatoria Uuid",
- "fr_FR": "Hack : Utiliser un tag Uuid aléatoire",
+ "fr_FR": "Hack : Utiliser un tag Uuid Aléatoire",
"he_IL": "האצה: השתמש בתג Uuid אקראי",
"it_IT": "Espediente: Usa un UUID del tag casuale",
"ja_JP": "ハック: ランダムな Uuid を使用",
@@ -15675,7 +15625,7 @@
"el_GR": "Αναγνωριστικό τίτλου",
"en_US": "Title ID",
"es_ES": "ID de título",
- "fr_FR": "ID du titre",
+ "fr_FR": "ID du Titre",
"he_IL": "מזהה משחק",
"it_IT": "ID Titolo",
"ja_JP": "タイトルID",
@@ -15700,7 +15650,7 @@
"el_GR": "Τοποθεσία DLC",
"en_US": "Container Path",
"es_ES": "Directorio del contenedor",
- "fr_FR": "Chemin du conteneur",
+ "fr_FR": "Chemin du Conteneur",
"he_IL": "נתיב מכיל",
"it_IT": "Percorso del contenitore",
"ja_JP": "コンテナパス",
@@ -15725,7 +15675,7 @@
"el_GR": "Πλήρης τοποθεσία",
"en_US": "Full Path",
"es_ES": "Directorio completo",
- "fr_FR": "Chemin complet",
+ "fr_FR": "Chemin Complet",
"he_IL": "נתיב מלא",
"it_IT": "Percorso completo",
"ja_JP": "フルパス",
@@ -15750,7 +15700,7 @@
"el_GR": "Αφαίρεση όλων",
"en_US": "Remove All",
"es_ES": "Quitar todo",
- "fr_FR": "Tout supprimer",
+ "fr_FR": "Tout Supprimer",
"he_IL": "מחק הכל",
"it_IT": "Rimuovi tutti",
"ja_JP": "すべて削除",
@@ -15775,7 +15725,7 @@
"el_GR": "Ενεργοποίηση Όλων",
"en_US": "Enable All",
"es_ES": "Activar todas",
- "fr_FR": "Tout activer",
+ "fr_FR": "Tout Activer",
"he_IL": "אפשר הכל",
"it_IT": "Abilita tutto",
"ja_JP": "すべて有効",
@@ -15800,7 +15750,7 @@
"el_GR": "Απενεργοποίηση Όλων",
"en_US": "Disable All",
"es_ES": "Desactivar todos",
- "fr_FR": "Tout désactiver",
+ "fr_FR": "Tout Désactiver",
"he_IL": "השבת הכל",
"it_IT": "Disabilita tutto",
"ja_JP": "すべて無効",
@@ -15825,7 +15775,7 @@
"el_GR": "",
"en_US": "Delete All",
"es_ES": "Eliminar Todo",
- "fr_FR": "Tout supprimer",
+ "fr_FR": "Tout Supprimer",
"he_IL": "מחק הכל",
"it_IT": "Elimina tutto",
"ja_JP": "すべて削除",
@@ -15850,7 +15800,7 @@
"el_GR": "Αλλαξε γλώσσα",
"en_US": "Change Language",
"es_ES": "Cambiar idioma",
- "fr_FR": "Changer la langue",
+ "fr_FR": "Changer la Langue",
"he_IL": "החלף שפה",
"it_IT": "Cambia lingua",
"ja_JP": "言語を変更",
@@ -15875,7 +15825,7 @@
"el_GR": "Εμφάνιση Τύπων Αρχείων",
"en_US": "Show File Types",
"es_ES": "Mostrar tipos de archivo",
- "fr_FR": "Afficher les types de fichiers",
+ "fr_FR": "Afficher les Types de Fichiers",
"he_IL": "הצג מזהה סוג קובץ",
"it_IT": "Mostra tipi di file",
"ja_JP": "ファイル形式を表示",
@@ -15883,7 +15833,7 @@
"no_NO": "Vis Filtyper",
"pl_PL": "Pokaż typy plików",
"pt_BR": "Mostrar Tipos de Arquivo",
- "ru_RU": "Показывать форматы файлов",
+ "ru_RU": "Показывать типы файлов",
"sv_SE": "Visa filtyper",
"th_TH": "แสดงประเภทของไฟล์",
"tr_TR": "Dosya Uzantılarını Göster",
@@ -15925,7 +15875,7 @@
"el_GR": "Εμφάνιση ονομάτων",
"en_US": "Show Names",
"es_ES": "Mostrar nombres",
- "fr_FR": "Afficher les noms",
+ "fr_FR": "Afficher les Noms",
"he_IL": "הצג שמות",
"it_IT": "Mostra nomi",
"ja_JP": "名称を表示",
@@ -15983,7 +15933,7 @@
"no_NO": "Stigende",
"pl_PL": "Rosnąco",
"pt_BR": "Ascendente",
- "ru_RU": "По возрастанию",
+ "ru_RU": "По Возрастанию",
"sv_SE": "Stigande",
"th_TH": "จากน้อยไปมาก",
"tr_TR": "Artan",
@@ -16008,7 +15958,7 @@
"no_NO": "Synkende",
"pl_PL": "Malejąco",
"pt_BR": "Descendente",
- "ru_RU": "По убыванию",
+ "ru_RU": "По Убыванию",
"sv_SE": "Fallande",
"th_TH": "จากมากไปน้อย",
"tr_TR": "Azalan",
@@ -16033,7 +15983,7 @@
"no_NO": "Funksjoner & forbedringer",
"pl_PL": "Funkcje i Ulepszenia",
"pt_BR": "Recursos & Melhorias",
- "ru_RU": "Функции и улучшения",
+ "ru_RU": "Функции & Улучшения",
"sv_SE": "Funktioner och förbättringar",
"th_TH": "คุณสมบัติ และ การเพิ่มประสิทธิภาพ",
"tr_TR": "Özellikler & İyileştirmeler",
@@ -16050,7 +16000,7 @@
"el_GR": "Παράθυρο σφάλματος",
"en_US": "Error Window",
"es_ES": "Ventana de error",
- "fr_FR": "Fenêtre d'erreur",
+ "fr_FR": "Fenêtre d'Erreur",
"he_IL": "חלון שגיאה",
"it_IT": "Finestra di errore",
"ja_JP": "エラーウインドウ",
@@ -16083,7 +16033,7 @@
"no_NO": "Velg om Ryujinx skal vises på din \"spillende\" Discord aktivitet eller ikke",
"pl_PL": "Wybierz, czy chcesz wyświetlać Ryujinx w swojej \"aktualnie grane\" aktywności Discord",
"pt_BR": "Escolha se deseja mostrar Ryujinx ou não na sua atividade do Discord quando estiver usando-o",
- "ru_RU": "Включает или отключает отображение статуса «Играет в игру» в Discord",
+ "ru_RU": "Включает или отключает отображение Ryujinx в статусе \"Сейчас Играет\" в Discord.",
"sv_SE": "Välj huruvida Ryujinx ska visas på din \"spelar för tillfället\" Discord-aktivitet",
"th_TH": "เลือกว่าจะแสดง Ryujinx ในกิจกรรม Discord \"ที่กำลังเล่นอยู่\" ของคุณหรือไม่?",
"tr_TR": "Ryujinx'i \"şimdi oynanıyor\" Discord aktivitesinde göstermeyi veya göstermemeyi seçin",
@@ -16108,7 +16058,7 @@
"no_NO": "Angi en spillmappe for å legge til i listen",
"pl_PL": "Wprowadź katalog gier aby dodać go do listy",
"pt_BR": "Escreva um diretório de jogo para adicionar à lista",
- "ru_RU": "Введите путь к папке с играми для добавления ее в список выше",
+ "ru_RU": "Введите путь к папке с играми чтобы добавить ее в список выше",
"sv_SE": "Ange en spelkatalog att lägga till i listan",
"th_TH": "ป้อนไดเรกทอรี่เกมที่จะทำการเพิ่มลงในรายการ",
"tr_TR": "Listeye eklemek için oyun dizini seçin",
@@ -16125,7 +16075,7 @@
"el_GR": "Προσθέστε μία τοποθεσία παιχνιδιών στη λίστα",
"en_US": "Add a game directory to the list",
"es_ES": "Agrega un directorio de juegos a la lista",
- "fr_FR": "Ajouter un répertoire de jeux à la liste",
+ "fr_FR": "Ajoute un répertoire de jeux à la liste",
"he_IL": "הוסף תקיית משחקים לרשימה",
"it_IT": "Aggiungi una cartella dei giochi alla lista",
"ja_JP": "リストにゲームディレクトリを追加します",
@@ -16150,7 +16100,7 @@
"el_GR": "Αφαιρέστε την επιλεγμένη τοποθεσία παιχνιδιών",
"en_US": "Remove selected game directory",
"es_ES": "Quita el directorio seleccionado de la lista",
- "fr_FR": "Supprimer le répertoire de jeu sélectionné",
+ "fr_FR": "Supprime le répertoire de jeu sélectionné",
"he_IL": "הסר את תקיית המשחקים שנבחרה",
"it_IT": "Rimuovi la cartella dei giochi selezionata",
"ja_JP": "選択したゲームディレクトリを削除します",
@@ -16158,7 +16108,7 @@
"no_NO": "Fjern valgt spillmappe",
"pl_PL": "Usuń wybrany katalog gier",
"pt_BR": "Remover diretório de jogo selecionado",
- "ru_RU": "Удалить выбранную папку игры",
+ "ru_RU": "Убрать выбранную папку игры из списка",
"sv_SE": "Ta bort vald spelkatalog",
"th_TH": "ลบไดเรกทอรี่เกมที่เลือก",
"tr_TR": "Seçili oyun dizinini kaldır",
@@ -16183,7 +16133,7 @@
"no_NO": "Angi en autoload-mappe som skal legges til i listen",
"pl_PL": "",
"pt_BR": "Insira um diretório de carregamento automático para adicionar à lista",
- "ru_RU": "Введите папку автозагрузки для добавления в список",
+ "ru_RU": "Введите папку автозагрузки для добавления в список выше",
"sv_SE": "Ange en katalog att automatiskt läsa in till listan",
"th_TH": "ป้อนไดเร็กทอรีสำหรับโหลดอัตโนมัติเพื่อเพิ่มลงในรายการ",
"tr_TR": "",
@@ -16250,7 +16200,7 @@
"el_GR": "Ενεργοποίηση ή απενεργοποίηση προσαρμοσμένων θεμάτων στο GUI",
"en_US": "Use a custom Avalonia theme for the GUI to change the appearance of the emulator menus",
"es_ES": "Activa o desactiva los temas personalizados para la interfaz",
- "fr_FR": "Utilisez un thème Avalonia personnalisé pour modifier l'apparence des menus de l'émulateur",
+ "fr_FR": "Utilise un thème Avalonia personnalisé pour modifier l'apparence des menus de l'émulateur",
"he_IL": "השתמש בעיצוב מותאם אישית של אבלוניה עבור ה-ממשק הגראפי כדי לשנות את המראה של תפריטי האמולטור",
"it_IT": "Utilizza un tema di Avalonia personalizzato per cambiare l'aspetto dei menù dell'emulatore",
"ja_JP": "エミュレータのメニュー外観を変更するためカスタム Avalonia テーマを使用します",
@@ -16258,7 +16208,7 @@
"no_NO": "Bruk et egendefinert Avalonia tema for GUI for å endre utseende til emulatormenyene",
"pl_PL": "Użyj niestandardowego motywu Avalonia dla GUI, aby zmienić wygląd menu emulatora",
"pt_BR": "Use um tema Avalonia personalizado para a GUI para alterar a aparência dos menus do emulador",
- "ru_RU": "Включить или отключить пользовательские темы",
+ "ru_RU": "Использовать пользовательскую тему Avalonia, чтобы изменить внешний вид меню эмулятора",
"sv_SE": "Använd ett anpassat Avalonia-tema för gränssnittet för att ändra utseendet i emulatormenyerna",
"th_TH": "ใช้ธีม Avalonia แบบกำหนดเองสำหรับ GUI เพื่อเปลี่ยนรูปลักษณ์ของเมนูโปรแกรมจำลอง",
"tr_TR": "Emülatör pencerelerinin görünümünü değiştirmek için özel bir Avalonia teması kullan",
@@ -16300,7 +16250,7 @@
"el_GR": "Αναζητήστε ένα προσαρμοσμένο θέμα GUI",
"en_US": "Browse for a custom GUI theme",
"es_ES": "Busca un tema personalizado para la interfaz",
- "fr_FR": "Parcourir un thème personnalisé pour l’interface graphique",
+ "fr_FR": "Parcourir vers un thème personnalisé pour l'interface utilisateur",
"he_IL": "חפש עיצוב ממשק גראפי מותאם אישית",
"it_IT": "Scegli un tema dell'interfaccia personalizzato",
"ja_JP": "カスタム GUI テーマを参照します",
@@ -16308,7 +16258,7 @@
"no_NO": "Søk etter et egendefinert GUI-tema",
"pl_PL": "Wyszukaj niestandardowy motyw GUI",
"pt_BR": "Navegar até um tema customizado",
- "ru_RU": "Просмотр пользовательской темы интерфейса",
+ "ru_RU": "Выбрать пользовательскую тему интерфейса",
"sv_SE": "Bläddra efter ett anpassat gränssnittstema",
"th_TH": "เรียกดูธีม GUI ที่กำหนดเอง",
"tr_TR": "Özel arayüz teması için göz at",
@@ -16333,9 +16283,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "Se esta opção está ativada nas configurações customizadas, as configurações globais de entrada serão usadas.\n\nNas configurações globais: você pode ativar ou desativá-las se necessário; está configuração será herdada por qualquer nova configuração customizada criada.",
- "ru_RU": "Если эта опция включена в пользовательских настройках, будет использована глобальная конфигурация ввода.\n\nВ глобальных настройках: переключите эту опцию по своему усмотрению, это будет унаследовано для вновь созданых пользовательских конфигураций",
+ "ru_RU": "Если эта опция включена в пользовательских настройках, будет использована глобальная конфигурация ввода.\n\nПо мере необходимости, вы можете включить или отключить её в глобальных настройках; эта настройка будет унаследована всеми новыми созданными индивидуальными конфигурациями.",
"sv_SE": "Om det här alternativet är aktiverat i anpassade inställningar kommer den globala inmatningskonfigurationen att användas.\n\nI de globala inställningarna: du kan aktivera eller inaktivera det efter behov; den här inställningen kommer att ärvas av alla nya anpassade konfigurationer som skapas.",
- "th_TH": "",
+ "th_TH": "หากเปิดใช้งานตัวเลือกนี้ในการตั้งค่าแบบกำหนดเอง การตั้งค่าการควบคุมแบบรวม (Global Input Configuration) จะถูกนำมาใช้\n\nในการตั้งค่าทั่วไป: คุณสามารถเปิดหรือปิดใช้งานได้ตามต้องการ โดยการตั้งค่านี้จะถูกใช้เป็นค่าเริ่มต้นสำหรับการตั้งค่าแบบกำหนดเองที่สร้างขึ้นใหม่ทุกอัน",
"tr_TR": "",
"uk_UA": "Якщо цей параметр увімкнено в користувацьких налаштуваннях, буде використовуватись глобальна конфігурація вводу.\n\nВ глобальних налаштуваннях: за потреби цю опцію можна вмикати або вимикати; це налаштування автоматично застосується до всіх нових конфігурацій, які ви створите.",
"zh_CN": "如果在自定义设置中启用了此选项,则将使用全局输入配置。\n\n在全局设置中: 您可以根据需要启用或禁用它;之后创建的任何自定义配置都将继承此设置。",
@@ -16350,7 +16300,7 @@
"el_GR": "Ενεργοποιήστε ή απενεργοποιήστε τη λειτουργία σύνδεσης",
"en_US": "Docked mode makes the emulated system behave as a docked Nintendo Switch. This improves graphical fidelity in most games. Conversely, disabling this will make the emulated system behave as a handheld Nintendo Switch, reducing graphics quality.\n\nConfigure Player 1 controls if planning to use docked mode; configure handheld controls if planning to use handheld mode.\n\nLeave ON if unsure.",
"es_ES": "El modo dock o modo TV hace que la consola emulada se comporte como una Nintendo Switch en su dock. Esto mejora la calidad gráfica en la mayoría de los juegos. Del mismo modo, si lo desactivas, el sistema emulado se comportará como una Nintendo Switch en modo portátil, reduciendo la cálidad de los gráficos.\n\nConfigura los controles de \"Jugador\" 1 si planeas jugar en modo dock/TV; configura los controles de \"Portátil\" si planeas jugar en modo portátil.\n\nActívalo si no sabes qué hacer.",
- "fr_FR": "Le mode docké fait que le système émulé se comporte comme une Nintendo Switch en mode dock. Cela améliore la qualité graphique dans la plupart des jeux. À l’inverse, désactiver ce mode fera que le système émulé se comporte comme une Nintendo Switch en mode portable, ce qui réduit la qualité graphique.\n\nConfigurez les contrôles du joueur 1 si vous prévoyez d’utiliser le mode docké ; configurez les contrôles pour le mode portable si vous comptez utiliser ce dernier.\n\nLaissez ACTIVÉ si vous n’êtes pas sûr..",
+ "fr_FR": "Le mode station d'accueil permet à la console émulée de se comporter comme une Nintendo Switch en mode station d'accueil. Cela améliore la qualité graphique dans la plupart des jeux. À l’inverse, désactiver ce mode fera que le système émulé se comporte comme une console Nintendo Switch portable, réduisant la qualité graphique.\n\nConfigurez les contrôles du joueur 1 si vous prévoyez d'utiliser le mode station d'accueil; configurez les contrôles pour le mode portable si vous prévoyez d'utiliser le mode portable.\n\nLaissez ACTIVÉ si vous n'êtes pas sûr.",
"he_IL": "מצב עגינה גורם למערכת המדומה להתנהג כ-נינטנדו סוויץ' בתחנת עגינתו. זה משפר את הנאמנות הגרפית ברוב המשחקים.\n לעומת זאת, השבתה של תכונה זו תגרום למערכת המדומה להתנהג כ- נינטנדו סוויץ' נייד, ולהפחית את איכות הגרפיקה.\n\nהגדירו את שלט שחקן 1 אם אתם מתכננים להשתמש במצב עגינה; הגדירו את פקדי כף היד אם אתם מתכננים להשתמש במצב נייד.\n\nמוטב להשאיר דלוק אם אתם לא בטוחים.",
"it_IT": "La modalità TV fa sì che il sistema emulato si comporti come una Nintendo Switch posizionata nella sua base. Ciò migliora la qualità grafica nella maggior parte dei giochi. Al contrario, disabilitandola il sistema emulato si comporterà come una Nintendo Switch in modalità portatile, riducendo la qualità grafica.\n\nConfigura i controlli del giocatore 1 se intendi usare la modalità TV; configura i controlli della modalità portatile se intendi usare quest'ultima.\n\nNel dubbio, lascia l'opzione attiva.",
"ja_JP": "有効にすると,ドッキングされた Nintendo Switch をエミュレートします.多くのゲームではグラフィックス品質が向上します.\n無効にすると,携帯モードの Nintendo Switch をエミュレートします.グラフィックスの品質は低下します.\n\nドッキングモード有効ならプレイヤー1の,無効なら携帯の入力を設定してください.\n\nよくわからない場合はオンのままにしてください.",
@@ -16358,7 +16308,7 @@
"no_NO": "Forankret modus gjør at systemet oppføre seg som en forankret Nintendo Switch. Dette forbedrer grafikkkvaliteten i de fleste spill. Motsatt vil deaktivering av dette gjøre at systemet oppføre seg som en håndholdt Nintendo Switch, noe som reduserer grafikkkvaliteten.\n\nKonfigurer spiller 1 kontroller hvis du planlegger å bruke forankret modus; konfigurer håndholdte kontroller hvis du planlegger å bruke håndholdte modus.\n\nLa PÅ hvis du er usikker.",
"pl_PL": "Tryb Zadokowany sprawia, że emulowany system zachowuje się jak zadokowany Nintendo Switch. Poprawia to jakość grafiki w większości gier. I odwrotnie, wyłączenie tej opcji sprawi, że emulowany system będzie zachowywał się jak przenośny Nintendo Switch, zmniejszając jakość grafiki.\n\nSkonfiguruj sterowanie gracza 1, jeśli planujesz używać trybu Zadokowanego; Skonfiguruj sterowanie przenośne, jeśli planujesz używać trybu przenośnego.\n\nPozostaw WŁĄCZONY, jeśli nie masz pewności.",
"pt_BR": "O modo TV faz o sistema emulado se comportar como um Nintendo Switch na TV, o que melhora a fidelidade gráfica na maioria dos jogos. Por outro lado, desativar essa opção fará o sistema emulado se comportar como um Nintendo Switch portátil, reduzindo a qualidade gráfica.\n\nConfigure os controles do jogador 1 se planeja usar o modo TV; configure os controles de portátil se planeja usar o modo Portátil.\n\nMantenha ativado se estiver em dúvida.",
- "ru_RU": "\"Стационарный\" режим запускает эмулятор, как если бы Nintendo Switch находилась в доке, что улучшает графику и разрешение в большинстве игр. И наоборот, при отключении этого режима эмулятор будет запускать игры в \"Портативном\" режиме, снижая качество графики.\n\nНастройте управление для Игрока 1 если планируете использовать эмулятор в \"Стационарном\" режиме; настройте портативное управление если планируете использовать эмулятор в \"Портативном\" режиме.\n\nРекомендуется оставить включенным.",
+ "ru_RU": "Режим \"Док-Станция\" заставляет эмулируемую работать как подключённая к док-станции консоль Nintendo Switch. Это улучшает графическую чёткость в большинстве игр. Отключение этой опции заставит эмулируемую систему вести себя как портативный Switch, снижая качество графики.\n\nНастройте управление для Игрока 1, если планируете использовать режим \"Док-Станция\"; настройте управление для портативного режима, если планируете использовать \"Портативный\" режим.\n\nРекомендуется оставить ВКЛЮЧЁННЫМ.",
"sv_SE": "Dockat läge gör att det emulerade systemet beter sig som en dockad Nintendo Switch. Detta förbättrar grafiken i de flesta spel. Inaktiveras detta så kommer det emulerade systemet att bete sig som en handhållen Nintendo Switch, vilket reducerar grafikkvaliteten.\n\nKonfigurera kontrollen för Spelare 1 om du planerar att använda dockat läge; konfigurera handhållna kontroller om du planerar att använda handhållet läge.\n\nLämna PÅ om du är osäker.",
"th_TH": "ด็อกโหมด ทำให้ระบบจำลองการทำงานเสมือน Nintendo ที่กำลังเชื่อมต่ออยู่ด็อก สิ่งนี้จะปรับปรุงความเสถียรภาพของกราฟิกในเกมส่วนใหญ่ ในทางกลับกัน การปิดใช้จะทำให้ระบบจำลองทำงานเหมือนกับ Nintendo Switch แบบพกพา ส่งผลให้คุณภาพกราฟิกลดลง\n\nแนะนำกำหนดค่าควบคุมของผู้เล่น 1 หากวางแผนที่จะใช้ด็อกโหมด กำหนดค่าการควบคุมแบบ แฮนด์เฮลด์ หากวางแผนที่จะใช้โหมดแฮนด์เฮลด์\n\nเปิดทิ้งไว้หากคุณไม่แน่ใจ",
"tr_TR": "Docked modu emüle edilen sistemin yerleşik Nintendo Switch gibi davranmasını sağlar. Bu çoğu oyunda grafik kalitesini arttırır. Diğer yandan, bu seçeneği devre dışı bırakmak emüle edilen sistemin portatif Ninendo Switch gibi davranmasını sağlayıp grafik kalitesini düşürür.\n\nDocked modu kullanmayı düşünüyorsanız 1. Oyuncu kontrollerini; Handheld modunu kullanmak istiyorsanız portatif kontrollerini konfigüre edin.\n\nEmin değilseniz aktif halde bırakın.",
@@ -16383,7 +16333,7 @@
"no_NO": "Direkte tastaturtilgang (HID) støtte. Gir deg spill-tilgang til tastaturet som en tekstinnlegg-enhet.\n\nfungerer kun med spill som lokalt støtter tastaturbruk på Ninteno SwitchTM maskinvare.\n\nLa være AV hvis du er usikker.",
"pl_PL": "Obsługa bezpośredniego dostępu do klawiatury (HID). Zapewnia dostęp gier do klawiatury jako urządzenia do wprowadzania tekstu.\n\nDziała tylko z grami, które natywnie wspierają użycie klawiatury w urządzeniu Switch hardware.\n\nPozostaw wyłączone w razie braku pewności.",
"pt_BR": "Suporte para acesso direto ao teclado (HID). Permite que os jogos acessem seu teclado como um dispositivo de entrada de texto.\n\nFunciona apenas com jogos que suportam o uso de teclado nativamente no hardware do Switch.\n\nDeixe desativado se estiver em dúvida.",
- "ru_RU": "Поддержка прямого ввода с клавиатуры (HID). Предоставляет игре прямой доступ к клавиатуре в качестве устройства ввода текста.\nРаботает только с играми, которые изначально поддерживают использование клавиатуры с Switch.\nРекомендуется оставить выключенным.",
+ "ru_RU": "Прямой ввод клавиаруты (HID). Предоставляет играм доступ к вашей клавиатуре как устройству для ввода текста.\nРаботает только с играми, которые изначально поддерживают использование клавиатуры с Switch.\nРекомендуется оставить ВЫКЛЮЧЕННЫМ.",
"sv_SE": "Stöd för direkt tangentbordsåtkomst (HID). Ger spel åtkomst till ditt tangentbord som en textinmatningsenhet.\n\nFungerar endast med spel som har inbyggt stöd för tangentbordsanvändning på Switch-hårdvara.\n\nLämna AV om du är osäker.",
"th_TH": "รองรับการเข้าถึงแป้นพิมพ์โดยตรง (HID) ให้เกมเข้าถึงคีย์บอร์ดของคุณเป็นอุปกรณ์ป้อนข้อความ\n\nใช้งานได้กับเกมที่รองรับการใช้งานคีย์บอร์ดบนฮาร์ดแวร์ของ Switch เท่านั้น\n\nหากคุณไม่แน่ใจให้ปิดใช้งานไว้",
"tr_TR": "",
@@ -16408,7 +16358,7 @@
"no_NO": "Direkte musepeker (HID) støtte. Gir deg spill-tilgang til musepeker.\n\nfungerer kun med spill som lokalt støtter musepekere på Ninteno SwitchTM maskinvare.\n\nNår aktivert, kan det hende touch funksjoner ikke fungerer\n\nLa være AV hvis du er usikker.",
"pl_PL": "Obsługa bezpośredniego dostępu do myszy (HID). Zapewnia dostęp gier do myszy jako urządzenia wskazującego.\n\nDziała tylko z grami, które natywnie obsługują przyciski myszy w urządzeniu Switch, które są nieliczne i daleko między nimi.\n\nPo włączeniu funkcja ekranu dotykowego może nie działać.\n\nPozostaw wyłączone w razie wątpliwości.",
"pt_BR": "Suporte para acesso direto ao mouse (HID). Permite que os jogos acessem seu mouse como um dispositivo de apontamento.\n\nFunciona apenas com jogos que suportam controles de mouse nativamente no hardware do Switch, o que é raro.\n\nQuando ativado, a funcionalidade de tela sensível ao toque pode não funcionar.\n\nDeixe desativado se estiver em dúvida.",
- "ru_RU": "Поддержка прямого ввода мыши (HID). Предоставляет игре прямой доступ к мыши в качестве указывающего устройства.\nРаботает только с играми, которые изначально поддерживают использование мыши совместно с железом Switch.\nРекомендуется оставить выключенным.",
+ "ru_RU": "Прямой ввод мыши (HID). Предоставляет играм доступ к вашей мыши как устройству для указания.\nРаботает только с играми, которые изначально поддерживают оборудовании Switch, таких игр немного.\n\nПри включении, сенсорные экраны могут не работать.\nРекомендуется оставить ВКЛЮЧЁННОЙ.",
"sv_SE": "Stöd för direkt musåtkomst (HID). Ger spel åtkomst till din mus som pekdon.\n\nFungerar endast med spel som har inbyggt stöd för muskontroller på Switch-hårdvara, som är endast ett fåtal.\n\nViss pekskärmsfunktionalitet kanske inte fungerar när aktiverat.\n\nLämna AV om du är osäker.",
"th_TH": "รองรับการเข้าถึงเมาส์โดยตรง (HID) ให้เกมเข้าถึงเมาส์ของคุณเป็นอุปกรณ์ชี้ตำแหน่ง\n\nใช้งานได้เฉพาะกับเกมที่รองรับการควบคุมเมาส์บนฮาร์ดแวร์ของ Switch เท่านั้น ซึ่งมีอยู่ไม่มากนัก\n\nเมื่อเปิดใช้งาน ฟังก์ชั่นหน้าจอสัมผัสอาจไม่ทำงาน\n\nหากคุณไม่แน่ใจให้ปิดใช้งานไว้",
"tr_TR": "",
@@ -16425,7 +16375,7 @@
"el_GR": "",
"en_US": "Sync System Time to match your PC's current date & time.",
"es_ES": "",
- "fr_FR": "Synchroniser l’heure système avec la date et l’heure actuelles de votre PC.",
+ "fr_FR": "Synchronise l’Heure Système avec la date et l’heure actuelle de votre PC.",
"he_IL": "",
"it_IT": "Sincronizza data e ora del sistema con quelle del PC.",
"ja_JP": "",
@@ -16433,9 +16383,9 @@
"no_NO": "Resynkroniser systemtiden slik at den samsvarer med PC-ens gjeldende dato og klokkeslett.",
"pl_PL": "",
"pt_BR": "Sincroniza a data e hora do emulador com seu sistema PC",
- "ru_RU": "Повторно синхронизирует системное время, чтобы оно соответствовало текущей дате и времени вашего компьютера.",
+ "ru_RU": "Синхронизировать время системы с текущей датой и временем на вашем компьютере.",
"sv_SE": "Återsynkronisera systemtiden för att matcha din dators aktuella datum och tid.",
- "th_TH": "",
+ "th_TH": "ปรับเวลาในระบบให้ตรงกับวันที่และเวลาปัจจุบันของเครื่องคอมพิวเตอร์ของคุณ",
"tr_TR": "",
"uk_UA": "Синхронізувати системний час, щоб він відповідав поточній даті та часу вашого ПК.",
"zh_CN": "重新同步系统时间以匹配您电脑的当前日期和时间。",
@@ -16450,7 +16400,7 @@
"el_GR": "",
"en_US": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference (F1 by default). We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
"es_ES": "Sincronización vertical de la consola emulada. En práctica un limitador del framerate para la mayoría de los juegos; desactivando puede causar que juegos corran a mayor velocidad o que las pantallas de carga tarden más o queden atascados.\n\nSe puede alternar en juego utilizando una tecla de acceso rápido configurable (F1 by default). Recomendamos hacer esto en caso de querer desactivar sincroniziación vertical.\n\nDesactívalo si no sabes qué hacer.",
- "fr_FR": "Synchronisation verticale de la console émulée. Il s'agit essentiellement d'un limiteur de fréquence d'images pour la majorité des jeux ; la désactivation peut entraîner une accélération du jeu ou provoquer des temps de chargement plus longs, voire des blocages..\n\nPeut être activée/désactivée en jeu via un raccourci clavier de votre choix (F1 par défaut). Nous recommandons d’utiliser ce raccourci si vous prévoyez de la désactiver.\n\nLaissez ACTIVÉE si vous n’êtes pas sûr.",
+ "fr_FR": "La synchronisation verticale de la console émulée. Essentiellement un limiteur de trame pour la majorité des jeux ; le désactiver peut entraîner un fonctionnement plus rapide des jeux ou prolonger ou bloquer les écrans de chargement.\n\nPeut être activé ou désactivé en jeu avec un raccourci clavier de votre choix (F1 par défaut). Nous recommandons d’utiliser ce raccourci si vous envisagez de le désactiver.\n\nLaissez ACTIVÉ si vous n'êtes pas sûr.",
"he_IL": "",
"it_IT": "Sincronizzazione verticale della console emulata. Funziona essenzialmente come un limitatore del framerate per la maggior parte dei giochi; disabilitarla può far girare giochi a velocità più alta, allungare le schermate di caricamento o farle bloccare.\n\nPuò essere attivata mentre giochi con un tasto di scelta rapida (F1 per impostazione predefinita). Ti consigliamo di farlo se hai intenzione di disabilitarla.\n\nNel dubbio, lascia l'opzione attiva.",
"ja_JP": "エミュレートされたゲーム機の垂直同期です. 多くのゲームにおいて, フレームリミッタとして機能します. 無効にすると, ゲームが高速で実行されたり, ロード中に時間がかかったり, 止まったりすることがあります.\n\n設定したホットキー(デフォルトではF1)で, ゲーム内で切り替え可能です. 無効にする場合は, この操作を行うことをおすすめします.\n\nよくわからない場合はオンのままにしてください.",
@@ -16458,7 +16408,7 @@
"no_NO": "Emuler konsollens loddrett synkronisering. på ett vis en bildefrekvens begrensning for de fleste spill; deaktivering kan få spill til å kjøre med høyere hastighet, eller til å laste skjermene tar lengre tid eller sitter fast.\n\nkan byttes inn i spillet med en hurtigtast for preferansen (F1 som standard). Vi anbefaler å gjøre dette hvis du planlegger å deaktivere dette.\n\nLa være PÅ hvis du er usikker.",
"pl_PL": "Synchronizacja pionowa emulowanej konsoli. Zasadniczo ogranicznik klatek dla większości gier; wyłączenie jej może spowodować, że gry będą działać z większą szybkością, ekrany wczytywania wydłużą się lub nawet utkną.\n\nMoże być przełączana w grze za pomocą preferowanego skrótu klawiszowego. Zalecamy to zrobić, jeśli planujesz ją wyłączyć.\n\nW razie wątpliwości pozostaw WŁĄCZONĄ.",
"pt_BR": "V-Sync do console emulado. Funciona essencialmente como um limitador de quadros para a maioria dos jogos; desativá-lo pode fazer com que os jogos rodem em uma velocidade mais alta ou que telas de carregamento demorem mais ou travem.\n\nPode ser alternado durante o jogo com uma tecla de atalho de sua preferência (F1 por padrão). Recomendamos isso caso planeje desativá-lo.\n\nMantenha ligado se estiver em dúvida.",
- "ru_RU": "Эмуляция вертикальной синхронизации консоли, которая ограничивает количество кадров в секунду в большинстве игр; отключение может привести к тому, что игры будут запущены с более высокой частотой кадров, но загрузка игры может занять больше времени, либо игра не запустится вообще.\n\nМожно включать и выключать эту настройку непосредственно в игре с помощью горячих клавиш (F1 по умолчанию). Если планируете отключить вертикальную синхронизацию, рекомендуем настроить горячие клавиши.\n\nРекомендуется оставить включенным.",
+ "ru_RU": "Эмуляция вертикальной синхронизации консоли, которая ограничивает количество кадров в секунду в большинстве игр; отключение может привести к тому, что игры будут запущены с более высокой частотой кадров, но загрузка игры может занять больше времени, либо игра не запустится вообще.\n\nМожно включать и выключать эту настройку непосредственно в игре с помощью горячих клавиш (F1 по умолчанию). Если планируете отключить вертикальную синхронизацию, рекомендуем настроить горячие клавиши.\n\nРекомендуется оставить ВКЛЮЧЁННЫМ.",
"sv_SE": "Emulerade konsollens vertikala synk. I grund och botten en begränsare för bitrutor för de flesta spel; inaktivera den kan orsaka att spel kör på en högre hastighet eller gör att skärmar tar längre tid att läsa eller fastnar i dem.\n\nKan växlas inne i spelet med en snabbtangent som du väljer (F1 som standard). Vi rekommenderar att göra detta om du planerar att inaktivera den.\n\nLämna PÅ om du är osäker.",
"th_TH": "Vertical Sync ของคอนโซลจำลอง โดยพื้นฐานแล้วเป็นตัวจำกัดเฟรมสำหรับเกมส่วนใหญ่ การปิดใช้งานอาจทำให้เกมทำงานด้วยความเร็วสูงขึ้น หรือทำให้หน้าจอการโหลดใช้เวลานานขึ้นหรือค้าง\n\nสามารถสลับได้ในเกมด้วยปุ่มลัดตามที่คุณต้องการ (F1 เป็นค่าเริ่มต้น) เราขอแนะนำให้ทำเช่นนี้หากคุณวางแผนที่จะปิดการใช้งาน\n\nเปิดทิ้งไว้หากคุณไม่แน่ใจ",
"tr_TR": "",
@@ -16475,7 +16425,7 @@
"el_GR": "Ενεργοποιεί ή απενεργοποιεί το PPTC",
"en_US": "Saves translated JIT functions so that they do not need to be translated every time the game loads.\n\nReduces stuttering and significantly speeds up boot times after the first boot of a game.\n\nLeave ON if unsure.",
"es_ES": "Guarda funciones de JIT traducidas para que no sea necesario traducirlas cada vez que el juego carga.\n\nReduce los tirones y acelera significativamente el tiempo de inicio de los juegos después de haberlos ejecutado al menos una vez.\n\nActívalo si no sabes qué hacer.",
- "fr_FR": "Sauvegarde les fonctions JIT traduites afin qu’elles n’aient pas besoin d’être retraduites à chaque chargement du jeu.\n\nRéduit les lags et accélère considérablement le temps de chargement après le premier lancement d'un jeu.\n\nLaissez ACTIVÉ si vous n’êtes pas sûr.",
+ "fr_FR": "Sauvegarde les fonctions JIT traduites afin qu’elles n’aient pas besoin d’être retraduites à chaque chargement du jeu.\n\nRéduit les lags et accélère considérablement le temps de chargement après le premier lancement d'un jeu.\n\nLaissez ACTIVÉ si vous n'êtes pas sûr.",
"he_IL": "שומר את פונקציות ה-JIT המתורגמות כך שלא יצטרכו לעבור תרגום שוב כאשר משחק עולה.\n\nמפחית תקיעות ומשפר מהירות עלייה של המערכת אחרי הפתיחה הראשונה של המשחק.\n\nמוטב להשאיר דלוק אם לא בטוחים.",
"it_IT": "Salva le funzioni JIT tradotte in modo che non debbano essere tradotte tutte le volte che si avvia un determinato gioco.\n\nRiduce i fenomeni di stuttering e velocizza sensibilmente gli avvii successivi del gioco.\n\nNel dubbio, lascia l'opzione attiva.",
"ja_JP": "翻訳されたJIT関数をセーブすることで, ゲームをロードするたびに毎回翻訳する処理を不要とします.\n\n一度ゲームを起動すれば,二度目以降の起動時遅延を大きく軽減できます.\n\nよくわからない場合はオンのままにしてください.",
@@ -16483,7 +16433,7 @@
"no_NO": "Lagrer oversatte JIT funksjoner så de ikke trenger og bli oversatt hver gang spillet laster.\n\nKan redusere hakkete spilling og gjør at spillet starter opp raskere ved første oppstart.\n\nLa være PÅ om usikker.",
"pl_PL": "Zapisuje przetłumaczone funkcje JIT, dzięki czemu nie muszą być tłumaczone za każdym razem, gdy gra się ładuje.\n\nZmniejsza zacinanie się i znacznie przyspiesza uruchamianie po pierwszym uruchomieniu gry.\n\nJeśli nie masz pewności, pozostaw WŁĄCZONE",
"pt_BR": "Salva funções JIT traduzidas para que elas não precisem ser traduzidas toda vez que o jogo for carregado.\n\nReduz a trepidação e acelera significativamente os tempos de inicialização após a primeira inicialização de um jogo.\n\nDeixe LIGADO se não tiver certeza.",
- "ru_RU": "Сохраняет скомпилированные JIT-функции для того, чтобы не преобразовывать их по новой каждый раз при запуске игры.\n\nУменьшает статтеры и значительно ускоряет последующую загрузку игр.\n\nРекомендуется оставить включенным.",
+ "ru_RU": "Сохраняет переведённые JIT-функции, чтобы они не нуждались в повторном переводе при каждом запуске игры.\n\nУменьшает статтеры и значительно ускоряет время загрузки после первого запуска игры.\n\nРекомендуется оставить ВКЛЮЧЁННЫМ.",
"sv_SE": "Sparar översatta JIT-funktioner så att de inte behöver översättas varje gång som spelet läses in.\n\nMinskar stuttering och snabbare på uppstartstiden väsentligt efter första uppstarten av ett spel.\n\nLämna PÅ om du är osäker.",
"th_TH": "บันทึกฟังก์ชั่น JIT ที่แปลแล้ว ดังนั้นจึงไม่จำเป็นต้องแปลทุกครั้งที่โหลดเกม\n\nลดอาการกระตุกและเร่งความเร็วการบูตได้อย่างมากหลังจากการบูตครั้งแรกของเกม\n\nเปิดทิ้งไว้หากคุณไม่แน่ใจ",
"tr_TR": "Çevrilen JIT fonksiyonlarını oyun her açıldığında çevrilmek zorunda kalmaması için kaydeder.\n\nTeklemeyi azaltır ve ilk açılıştan sonra oyunların ilk açılış süresini ciddi biçimde hızlandırır.\n\nEmin değilseniz aktif halde bırakın.",
@@ -16500,7 +16450,7 @@
"el_GR": "",
"en_US": "Load the PPTC using a third of the amount of cores.",
"es_ES": "Cargue el PPTC utilizando un tercio de la cantidad de núcleos.",
- "fr_FR": "Charger le PPTC en utilisant un tiers des cœurs disponibles.",
+ "fr_FR": "Charge le PPTC en utilisant un tiers des cœurs disponibles.",
"he_IL": "",
"it_IT": "Carica la cache PPTC usando un terzo dei core del processore.",
"ja_JP": "",
@@ -16508,7 +16458,7 @@
"no_NO": "Last inn PPTC med en tredjedel av antall kjerner.",
"pl_PL": "",
"pt_BR": "Carrega o PPTC usando um terço da quantidade de núcleos.",
- "ru_RU": "Загрузить PPTC, используя треть от количества ядер.",
+ "ru_RU": "Загрузить PPTC используя треть от количества ядер.",
"sv_SE": "Läs in PPTC med en tredjedel av mängden kärnor.",
"th_TH": "โหลด PPTC โดยใช้หนึ่งในสามของจำนวนคอร์",
"tr_TR": "",
@@ -16525,7 +16475,7 @@
"el_GR": "Ενεργοποιεί τους ελέγχους ακεραιότητας σε αρχεία περιεχομένου παιχνιδιού",
"en_US": "Checks for corrupt files when booting a game, and if corrupt files are detected, displays a hash error in the log.\n\nHas no impact on performance and is meant to help troubleshooting.\n\nLeave ON if unsure.",
"es_ES": "Comprueba si hay archivos corruptos en los juegos que ejecutes al abrirlos, y si detecta archivos corruptos, muestra un error de Hash en los registros.\n\nEsto no tiene impacto alguno en el rendimiento y está pensado para ayudar a resolver problemas.\n\nActívalo si no sabes qué hacer.",
- "fr_FR": "Vérifie la présence de fichiers corrompus au démarrage d’un jeu. En cas de fichiers corrompus détectés, un message d’erreur de hachage s’affiche dans le journal.\n\nN’a aucun impact sur les performances et est destiné à faciliter le dépannage.\n\nLaissez ACTIVÉ si vous n’êtes pas sûr.",
+ "fr_FR": "Vérifie la présence de fichiers corrompus au démarrage d’un jeu. En cas de fichiers corrompus détectés, un message d’erreur de hachage s’affiche dans le journal.\n\nN’a aucun impact sur la performance et est destiné à faciliter le dépannage.\n\nLaissez ACTIVÉ si vous n’êtes pas sûr.",
"he_IL": "בודק לקבצים שגויים כאשר משחק עולה, ואם מתגלים כאלו, מציג את מזהה השגיאה שלהם לקובץ הלוג.\n\nאין לכך השפעה על הביצועים ונועד לעזור לבדיקה וניפוי שגיאות של האמולטור.\n\nמוטב להשאיר דלוק אם לא בטוחים.",
"it_IT": "Controlla la presenza di file corrotti quando si avvia un gioco. Se vengono rilevati dei file corrotti, verrà mostrato un errore di hash nel log.\n\nQuesta opzione non influisce sulle prestazioni ed è pensata per facilitare la risoluzione dei problemi.\n\nNel dubbio, lascia l'opzione attiva.",
"ja_JP": "ゲーム起動時にファイル破損をチェックし,破損が検出されたらログにハッシュエラーを表示します..\n\nパフォーマンスには影響なく, トラブルシューティングに役立ちます.\n\nよくわからない場合はオンのままにしてください.",
@@ -16533,7 +16483,7 @@
"no_NO": "Sjekker for korrupte filer ved oppstart av et spill, og dersom korrupte filer oppdages, viser en hashfeil i loggen.\n\nhar ingen innvirkning på ytelsen og er ment å hjelpe med feilsøking.\n\nLa være PÅ hvis usikker.",
"pl_PL": "Sprawdza pliki podczas uruchamiania gry i jeśli zostaną wykryte uszkodzone pliki, wyświetla w dzienniku błąd hash.\n\nNie ma wpływu na wydajność i ma pomóc w rozwiązywaniu problemów.\n\nPozostaw WŁĄCZONE, jeśli nie masz pewności.",
"pt_BR": "Verifica se há arquivos corrompidos ao inicializar um jogo e, se forem detectados, exibe um erro de hash no log.\n\nNão tem impacto no desempenho e tem como objetivo ajudar na solução de problemas.\n\nDeixe LIGADO se não tiver certeza.",
- "ru_RU": "Проверяет файлы при загрузке игры и если обнаружены поврежденные файлы, выводит сообщение о поврежденном хэше в журнале.\n\nНе влияет на производительность и необходим для помощи в устранении неполадок.\n\nРекомендуется оставить включенным.",
+ "ru_RU": "Проверяет на наличие повреждённых файлов при запуске игры, и если такие файлы обнаружены, отображает ошибку хеша в журнале.\n\nНе влияет на производительность и предназначено для помощи в устранении неполадок.\n\nРекомендуется оставить ВКЛЮЧЁННЫМ.",
"sv_SE": "Letar efter skadade filer när ett spel startas upp, och om skadade filer hittas, visas ett kontrollsummefel i loggen.\n\nHar ingen påverkan på prestandan och är tänkt att hjälpa felsökningen.\n\nLämna PÅ om du är osäker.",
"th_TH": "ตรวจสอบไฟล์ที่เสียหายเมื่อบูตเกม และหากตรวจพบไฟล์ที่เสียหาย จะแสดงข้อผิดพลาดของแฮชในบันทึก\n\nไม่มีผลกระทบต่อประสิทธิภาพการทำงานและมีไว้เพื่อช่วยในการแก้ไขปัญหา\n\nเปิดทิ้งไว้หากคุณไม่แน่ใจ",
"tr_TR": "Oyun açarken hatalı dosyaların olup olmadığını kontrol eder, ve hatalı dosya bulursa log dosyasında hash hatası görüntüler.\n\nPerformansa herhangi bir etkisi yoktur ve sorun gidermeye yardımcı olur.\n\nEmin değilseniz aktif halde bırakın.",
@@ -16550,7 +16500,7 @@
"el_GR": "Αλλαγή ήχου υποστήριξης",
"en_US": "Changes the backend used to render audio.\n\nSDL2 is the preferred one, while OpenAL and SoundIO are used as fallbacks. Dummy will have no sound.\n\nSet to SDL2 if unsure.",
"es_ES": "Cambia el motor usado para renderizar audio.\n\nSDL2 es el preferido, mientras que OpenAL y SoundIO se usan si hay problemas con este. Dummy no produce audio.\n\nSelecciona SDL2 si no sabes qué hacer.",
- "fr_FR": "Change le moteur utilisé pour le rendu audio.\n\nSDL2 est le moteur recommandé, tandis qu’OpenAL et SoundIO sont utilisés en secours. Dummy ne produit aucun son.\n\nLaissez sur SDL2 si vous n'êtes pas sûr.",
+ "fr_FR": "Modifie la backend utilisé pour donner un rendu audio.\n\nSDL2 est recommandé, tandis que OpenAL et SoundIO sont utilisés en secours. Dummy ne produit aucun son.\n\nLaissez sur SDL2 si vous n'êtes pas sûr.",
"he_IL": "משנה את אחראי השמע.\n\nSDL2 הוא הנבחר, למראת שOpenAL וגם SoundIO משומשים כאפשרויות חלופיות. אפשרות הDummy לא תשמיע קול כלל.\n\nמוטב להשאיר על SDL2 אם לא בטוחים.",
"it_IT": "Cambia il backend usato per riprodurre l'audio.\n\nSDL2 è quello preferito, mentre OpenAL e SoundIO sono usati come ripiego. Dummy non riprodurrà alcun suono.\n\nNel dubbio, imposta l'opzione su SDL2.",
"ja_JP": "音声レンダリングに使用するバックエンドを変更します.\n\nSDL2 が優先され, OpenAL と SoundIO はフォールバックとして使用されます. ダミーは音声出力しません.\n\nよくわからない場合は SDL2 を設定してください.",
@@ -16558,7 +16508,7 @@
"no_NO": "Endrer backend brukt til å gjengi lyd.\n\nSDL2 er foretrukket, mens OpenAL og SoundIO brukes som reserveløsning. Dummy kommer ikke til å ha lyd.\n\nSett til SDL2 hvis usikker.",
"pl_PL": "Zmienia backend używany do renderowania dźwięku.\n\nSDL2 jest preferowany, podczas gdy OpenAL i SoundIO są używane jako rezerwy. Dummy nie będzie odtwarzać dźwięku.\n\nW razie wątpliwości ustaw SDL2.",
"pt_BR": "Altera o módulo usado para renderizar áudio.\n\nSDL2 é o preferido, enquanto OpenAL e SoundIO são usados como fallbacks. Dummy não terá som.\n\nDefina como SDL2 se não tiver certeza.",
- "ru_RU": "Изменяет используемый аудио бэкенд для рендера звука.\n\nSDL2 является предпочтительным вариантом, в то время как OpenAL и SoundIO используются в качестве резервных.\n\nРекомендуется использование SDL2.",
+ "ru_RU": "Меняет бэкенд используемый для воспроизведения аудио.\n\nSDL2 — предпочтительный вариант, в то время как OpenAL и SoundIO используются как резервные. Dummy не будет воспроизводить звук.\n\nРекомендуется использовать SDL2.",
"sv_SE": "Ändrar bakänden som används för att rendera ljud.\n\nSDL2 är den föredragna, men OpenAL och SoundIO används för att falla tillbaka på. Dummy har inget ljud.\n\nStäll in till SDL2 om du är osäker.",
"th_TH": "เปลี่ยนแบ็กเอนด์ที่ใช้ในการเรนเดอร์เสียง\n\nแนะนำเป็น SDL2 ในขณะที่ OpenAL และ SoundIO ถูกใช้เป็นทางเลือกสำรอง ดัมมี่จะไม่มีเสียง\n\nตั้งค่าเป็น SDL2 หากคุณไม่แน่ใจ",
"tr_TR": "Ses çıkış motorunu değiştirir.\n\nSDL2 tercih edilen seçenektir, OpenAL ve SoundIO ise alternatif olarak kullanılabilir. Dummy seçeneğinde ses çıkışı olmayacaktır.\n\nEmin değilseniz SDL2 seçeneğine ayarlayın.",
@@ -16575,7 +16525,7 @@
"el_GR": "Αλλάξτε τον τρόπο αντιστοίχισης και πρόσβασης στη μνήμη επισκέπτη. Επηρεάζει σε μεγάλο βαθμό την απόδοση της προσομοίωσης της CPU.",
"en_US": "Change how guest memory is mapped and accessed. Greatly affects emulated CPU performance.\n\nSet to HOST UNCHECKED if unsure.",
"es_ES": "Cambia la forma de mapear y acceder a la memoria del guest. Afecta en gran medida al rendimiento de la CPU emulada.\n\nSelecciona \"Host sin verificación\" si no sabes qué hacer.",
- "fr_FR": "Modifie la manière dont la mémoire émulée est mappée et accédée. Impacte fortement les performances du processeur émulé.\n\nLaissez sur HÔTE NON VÉRIFIÉ si vous n'êtes pas sûr.",
+ "fr_FR": "Modifie la manière dont la mémoire émulée est mappée et accédée. Impacte fortement la performance du processeur émulé.\n\nLaissez sur HÔTE NON VÉRIFIÉ si vous n'êtes pas sûr.",
"he_IL": "שנה איך שזיכרון מארח מיוחד ומונגד. משפיע מאוד על ביצועי המעבד המדומה.\n\nמוטב להשאיר על מארח לא מבוקר אם לא בטוחים.",
"it_IT": "Cambia il modo in cui la memoria guest è mappata e vi si accede. Influisce notevolmente sulle prestazioni della CPU emulata.\n\nNel dubbio, imposta l'opzione su Host Unchecked.",
"ja_JP": "ゲストメモリのマップ/アクセス方式を変更します. エミュレートされるCPUのパフォーマンスに大きな影響を与えます.\n\nよくわからない場合は「ホスト,チェックなし」を設定してください.",
@@ -16583,7 +16533,7 @@
"no_NO": "Endre hvordan gjesteminne tilordnes og åpnes. Påvirker emulator CPU-ytelsen veldig mye.\n\nSett til HOST UNCHECKED hvis usikker.",
"pl_PL": "Zmień sposób mapowania i uzyskiwania dostępu do pamięci gości. Znacznie wpływa na wydajność emulowanego procesora.\n\nUstaw na HOST UNCHECKED, jeśli nie masz pewności.",
"pt_BR": "Altera como a memória do convidado é mapeada e acessada. Afeta muito o desempenho da CPU emulada.\n\nDefina como HÓSPEDE SEM VERIFICAÇÃO se não tiver certeza.",
- "ru_RU": "Меняет разметку и доступ к гостевой памяти. Значительно влияет на производительность процессора.\n\nРекомендуется оставить «Хост не установлен»",
+ "ru_RU": "Меняет способ отображения и доступа к памяти гостевой системы. Значительно влияет на производительность эмулируемого процессора.\n\nРекомендуется использовать ХОСТ БЕЗ ПРОВЕРКИ.",
"sv_SE": "Ändra hur gästminne mappas och ges åtkomst till. Påverkar emulerad CPU-prestanda mycket.\n\nStäll in till \"Värd inte kontrollerad\" om du är osäker.",
"th_TH": "เปลี่ยนวิธีการเข้าถึงหน่วยความจำของผู้เยี่ยมชม ส่งผลอย่างมากต่อประสิทธิภาพการทำงานของ CPU ที่จำลอง\n\nตั้งค่าเป็น ไม่ได้ตรวจสอบโฮสต์ หากคุณไม่แน่ใจ",
"tr_TR": "Guest hafızasının nasıl tahsis edilip erişildiğini değiştirir. Emüle edilen CPU performansını ciddi biçimde etkiler.\n\nEmin değilseniz HOST UNCHECKED seçeneğine ayarlayın.",
@@ -16600,7 +16550,7 @@
"el_GR": "Χρησιμοποιήστε έναν πίνακα σελίδων λογισμικού για τη μετάφραση διευθύνσεων. Υψηλότερη ακρίβεια αλλά πιο αργή απόδοση.",
"en_US": "Use a software page table for address translation. Highest accuracy but slowest performance.",
"es_ES": "Usa una tabla de paginación de software para traducir direcciones. Ofrece la precisión más exacta pero el rendimiento más lento.",
- "fr_FR": "Utilise une table des pages logicielle pour la traduction des adresses. Offre la plus grande précision mais les performances sont les plus lentes.",
+ "fr_FR": "Utilise une table logicielle pour la traduction d'adresses. La plus grande précision est fournie, mais la performance sera impactée.",
"he_IL": "השתמש בתוכנת ה-page table בכדי להתייחס לתרגומים. דיוק מרבי לקונסולה אך המימוש הכי איטי.",
"it_IT": "Usa una software page table per la traduzione degli indirizzi. Massima precisione ma prestazioni più lente.",
"ja_JP": "アドレス変換にソフトウェアページテーブルを使用します. 非常に正確ですがパフォーマンスが大きく低下します.",
@@ -16608,7 +16558,7 @@
"no_NO": "Bruk en programvareside tabell for adresseoversettelse. Høyeste nøyaktighet, men tregeste ytelse.",
"pl_PL": "Użyj tabeli stron oprogramowania do translacji adresów. Najwyższa celność, ale najwolniejsza wydajność.",
"pt_BR": "Usar uma tabela de página via software para tradução de endereços. Maior precisão, porém performance mais baixa.",
- "ru_RU": "Использует таблицу страниц для преобразования адресов. \nСамая высокая точность, но самая низкая производительность.",
+ "ru_RU": "Использовать программную таблицу страниц для преобразования адресов. Самая высокая точность, но самая низкая производительность.",
"sv_SE": "Använd en programvarubaserad page table för adressöversättning. Högsta noggrannhet men lägsta prestanda.",
"th_TH": "ใช้ตารางหน้าซอฟต์แวร์สำหรับการแปลที่อยู่ ความแม่นยำสูงสุดแต่ประสิทธิภาพช้าที่สุด",
"tr_TR": "Adres çevirisi için bir işlemci sayfası kullanır. En yüksek doğruluğu ve en yavaş performansı sunar.",
@@ -16625,7 +16575,7 @@
"el_GR": "Απευθείας αντιστοίχιση της μνήμης στον χώρο διευθύνσεων υπολογιστή υποδοχής. Πολύ πιο γρήγορη μεταγλώττιση και εκτέλεση JIT.",
"en_US": "Directly map memory in the host address space. Much faster JIT compilation and execution.",
"es_ES": "Mapea la memoria directamente en la dirección de espacio del host. Compilación y ejecución JIT mucho más rápida.",
- "fr_FR": "Mappe directement la mémoire dans l’espace d’adressage de l’hôte. Compilation JIT et exécution beaucoup plus rapides.",
+ "fr_FR": "Mappe directement la mémoire dans l'espace d'adresses de l'hôte. Compilation et exécution JIT beaucoup plus rapides.",
"he_IL": "ממפה זיכרון ישירות לכתובת המארח. מהיר בהרבה ביכולות קימפול ה-JIT והריצה.",
"it_IT": "Mappa direttamente la memoria nello spazio degli indirizzi dell'host. Compilazione ed esecuzione JIT molto più veloce.",
"ja_JP": "ホストのアドレス空間にメモリを直接マップします.JITのコンパイルと実行速度が大きく向上します.",
@@ -16633,7 +16583,7 @@
"no_NO": "Direkte kartminne i vertens adresseområde. Mye raskere JIT kompilering og utførelse.",
"pl_PL": "Bezpośrednio mapuj pamięć w przestrzeni adresowej hosta. Znacznie szybsza kompilacja i wykonanie JIT.",
"pt_BR": "Mapeia memória no espaço de endereço hóspede diretamente. Compilação e execução do JIT muito mais rápida.",
- "ru_RU": "Прямая разметка памяти в адресном пространстве хоста. \nЗначительно более быстрые запуск и компиляция JIT.",
+ "ru_RU": "Прямое отображение памяти в адресном пространстве хоста. Значительно более быстрый запуск и компиляция JIT.",
"sv_SE": "Direkt mappning av minne i host address space. Mycket snabbare JIT-kompilering och körning.",
"th_TH": "แมปหน่วยความจำในพื้นที่ที่อยู่โฮสต์โดยตรง การคอมไพล์และดำเนินการของ JIT เร็วขึ้นมาก",
"tr_TR": "Hafızayı doğrudan host adres aralığında tahsis eder. Çok daha hızlı JIT derleme ve işletimi sunar.",
@@ -16658,7 +16608,7 @@
"no_NO": "Direkte kartminne, men ikke masker adressen i gjesteadressen før du har tilgang. raskere, men på bekostning av sikkerhet. gjeste-programmet kan få tilgang til minne fra hvor som helst i Ryujinx, så bare kjøre programmer du stoler på med denne modusen.",
"pl_PL": "Bezpośrednio mapuj pamięć, ale nie maskuj adresu w przestrzeni adresowej gościa przed uzyskaniem dostępu. Szybciej, ale kosztem bezpieczeństwa. Aplikacja gościa może uzyskać dostęp do pamięci z dowolnego miejsca w Ryujinx, więc w tym trybie uruchamiaj tylko programy, którym ufasz.",
"pt_BR": "Mapeia memória diretamente, mas sem limitar o acesso ao espaço de endereçamento do sistema convidado. Mais rápido, porém menos seguro. O aplicativo convidado pode acessar memória de qualquer parte do Ryujinx, então apenas rode programas em que você confia nesse modo.",
- "ru_RU": "Производит прямую разметку памяти, но не маскирует адрес в гостевом адресном пространстве перед получением доступа. \nБыстро, но небезопасно. Гостевое приложение может получить доступ к памяти из Ryujinx, поэтому в этом режиме рекомендуется запускать только те программы, которым вы доверяете.",
+ "ru_RU": "Прямое отображение памяти, но без маскировки адреса в адресном пространстве гостевой системы перед доступом. Быстрее, но за счёт безопасности. Гостевая программа может получить доступ к памяти из любого места в Ryujinx, поэтому запускайте только доверенные программы в этом режиме.",
"sv_SE": "Direkt mappning av minne, men maskera inte adressen inom guest address space innan åtkomst. Snabbare men kostar säkerhet. Gästapplikationen kan komma åt minne från överallt i Ryujinx, så kör endast program som du litar på i detta läge.",
"th_TH": "แมปหน่วยความจำโดยตรง แต่อย่าตั้งค่าที่อยู่ของผู้เยี่ยมชมก่อนที่จะเข้าถึง เร็วกว่า แต่ต้องแลกกับความปลอดภัย แอปพลิเคชั่นของผู้เยี่ยมชมสามารถเข้าถึงหน่วยความจำได้จากทุกที่ใน Ryujinx แนะนำให้รันเฉพาะโปรแกรมที่คุณเชื่อถือในโหมดนี้",
"tr_TR": "Hafızayı doğrudan tahsis eder, ancak host aralığına erişimden önce adresi maskelemez. Daha iyi performansa karşılık emniyetten ödün verir. Misafir uygulama Ryujinx içerisinden istediği hafızaya erişebilir, bu sebeple bu seçenek ile sadece güvendiğiniz uygulamaları çalıştırın.",
@@ -16675,7 +16625,7 @@
"el_GR": "Χρησιμοποιήστε Hypervisor αντί για JIT. Βελτιώνει σημαντικά την απόδοση όταν διατίθεται, αλλά μπορεί να είναι ασταθής στην τρέχουσα κατάστασή του.",
"en_US": "Use Hypervisor instead of JIT. Greatly improves performance when available, but can be unstable in its current state.",
"es_ES": "Usar Hypervisor en lugar de JIT. Mejora enormemente el rendimiento cuando está disponible, pero puede ser inestable en su estado actual.",
- "fr_FR": "Utiliser l'Hyperviseur au lieu du JIT. Améliore considérablement les performances lorsque disponible, mais peut être instable dans son état actuel.",
+ "fr_FR": "Utilise l'Hyperviseur au lieu du JIT. Améliore considérablement la performance lorsque disponible, mais peut être instable dans son état actuel.",
"he_IL": "השתמש ב- Hypervisor במקום JIT. משפר מאוד ביצועים כשניתן, אבל יכול להיות לא יציב במצבו הנוכחי.",
"it_IT": "Usa Hypervisor invece di JIT. Migliora notevolmente le prestazioni quando disponibile, ma può essere instabile nel suo stato attuale.",
"ja_JP": "JIT の代わりにハイパーバイザーを使用します. 利用可能な場合, パフォーマンスが大幅に向上しますが, 現在の状態では不安定になる可能性があります.",
@@ -16683,7 +16633,7 @@
"no_NO": "Bruk Hypervisor i stedet for JIT. Det øker ytelsen mye hvis det er tilgjengelig, men det kan være ustabilt i den nåværende tilstanden.",
"pl_PL": "Użyj Hiperwizora zamiast JIT. Znacznie poprawia wydajność, gdy jest dostępny, ale może być niestabilny w swoim obecnym stanie ",
"pt_BR": "Usa o Hypervisor em vez de JIT (recompilador dinâmico). Melhora significativamente o desempenho quando disponível, mas pode ser instável no seu estado atual.",
- "ru_RU": "Использует Hypervisor вместо JIT. Значительно увеличивает производительность, но может работать нестабильно.",
+ "ru_RU": "Использует Hypervisor вместо JIT. Когда доступен, значительно улучшает производительность, но может быть нестабильным в текущем состоянии.",
"sv_SE": "Använd hypervisor istället för JIT. Förbättrar prestandan avsevärt när den finns tillgänglig men kan ge ostabilitet i dess aktuella tillstånd.",
"th_TH": "ใช้ Hypervisor แทน JIT ปรับปรุงประสิทธิภาพอย่างมากเมื่อพร้อมใช้งาน แต่อาจไม่เสถียรในสถานะปัจจุบัน",
"tr_TR": "JIT yerine Hypervisor kullan. Uygun durumlarda performansı büyük oranda arttırır. Ancak şu anki halinde stabil durumda çalışmayabilir.",
@@ -16698,9 +16648,9 @@
"ar_SA": "يستخدم تخطيط وضع الذاكرة البديل لتقليد نموذج سويتش المطورين.\n\nيعد هذا مفيدا فقط لحزم النسيج عالية الدقة أو تعديلات دقة 4K. لا يحسن الأداء.\n\nاتركه معطلا إذا لم تكن متأكدا.",
"de_DE": "Erhöht den Arbeitsspeicher des emulierten Systems von 4 GiB auf 6 GiB.\n\nDies ist nur für Texturenpakete mit höherer Auflösung oder Mods mit 4K-Auflösung nützlich. Diese Option verbessert NICHT die Leistung.\n\nIm Zweifelsfall AUS lassen.",
"el_GR": "Επεκτείνει την ποσότητα της μνήμης στο εξομοιούμενο σύστημα από 4 GiB σε 6 GiB",
- "en_US": "Utilizes an alternative memory mode with 8GiB of DRAM to mimic a Switch development model.\n\nThis is only useful for higher-resolution texture packs or 4k resolution mods. Does NOT improve performance.\n\nLeave OFF if unsure.",
+ "en_US": "Utilizes an alternative memory mode with 8GiB of DRAM to mimic a Switch development model.\n\nThis is only useful for higher-resolution texture packs or 4k resolution mods. Does NOT improve performance.\n\nLeave at 4GiB if unsure.",
"es_ES": "Expande la memoria DRAM del sistema emulado de 4GiB a 6GiB.\n\nUtilizar solo con packs de texturas HD o mods de resolución 4K. NO mejora el rendimiento.\n\nDesactívalo si no sabes qué hacer.",
- "fr_FR": "Utilise un mode mémoire alternatif avec 4, 6, 8 ou 12GiO de DRAM pour simuler un modèle de développement Switch.\n\nUtile uniquement pour les packs de textures haute résolution ou les mods en 4K.\nN’améliore PAS les performances.\n\nLaissez à 4GiO si vous n’êtes pas sûr.",
+ "fr_FR": "Utilise un mode mémoire alternatif avec 4, 6, 8 ou 12GiO de DRAM pour simuler un modèle de développement Switch.\n\nUtile uniquement pour les packs de textures haute résolution ou les mods en 4K.\nN’améliore PAS la performance.\n\nLaissez à 4GiO si vous n’êtes pas sûr.",
"he_IL": "מנצל תצורת מצב-זיכרון חלופית לחכות את מכשיר הפיתוח של הסוויץ'.\n\nזה שימושי להחלפת חבילות מרקמים באיכותיים יותר או כאלו ברזולוציית 4k. לא משפר ביצועים.\n\nמוטב להשאיר כבוי אם לא בטוחים.",
"it_IT": "Utilizza un layout di memoria alternativo per imitare un'unità di sviluppo di Switch.\n\nQuesta opzione è utile soltanto per i pacchetti di texture ad alta risoluzione o per le mod che aumentano la risoluzione a 4K. NON migliora le prestazioni.\n\nNel dubbio, lascia l'opzione disattivata.",
"ja_JP": "エミュレートされたシステムのメモリ容量を 4GiB から 6GiB に増加します.\n\n高解像度のテクスチャパックや 4K解像度の mod を使用する場合に有用です. パフォーマンスを改善するものではありません.\n\nよくわからない場合はオフのままにしてください.",
@@ -16708,7 +16658,7 @@
"no_NO": "Bruker en alternativ minnemodus med 8GiB i DRAM for og etterligne Switch utvikler modeller.\n\nDette er bare nyttig for teksturpakker eller 4k oppløsningsmoduler. Forbedrer IKKE ytelsen.\n\nLa AV hvis usikker.",
"pl_PL": "Wykorzystuje alternatywny układ MemoryMode, aby naśladować model rozwojowy Switcha.\n\nJest to przydatne tylko w przypadku pakietów tekstur o wyższej rozdzielczości lub modów w rozdzielczości 4k. NIE poprawia wydajności.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.",
"pt_BR": "Utiliza um modo de memória alternativo com 6, 8 ou 12 GB de DRAM para imitar um modelo de desenvolvimento do Switch.\n\nIsso só é útil para pacotes de textura de alta resolução ou mods de resolução 4k. NÃO melhora o desempenho.\n\nDeixe em 4 GB se não tiver certeza.",
- "ru_RU": "Использует альтернативный макет MemoryMode для имитации использования Nintendo Switch в режиме разработчика.\n\nПолезно только для пакетов текстур с высоким разрешением или модов добавляющих разрешение 4К. Не улучшает производительность.\n\nРекомендуется оставить выключенным.",
+ "ru_RU": "Использует альтернативный режим памяти с 4, 6, 8, или 12 ГиБ ОЗУ для имитации Nintendo Switch в режиме разработчика.\n\nЭто полезно только для текстурных пакетов с более высоким разрешением или модов с разрешением 4K. НЕ улучшает производительность.\n\nРекомендуется использовать 4ГиБ.",
"sv_SE": "Använder ett alternativt minnesläge med 8GiB av DRAM för att efterlikna en utvecklingsmodell av Switch.\n\nDetta är endast användbart för texturpaket med högre upplösning eller moddar för 4k-upplösning. Det förbättrar INTE prestandan.\n\nLämna AV om du är osäker.",
"th_TH": "ใช้รูปแบบ MemoryMode ทางเลือกเพื่อเลียนแบบโมเดลการพัฒนาสวิตช์\n\nสิ่งนี้มีประโยชน์สำหรับแพ็กพื้นผิวที่มีความละเอียดสูงกว่าหรือม็อดที่มีความละเอียด 4k เท่านั้น\n\nปล่อยให้ปิดหากคุณไม่แน่ใจ",
"tr_TR": "Emüle edilen sistem hafızasını 4GiB'dan 6GiB'a yükseltir.\n\nBu seçenek yalnızca yüksek çözünürlük doku paketleri veya 4k çözünürlük modları için kullanılır. Performansı artırMAZ!\n\nEmin değilseniz devre dışı bırakın.",
@@ -16733,7 +16683,7 @@
"no_NO": "Ignorerer ikke implementerte Horisont OS-tjenester. Dette kan hjelpe med å omgå krasj ved oppstart av enkelte spill.\n\nLa AV hvis du er usikker.",
"pl_PL": "Ignoruje niezaimplementowane usługi Horizon OS. Może to pomóc w ominięciu awarii podczas uruchamiania niektórych gier.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.",
"pt_BR": "Ignora serviços não implementados do Horizon OS. Isso pode ajudar a contornar travamentos ao inicializar certos jogos.\n\nDeixe OFF se não tiver certeza.",
- "ru_RU": "Игнорирует нереализованные сервисы Horizon в новых прошивках. Эта настройка поможет избежать вылеты при запуске определенных игр.\n\nРекомендуется оставить выключенным.",
+ "ru_RU": "Игнорирует не реализованные сервисы операционной системы Horizon. Это может помочь избежать сбоев при запуске некоторых игр.\n\nРекомендуется оставить ВЫКЛЮЧЕННЫМ.",
"sv_SE": "Ignorerar Horizon OS-tjänster som inte har implementerats. Detta kan avhjälpa krascher när vissa spel startar upp.\n\nLämna AV om du är osäker.",
"th_TH": "ละเว้นบริการ Horizon OS ที่ยังไม่ได้ใช้งาน วิธีนี้อาจช่วยในการหลีกเลี่ยงข้อผิดพลาดเมื่อบูตเกมบางเกม\n\nปล่อยให้ปิดหากคุณไม่แน่ใจ",
"tr_TR": "Henüz programlanmamış Horizon işletim sistemi servislerini görmezden gelir. Bu seçenek belirli oyunların açılırken çökmesinin önüne geçmeye yardımcı olabilir.\n\nEmin değilseniz devre dışı bırakın.",
@@ -16750,7 +16700,7 @@
"el_GR": "",
"en_US": "The Controller Applet dialog will not appear if the gamepad is disconnected while an application is running.\n\nLeave OFF if unsure.",
"es_ES": "",
- "fr_FR": "La fenêtre de l’applet manette ne s’affichera pas si la manette est déconnectée pendant l’exécution d’une application\n\nLaissez DÉSACTIVÉ si vous n’êtes pas sûr.",
+ "fr_FR": "La fenêtre de l’Applet Manette ne s’affichera pas si la manette est déconnectée pendant l’exécution d’une application\n\nLaissez DÉSACTIVÉ si vous n’êtes pas sûr.",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -16758,9 +16708,9 @@
"no_NO": "Håndkontroller-appleten vises ikke hvis gamepaden kobles fra mens et program kjører.",
"pl_PL": "",
"pt_BR": "A caixa de diálogo do Applet do controlador não aparecerá se o controle for desconectado enquanto um aplicativo estiver em execução.\n\nDeixe a opção DESLIGADO se não tiver certeza.",
- "ru_RU": "Диалоговое окно апплета контроллера не будет отображаться, если геймпад отключен во время работы приложения.\n\nОставьте выключенным, если не уверены.",
+ "ru_RU": "Окно апплета контроллера не появится, если контроллер был отключён во время работы приложения.\n\nРекомендуется оставить ВЫКЛЮЧЕННЫМ.",
"sv_SE": "Handkontroller-appleten kommer inte att visas om gamepaden är frånkopplad under tiden en applikation körs.\n\nLämna AV om du är osäker.",
- "th_TH": "",
+ "th_TH": "กล่องโต้ตอบของ Controller Applet จะไม่ปรากฏขึ้น หากเกมแพดถูกถอดออกในขณะที่แอปพลิเคชันกำลังทำงานอยู่\n\nหากไม่แน่ใจ ให้ปิดการใช้งานไว้",
"tr_TR": "",
"uk_UA": "Діалогове вікно Аплету Контролера не з'явиться, якщо геймпад було відключено під час роботи програми.\n\nЗалиште вимкненим якщо не впевнені.",
"zh_CN": "在应用程序运行时如果游戏手柄断开连接则不会显示控制器小程序对话框。\n\n如果不确定,请保持关闭状态。",
@@ -16783,7 +16733,7 @@
"no_NO": "Dette alternativet hopper over dialogen 'Administrere Brukerprofiler' under spilling, og bruker en forhåndsvalgt profil.\n\nProfilbytte finnes i 'Innstillinger' - 'Administrer Brukerprofiler'. Velg ønsket profil før du laster spillet.",
"pl_PL": "Ta opcja pomija okno dialogowe 'Zarządzaj profilami użytkowników' podczas gry, używając wcześniej wybrany profil.\n\nPrzełączanie profili można znaleźć w 'Ustawienia' - 'Zarządzaj Profilami Użytkowników'. Wybierz żądany profil przed załadowaniem gry.",
"pt_BR": "Esta opção ignora a caixa de diálogo 'Gerenciar Perfis de Usuário' durante o jogo, usando um perfil pré-selecionado.\n\nO gerenciamento de perfis pode ser encontrado em 'Configurações' - 'Gerenciar Perfis de Usuários'. Selecione o perfil desejado antes de carregar o jogo.",
- "ru_RU": "Эта опция пропускает диалоговое окно 'Менеджер учётных записей' во время игры, используя предварительно выбранный профиль.\n\nПереключение профилей можно найти в 'Параметры' - 'Менеджер учётных записей'. Выберите желаемый профиль перед загрузкой игры.",
+ "ru_RU": "Эта опция пропускает окно 'Управление профилями' во время игры, используя заранее выбранный профиль.\n\nПереключение профилей доступно в разделе 'Параметры' - 'Управление профилями'. Выберите нужный профиль перед запуском игры.",
"sv_SE": "Det här alternativet hoppar över dialogrutan 'Hantera användarprofiler' under spelet och använder en förvald profil.\n\nProfilväxling finns i 'Inställningar' - 'Hantera användarprofiler'. Välj önskad profil innan du laddar spelet.",
"th_TH": "ตัวเลือกนี้จะข้ามหน้าต่าง 'จัดการโปรไฟล์ผู้ใช้งาน' ระหว่างเล่นเกม โดยใช้โปรไฟล์ที่เลือกไว้ล่วงหน้า\n\nการสลับโปรไฟล์สามารถพบได้ใน 'ตั้งค่า' - 'จัดการโปรไฟล์ผู้ใช้งาน' เลือกโปรไฟล์ที่คุณต้องการก่อนโหลดเกม",
"tr_TR": "Bu seçenek, oyun sırasında 'Kullanıcı Profillerini Yönet' iletişim kutusunu atlar ve önceden seçilmiş bir profil kullanır.\n\nProfil değiştirme 'Seçenekler' - 'Kullanıcı Profillerini Yönet' bölümünde bulunur. Oyunu yüklemeden önce istediğiniz profili seçin.",
@@ -16800,7 +16750,7 @@
"el_GR": "Ενεργοποίηση Πολυνηματικής Επεξεργασίας Γραφικών",
"en_US": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.",
"es_ES": "Ejecuta los comandos del motor gráfico en un segundo hilo. Acelera la compilación de sombreadores, reduce los tirones, y mejora el rendimiento en controladores gráficos que no realicen su propio procesamiento con múltiples hilos. Rendimiento ligeramente superior en controladores gráficos que soporten múltiples hilos.\n\nSelecciona \"Auto\" si no sabes qué hacer.",
- "fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore les performances sur les pilotes GPU sans support natif du multithreading. Offre une légère amélioration des performances sur les pilotes multithreadés.\n\nRéglez sur AUTO si vous n’êtes pas sûr.",
+ "fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore la performance sur les pilotes GPU sans support natif du multithreading. Offre une légère amélioration des performances sur les pilotes multithreadés.\n\nRéglez sur AUTO si vous n’êtes pas sûr.",
"he_IL": "מריץ פקודות גראפיקה בתהליך שני נפרד.\n\nמאיץ עיבוד הצללות, מפחית תקיעות ומשפר ביצועים של דרייבר כרטיסי מסך אשר לא תומכים בהרצה רב-תהליכית.\n\nמוטב להשאיר על אוטומטי אם לא בטוחים.",
"it_IT": "Esegue i comandi del backend grafico su un secondo thread.\n\nVelocizza la compilazione degli shader, riduce lo stuttering e migliora le prestazioni sui driver grafici senza il supporto integrato al multithreading. Migliora leggermente le prestazioni sui driver che supportano il multithreading.\n\nNel dubbio, imposta l'opzione su Automatico.",
"ja_JP": "グラフィックスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
@@ -16808,7 +16758,7 @@
"no_NO": "Utfører grafikkbackend kommandoer på en annen tråd.\n\nØker hastigheten for shaderkomprimering, reduserer hakking og forbedrer ytelsen til GPU-drivere uten å spre støtten fra sine egne. Litt bedre ytelse på drivere med flertråd.\n\nSett for å AUTO hvis usikker.",
"pl_PL": "Wykonuje polecenia backend'u graficznego w drugim wątku.\n\nPrzyspiesza kompilację shaderów, zmniejsza zacinanie się i poprawia wydajność sterowników GPU bez własnej obsługi wielowątkowości. Nieco lepsza wydajność w sterownikach z wielowątkowością.\n\nUstaw na AUTO, jeśli nie masz pewności.",
"pt_BR": "Executa comandos do renderizador gráfico em um segundo thread.\n\nAcelera a compilação de shader, reduz a gagueira e melhora o desempenho em drivers de GPU sem suporte multithreading próprio. Desempenho ligeiramente melhor em drivers com multithreading.\n\nDefina como AUTO se não tiver certeza.",
- "ru_RU": "Выполняет команды графического бэкенда на втором потоке.\n\nУскоряет компиляцию шейдеров, уменьшает статтеры и повышает производительность на драйверах видеоадаптера без поддержки многопоточности. Производительность на драйверах с многопоточностью немного выше.\n\nРекомендуется оставить Автоматически.",
+ "ru_RU": "Выполняет команды графического бэкенда на втором потоке.\n\nУскоряет компиляцию шейдеров, уменьшает статтеры и повышает производительность на драйверах видеоадаптера без поддержки многопоточности. Производительность на драйверах с многопоточностью немного выше.\n\nРекомендуется оставить АВТОМАТИЧЕСКИ.",
"sv_SE": "Kör kommandon för grafikbakände i en andra tråd.\n\nSnabbar upp shader compilation, minskar stuttering och förbättrar prestandan på GPU-drivrutiner utan stöd för egen multithreading. Något bättre prestanda på drivrutiner med multithreading.\n\nStäll in till AUTO om du är osäker.",
"th_TH": "ดำเนินการคำสั่งแบ็กเอนด์กราฟิกบนเธรดที่สอง\n\nเร่งความเร็วการคอมไพล์ ลดการกระตุก และปรับปรุงประสิทธิภาพการทำงานของไดรเวอร์ GPU โดยไม่ต้องรองรับมัลติเธรดในตัว ประสิทธิภาพที่ดีขึ้นเล็กน้อยสำหรับไดรเวอร์ที่มีมัลติเธรด\n\nตั้งเป็น อัตโนมัติ หากคุณไม่แน่ใจ",
"tr_TR": "Grafik arka uç komutlarını ikinci bir iş parçacığında işletir.\n\nKendi multithreading desteği olmayan sürücülerde shader derlemeyi hızlandırıp performansı artırır. Multithreading desteği olan sürücülerde çok az daha iyi performans sağlar.\n\nEmin değilseniz Otomatik seçeneğine ayarlayın.",
@@ -16825,7 +16775,7 @@
"el_GR": "Εκτελεί εντολές γραφικών σε ένα δεύτερο νήμα. Επιτρέπει την πολυνηματική μεταγλώττιση Shader σε χρόνο εκτέλεσης, μειώνει το τρεμόπαιγμα και βελτιώνει την απόδοση των προγραμμάτων οδήγησης χωρίς τη δική τους υποστήριξη πολλαπλών νημάτων. Ποικίλες κορυφαίες επιδόσεις σε προγράμματα οδήγησης με multithreading. Μπορεί να χρειαστεί επανεκκίνηση του Ryujinx για να απενεργοποιήσετε σωστά την ενσωματωμένη λειτουργία πολλαπλών νημάτων του προγράμματος οδήγησης ή ίσως χρειαστεί να το κάνετε χειροκίνητα για να έχετε την καλύτερη απόδοση.",
"en_US": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.",
"es_ES": "Ejecuta los comandos del motor gráfico en un segundo hilo. Acelera la compilación de sombreadores, reduce los tirones, y mejora el rendimiento en controladores gráficos que no realicen su propio procesamiento con múltiples hilos. Rendimiento ligeramente superior en controladores gráficos que soporten múltiples hilos.\n\nSelecciona \"Auto\" si no sabes qué hacer.",
- "fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore les performances sur les pilotes GPU sans support natif du multithreading. Offre une légère amélioration des performances sur les pilotes multithreadés.\n\nRéglez sur AUTO si vous n’êtes pas sûr.",
+ "fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore la performance sur les pilotes GPU sans support de multithreading. Légère augementation des performances sur les pilotes avec multithreading intégrer.\n\nRéglez sur Auto en cas d'incertitude.",
"he_IL": "מריץ פקודות גראפיקה בתהליך שני נפרד.\n\nמאיץ עיבוד הצללות, מפחית תקיעות ומשפר ביצועים של דרייבר כרטיסי מסך אשר לא תומכים בהרצה רב-תהליכית.\n\nמוטב להשאיר על אוטומטי אם לא בטוחים.",
"it_IT": "Esegue i comandi del backend grafico su un secondo thread.\n\nVelocizza la compilazione degli shader, riduce lo stuttering e migliora le prestazioni sui driver grafici senza il supporto integrato al multithreading. Migliora leggermente le prestazioni sui driver che supportano il multithreading.\n\nNel dubbio, imposta l'opzione su Automatico.",
"ja_JP": "グラフィックスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
@@ -16833,7 +16783,7 @@
"no_NO": "Utfører grafikkbackend kommandoer på en annen tråd.\n\nØker hastigheten for shaderkomprimering, reduserer hakking og forbedrer ytelsen til GPU-drivere uten flertråd støtte. Litt bedre ytelse på drivere med flertråd.\n\nSett for å AUTO hvis usikker.",
"pl_PL": "Wykonuje polecenia backend'u graficznego w drugim wątku.\n\nPrzyspiesza kompilację shaderów, zmniejsza zacinanie się i poprawia wydajność sterowników GPU bez własnej obsługi wielowątkowości. Nieco lepsza wydajność w sterownikach z wielowątkowością.\n\nUstaw na AUTO, jeśli nie masz pewności.",
"pt_BR": "Executa comandos do renderizador gráfico em um segundo thread.\n\nAcelera a compilação de shader, reduz a gagueira e melhora o desempenho em drivers de GPU sem suporte multithreading próprio. Desempenho ligeiramente melhor em drivers com multithreading.\n\nDefina como AUTO se não tiver certeza.",
- "ru_RU": "Выполняет команды графического бэкенда на втором потоке.\n\nУскоряет компиляцию шейдеров, уменьшает статтеры и повышает производительность на драйверах видеоадаптера без поддержки многопоточности. Производительность на драйверах с многопоточностью немного выше.\n\nРекомендуется оставить Автоматически.",
+ "ru_RU": "Выполняет команды графического бэкенда на втором потоке.\n\nУскоряет компиляцию шейдеров, уменьшает статтеры и повышает производительность на драйверах видеоадаптера без поддержки многопоточности. Производительность на драйверах с многопоточностью немного выше.\n\nРекомендуется оставить АВТОМАТИЧЕСКИ.",
"sv_SE": "Kör kommandon för grafikbakände i en andra tråd.\n\nSnabbar upp shader compilation, minskar stuttering och förbättrar prestandan på GPU-drivrutiner utan stöd för egen multithreading. Något bättre prestanda på drivrutiner med multithreading.\n\nStäll in till AUTO om du är osäker.",
"th_TH": "ดำเนินการคำสั่งแบ็กเอนด์กราฟิกบนเธรดที่สอง\n\nเร่งความเร็วการคอมไพล์เชเดอร์ ลดการกระตุก และปรับปรุงประสิทธิภาพการทำงานของไดรเวอร์ GPU โดยไม่ต้องรองรับมัลติเธรดในตัว ประสิทธิภาพที่ดีขึ้นเล็กน้อยสำหรับไดรเวอร์ที่มีมัลติเธรด\n\nตั้งเป็น อัตโนมัติ หากคุณไม่แน่ใจ",
"tr_TR": "Grafik arka uç komutlarını ikinci bir iş parçacığında işletir.\n\nKendi multithreading desteği olmayan sürücülerde shader derlemeyi hızlandırıp performansı artırır. Multithreading desteği olan sürücülerde çok az daha iyi performans sağlar.\n\nEmin değilseniz Otomatik seçeneğine ayarlayın.",
@@ -16854,11 +16804,11 @@
"he_IL": "שומר זכרון מטמון של הצללות, דבר שמפחית תקיעות בריצות מסוימות.\n\nמוטב להשאיר דלוק אם לא בטוחים.",
"it_IT": "Salva una cache degli shader su disco che riduce i fenomeni di stuttering nelle esecuzioni successive.\n\nNel dubbio, lascia l'opzione attiva.",
"ja_JP": "ディスクシェーダーキャッシュをセーブし,次回以降の実行時遅延を軽減します.\n\nよくわからない場合はオンのままにしてください.",
- "ko_KR": "후속 실행 시 끊김 현상을 줄이는 디스크 셰이더 캐시를 저장합니다.\n\n모르면 체크 상태로 두세요.",
+ "ko_KR": "후속 실행 시, 끊김 현상을 줄이는 디스크 셰이더 캐시를 저장합니다.\n\n모르면 체크 상태로 두세요.",
"no_NO": "Lagrer en disk shader cache som reduserer hakking jo flere ganger du spiller.\n\nLa være PÅ om usikker.",
"pl_PL": "Zapisuje pamięć podręczną shaderów na dysku, co zmniejsza zacinanie się w kolejnych uruchomieniach.\n\nPozostaw WŁĄCZONE, jeśli nie masz pewności.",
"pt_BR": "Salva um cache de shader no disco que reduz a trepidação em execuções subsequentes.\n\nDeixe LIGADO se não tiver certeza.",
- "ru_RU": "Сохраняет кэш шейдеров на диске, для уменьшения статтеров при последующих запусках.\n\nРекомендуется оставить включенным.",
+ "ru_RU": "Сохраняет кэш шейдеров на диске, для уменьшения статтеров при последующих запусках.\n\nРекомендуется оставить ВКЛЮЧЁННЫМ.",
"sv_SE": "Sparar en disk shader cache som minskar stuttering i efterföljande körningar.\n\nLämna PÅ om du är osäker.",
"th_TH": "บันทึกแคชแสงเงาของดิสก์ซึ่งช่วยลดการกระตุกในการรันครั้งต่อๆ ไป\n\nเปิดทิ้งไว้หากคุณไม่แน่ใจ",
"tr_TR": "Sonraki çalışmalarda takılmaları engelleyen bir gölgelendirici disk önbelleğine kaydeder.",
@@ -16883,7 +16833,7 @@
"no_NO": "Dobler spillets gjengivelse.\n\nNoen få spill fungerer kanskje ikke med dette aktivert og kan se veldig pikselert ut selv når gjengivelsen er økt; for de spillene, så kan det hende du må bruke modifikasjoner som fjerner anti-aliasing eller som øker den interne gjengivelsen. For og bruke sistnenvte, så vil du helst bruke \"Native\".\n\nHa til tanke at 4x er unødig for virituelt alle maskiner.",
"pl_PL": "",
"pt_BR": "Multiplica a resolução de renderização do jogo.\n\nAlguns jogos podem não funcionar bem com essa opção e apresentar uma aparência pixelada, mesmo com o aumento da resolução; para esses jogos, talvez seja necessário encontrar mods que removam o anti-aliasing ou aumentem a resolução de renderização interna. Ao usar a segunda opção, provavelmente desejará selecionar Nativa.\n\nEssa opção pode ser alterada enquanto um jogo está em execução, clicando em \"Aplicar\" abaixo; basta mover a janela de configurações para o lado e experimentar até encontrar o visual preferido para o jogo.\n\nLembre-se de que 4x é exagerado para praticamente qualquer configuração.",
- "ru_RU": "Увеличивает разрешение рендера игры.\n\nНекоторые игры могут не работать с этой настройкой и выглядеть смазано даже когда разрешение увеличено. Для таких игр может потребоваться установка модов, которые убирают сглаживание или увеличивают разрешение рендеринга. \nДля использования последнего, вам нужно будет выбрать опцию «Нативное».\n\nЭта опция может быть изменена во время игры по нажатию кнопки «Применить» ниже. Вы можете просто переместить окно настроек в сторону и поэкспериментировать, пока не подберете подходящие настройки для конкретной игры.\n\nИмейте в виду, что «4x» является излишеством.",
+ "ru_RU": "Увеличивает разрешение рендера игры.\n\nНекоторые игры могут не работать с этой настройкой и выглядеть смазано даже когда разрешение увеличено. Для таких игр может потребоваться установка модов, которые убирают сглаживание или увеличивают разрешение рендеринга.\nДля использования последнего, вам нужно будет выбрать опцию «Нативное».\n\nЭта опция может быть изменена во время игры по нажатию кнопки «Применить» ниже. Вы можете просто переместить окно настроек в сторону и поэкспериментировать, пока не подберете подходящие настройки для конкретной игры.\n\nИмейте в виду, что «4x» является излишеством.",
"sv_SE": "Multiplicerar spelets renderingsupplösning.\n\nNågra spel kanske inte fungerar med detta och ser pixelerade ut även när upplösningen ökas; för dessa spel så kan du behöva hitta moddar som tar bort anti-aliasing eller som ökar deras interna renderingsupplösning. För att använda det senare, kommer du sannolikt vilja välja Inbyggd.\n\nDet här alternativet kan ändras medan ett spel körs genom att klicka på \"Tillämpa\" nedan. du kan helt enkelt flytta inställningsfönstret åt sidan och experimentera tills du hittar ditt föredragna utseende för ett spel.\n\nTänk på att 4x är overkill för praktiskt taget alla maskiner.",
"th_TH": "คูณความละเอียดการเรนเดอร์ของเกม\n\nเกมบางเกมอาจไม่สามารถใช้งานได้และดูเป็นพิกเซลแม้ว่าความละเอียดจะเพิ่มขึ้นก็ตาม สำหรับเกมเหล่านั้น คุณอาจต้องค้นหาม็อดที่ลบรอยหยักของภาพหรือเพิ่มความละเอียดในการเรนเดอร์ภายใน หากต้องการใช้อย่างหลัง คุณอาจต้องเลือก Native\n\nตัวเลือกนี้สามารถเปลี่ยนแปลงได้ในขณะที่เกมกำลังทำงานอยู่โดยคลิก \"นำมาใช้\" ด้านล่าง คุณสามารถย้ายหน้าต่างการตั้งค่าไปด้านข้างและทดลองจนกว่าคุณจะพบรูปลักษณ์ที่คุณต้องการสำหรับเกม\n\nโปรดทราบว่า 4x นั้นเกินความจำเป็นสำหรับการตั้งค่าแทบทุกประเภท",
"tr_TR": "",
@@ -16904,7 +16854,7 @@
"he_IL": "שיפור רזולוציית נקודה צפה, כגון 1.5. הוא שיפור לא אינטגרלי הנוטה לגרום יותר בעיות או להקריס.",
"it_IT": "Scala della risoluzione in virgola mobile, come 1,5. I valori non interi hanno maggiori probabilità di causare problemi o arresti anomali.",
"ja_JP": "1.5 のような整数でない倍率を指定すると,問題が発生したりクラッシュしたりする場合があります.",
- "ko_KR": "부동 소수점 해상도 스케일(예: 1.5)입니다. 적분이 아닌 스케일은 문제나 충돌을 일으킬 가능성이 높습니다.",
+ "ko_KR": "부동 소수점 해상도 스케일(예 : 1.5)입니다. 적분이 아닌 스케일은 문제나 충돌을 일으킬 가능성이 높습니다.",
"no_NO": "Det er mer sannsynlig at flytende punktoppløsning skalaer som 1.5. Ikke-integrerte skalaer forårsaker problemer eller krasj.",
"pl_PL": "Skala rozdzielczości zmiennoprzecinkowej, np. 1,5. Skale niecałkowite częściej powodują problemy lub awarie.",
"pt_BR": "Escala de resolução de ponto flutuante, como 1.5. Valores não inteiros tem probabilidade maior de causar problemas ou quebras.",
@@ -16933,7 +16883,7 @@
"no_NO": "Nivå av Anisotropisk filtrering. Sett til Auto for å bruke verdien som kreves av spillet.",
"pl_PL": "",
"pt_BR": "Nível de Filtragem Anisotrópica. Defina como Automático para usar o valor solicitado pelo jogo.",
- "ru_RU": "Уровень анизотропной фильтрации. \n\nУстановите значение Автоматически, чтобы использовать значение по умолчанию игры.",
+ "ru_RU": "Уровень анизотропной фильтрации. \n\nУстановите значение Автоматическая, чтобы использовать значение запрашиваемое игрой.",
"sv_SE": "Nivå av anisotropisk filtrering. Ställ in till Automatiskt för att använda det värde som begärts av spelet.",
"th_TH": "ระดับของ Anisotropic ตั้งค่าเป็นอัตโนมัติเพื่อใช้ค่าพื้นฐานของเกม",
"tr_TR": "",
@@ -16975,7 +16925,7 @@
"el_GR": "Ενεργοποιεί ή απενεργοποιεί την καταγραφή σε ένα αρχείο στο δίσκο",
"en_US": "Saves console logging to a log file on disk. Does not affect performance.",
"es_ES": "Guarda los registros de la consola en archivos en disco. No afectan al rendimiento.",
- "fr_FR": "Enregistre les journaux de la console dans un fichier sur le disque. N’affecte pas les performances.",
+ "fr_FR": "Enregistre les journaux de la console dans un fichier sur le disque. N’affecte pas la performance.",
"he_IL": "שומר את רישומי שורת הפקודות לזיכרון, לא משפיע על ביצועי היישום.",
"it_IT": "Salva il log della console in un file su disco. Non influisce sulle prestazioni.",
"ja_JP": "コンソール出力されるログをディスク上のログファイルにセーブします. パフォーマンスには影響を与えません.",
@@ -17000,7 +16950,7 @@
"el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων καταγραφής ατελειών",
"en_US": "Prints stub log messages in the console. Does not affect performance.",
"es_ES": "Escribe mensajes de Stub en la consola. No afectan al rendimiento.",
- "fr_FR": "Affiche dans la console les journaux stub. N’affecte pas les performances.",
+ "fr_FR": "Affiche dans la console les journaux stub. N’affecte pas la performance.",
"he_IL": "מדפיס רישומים כושלים לשורת הפקודות. לא משפיע על ביצועי היישום.",
"it_IT": "Stampa i messaggi di log relativi alle stub nella console. Non influisce sulle prestazioni.",
"ja_JP": "stub ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
@@ -17025,7 +16975,7 @@
"el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής πληροφοριών",
"en_US": "Prints info log messages in the console. Does not affect performance.",
"es_ES": "Escribe mensajes de Info en la consola. No afectan al rendimiento.",
- "fr_FR": "Affiche dans la console les journaux info. N’affecte pas les performances.",
+ "fr_FR": "Affiche dans la console les journaux info. N’affecte pas la performance.",
"he_IL": "מדפיק רישומי מידע לשורת הפקודות. לא משפיע על ביצועי היישום.",
"it_IT": "Stampa i messaggi di log informativi nella console. Non influisce sulle prestazioni.",
"ja_JP": "info ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
@@ -17050,7 +17000,7 @@
"el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων καταγραφής προειδοποιήσεων",
"en_US": "Prints warning log messages in the console. Does not affect performance.",
"es_ES": "Escribe mensajes de Advertencia en la consola. No afectan al rendimiento.",
- "fr_FR": "Affiche dans la console les journaux d’avertissement. N’affecte pas les performances.",
+ "fr_FR": "Affiche dans la console les journaux d’avertissement. N’affecte pas la performance.",
"he_IL": "מדפיק רישומי הערות לשורת הפקודות. לא משפיע על ביצועי היישום.",
"it_IT": "Stampa i messaggi di log relativi agli avvisi nella console. Non influisce sulle prestazioni.",
"ja_JP": "warning ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
@@ -17075,7 +17025,7 @@
"el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής σφαλμάτων",
"en_US": "Prints error log messages in the console. Does not affect performance.",
"es_ES": "Escribe mensajes de Error en la consola. No afectan al rendimiento.",
- "fr_FR": "Affiche dans la console les journaux d’erreur. N’affecte pas les performances.",
+ "fr_FR": "Affiche dans la console les journaux d’erreur. N’affecte pas la performance.",
"he_IL": "מדפיס רישומי שגיאות לשורת הפקודות. לא משפיע על ביצועי היישום.",
"it_IT": "Stampa i messaggi di log relativi agli errori nella console. Non influisce sulle prestazioni.",
"ja_JP": "error ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
@@ -17100,7 +17050,7 @@
"el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής ιχνών",
"en_US": "Prints trace log messages in the console. Does not affect performance.",
"es_ES": "Escribe mensajes de Rastro en la consola. No afectan al rendimiento.",
- "fr_FR": "Affiche dans la console les journaux de trace. N’affecte pas les performances.",
+ "fr_FR": "Affiche dans la console les journaux de trace. N’affecte pas la performance.",
"he_IL": "מדפיק רישומי זיכרון לשורת הפקודות. לא משפיע על ביצועי היישום.",
"it_IT": "Stampa i messaggi di log relativi al trace nella console. Non influisce sulle prestazioni.",
"ja_JP": "trace ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
@@ -17125,7 +17075,7 @@
"el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων καταγραφής επισκεπτών",
"en_US": "Prints guest log messages in the console. Does not affect performance.",
"es_ES": "Escribe mensajes de Guest en la consola. No afectan al rendimiento.",
- "fr_FR": "Affiche dans la console les journaux du système invité. N’affecte pas les performances.",
+ "fr_FR": "Affiche dans la console les journaux du système invité. N’affecte pas la performance.",
"he_IL": "מדפיס רישומי אורח לשורת הפקודות. לא משפיע על ביצועי היישום.",
"it_IT": "Stampa i messaggi di log del guest nella console. Non influisce sulle prestazioni.",
"ja_JP": "guest ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
@@ -17200,11 +17150,11 @@
"el_GR": "Χρησιμοποιήστε με προσοχή",
"en_US": "Use with care",
"es_ES": "Usar con cuidado",
- "fr_FR": "À utiliser avec précaution",
+ "fr_FR": "À Utiliser avec Précaution",
"he_IL": "השתמש בזהירות",
"it_IT": "Usa con cautela",
"ja_JP": "使用上の注意",
- "ko_KR": "주의해서 사용",
+ "ko_KR": "사용상 주의 요함",
"no_NO": "Bruk med forsiktighet",
"pl_PL": "Używaj ostrożnie",
"pt_BR": "Use com cuidado",
@@ -17225,7 +17175,7 @@
"el_GR": "",
"en_US": "Prints Avalonia (UI) log messages in the console.",
"es_ES": "",
- "fr_FR": "Affiche les journaux Avalonia (UI) dans la console.",
+ "fr_FR": "Affiche les journaux Avalonia (Interface Utilisateur) dans la console.",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -17235,7 +17185,7 @@
"pt_BR": "Imprime mensagens de log do Avalonia (UI) no console.",
"ru_RU": "Выводит сообщения журнала Avalonia (интерфейс) в консоли.",
"sv_SE": "Skriver ut loggmeddelanden från Avalonia (användargränssnittet) i konsollen.",
- "th_TH": "",
+ "th_TH": "แสดงข้อความบันทึก (log) ของ Avalonia (UI) ในคอนโซล",
"tr_TR": "",
"uk_UA": "Виводити повідомлення журналу Avalonia (UI) в консоль",
"zh_CN": "在控制台显示 Avalonia (UI) 的日志信息",
@@ -17275,7 +17225,7 @@
"el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής εντοπισμού σφαλμάτων",
"en_US": "Prints debug log messages in the console.\n\nOnly use this if specifically instructed by a staff member, as it will make logs difficult to read and worsen emulator performance.",
"es_ES": "Escribe mensajes de debug en la consola\n\nActiva esto solo si un miembro del equipo te lo pide expresamente, pues hará que el registro sea difícil de leer y empeorará el rendimiento del emulador.",
- "fr_FR": "Affiche dans la console les journaux de débogage.\n\nN’utilisez cette option que si un membre du personnel vous l’a expressément demandé, car cela rendra les journaux difficiles à lire et dégradera les performances de l’émulateur.",
+ "fr_FR": "Affiche dans la console les journaux de débogage.\n\nN’utilisez cette option que si un membre du personnel vous l’a expressément demandé, car cela rendra les journaux difficiles à lire et dégradera la performance de l’émulateur.",
"he_IL": "מדפיס הודעות יומן ניפוי באגים בשורת הפקודות.",
"it_IT": "Stampa i messaggi di log per il debug nella console.\n\nUsa questa opzione solo se specificatamente richiesto da un membro del team, dal momento che rende i log difficili da leggere e riduce le prestazioni dell'emulatore.",
"ja_JP": "デバッグログメッセージをコンソールに出力します.\n\nログが読みづらくなり,エミュレータのパフォーマンスが低下するため,開発者から特別な指示がある場合のみ使用してください.",
@@ -17292,206 +17242,6 @@
"zh_TW": "在控制台中輸出偵錯日誌訊息。\n\n只有在人員特別指示的情況下才能使用,因為這會導致日誌難以閱讀,並降低模擬器效能。"
}
},
- {
- "ID": "LoadApplicationFileTooltip",
- "Translations": {
- "ar_SA": "افتح مستكشف الملفات لاختيار ملف متوافق مع سويتش لتحميله",
- "de_DE": "Öffnet die Dateiauswahl um Datei zu laden, welche mit der Switch kompatibel ist",
- "el_GR": "Ανοίξτε έναν επιλογέα αρχείων για να επιλέξετε ένα αρχείο συμβατό με το Switch για φόρτωση",
- "en_US": "Open a file explorer to choose a Switch compatible file to load",
- "es_ES": "Abre el explorador de archivos para elegir un archivo compatible con Switch para cargar",
- "fr_FR": "Ouvre un explorateur de fichiers pour choisir un fichier compatible Switch à charger.",
- "he_IL": "פתח סייר קבצים כדי לבחור קובץ תואם סוויץ' לטעינה",
- "it_IT": "Apri un selettore file per scegliere un file compatibile con Switch da caricare",
- "ja_JP": "ロードする Switch 互換のファイルを選択するためファイルエクスプローラを開きます",
- "ko_KR": "파일 탐색기를 열어 불러올 Switch 호환 파일을 선택",
- "no_NO": "Åpne filutforsker for å velge en Switch kompatibel fil å laste",
- "pl_PL": "Otwórz eksplorator plików, aby wybrać plik kompatybilny z Switch do wczytania",
- "pt_BR": "Abre um explorador de arquivos para escolher um arquivo compatível com o Switch para carregar",
- "ru_RU": "Открывает файловый менеджер для выбора файла, совместимого с Nintendo Switch.",
- "sv_SE": "Öppna en filutforskare för att välja en Switch-kompatibel fil att läsa in",
- "th_TH": "เปิดตัวสำรวจไฟล์เพื่อเลือกไฟล์ที่เข้ากันได้กับ Switch ที่จะโหลด",
- "tr_TR": "Switch ile uyumlu bir dosya yüklemek için dosya tarayıcısını açar",
- "uk_UA": "Відкриває Файловий провідник, щоб обрати для завантаження сумісний зі Switch файл",
- "zh_CN": "选择 Switch 游戏文件并加载",
- "zh_TW": "開啟檔案總管,選擇與 Switch 相容的檔案來載入"
- }
- },
- {
- "ID": "LoadApplicationFolderTooltip",
- "Translations": {
- "ar_SA": "افتح مستكشف الملفات لاختيار تطبيق متوافق مع سويتش للتحميل",
- "de_DE": "Öffnet die Dateiauswahl um ein Spiel zu laden, welches mit der Switch kompatibel ist",
- "el_GR": "Ανοίξτε έναν επιλογέα αρχείων για να επιλέξετε μία μη συσκευασμένη εφαρμογή, συμβατή με το Switch για φόρτωση",
- "en_US": "Open a file explorer to choose a Switch compatible, unpacked application to load",
- "es_ES": "Abre el explorador de archivos para elegir un archivo desempaquetado y compatible con Switch para cargar",
- "fr_FR": "Ouvre un explorateur de fichiers pour choisir une application dépaquetée compatible Switch à charger.",
- "he_IL": "פתח סייר קבצים כדי לבחור יישום תואם סוויץ', לא ארוז לטעינה.",
- "it_IT": "Apri un selettore file per scegliere un'applicazione estratta compatibile con Switch da caricare",
- "ja_JP": "ロードする Switch 互換の展開済みアプリケーションを選択するためファイルエクスプローラを開きます",
- "ko_KR": "Switch와 호환되는 압축 해제된 앱을 선택하여 불러오려면 파일 탐색기를 엽니다.",
- "no_NO": "Åpne en filutforsker for å velge en Switch kompatibel, upakket applikasjon for å laste",
- "pl_PL": "Otwórz eksplorator plików, aby wybrać zgodną z Switch, rozpakowaną aplikację do załadowania",
- "pt_BR": "Abre um explorador de arquivos para escolher um aplicativo descompactado compatível com o Switch para carregar",
- "ru_RU": "Открывает файловый менеджер для выбора распакованного приложения, совместимого с Nintendo Switch.",
- "sv_SE": "Öppna en filutforskare för att välja en Switch-kompatibel, uppackad applikation att läsa in",
- "th_TH": "เปิดตัวสำรวจไฟล์เพื่อเลือกไฟล์ที่เข้ากันได้กับ Switch ที่จะโหลด",
- "tr_TR": "Switch ile uyumlu ayrıştırılmamış bir uygulama yüklemek için dosya tarayıcısını açar",
- "uk_UA": "Відкриває Файловий провідник, щоб обрати сумісну зі Switch розпаковану програму для завантаження",
- "zh_CN": "选择解包后的 Switch 游戏目录并加载",
- "zh_TW": "開啟檔案總管,選擇與 Switch 相容且未封裝的應用程式來載入"
- }
- },
- {
- "ID": "LoadDlcFromFolderTooltip",
- "Translations": {
- "ar_SA": "",
- "de_DE": "",
- "el_GR": "",
- "en_US": "Open a file explorer to choose one or more folders to bulk load DLC from",
- "es_ES": "Abrir un explorador de archivos para seleccionar una o más carpetas para cargar DLC de forma masiva",
- "fr_FR": "Ouvre un explorateur de fichiers pour choisir un ou plusieurs dossiers afin de charger en masse des DLC",
- "he_IL": "",
- "it_IT": "Apri un selettore file per scegliere una o più cartelle dalle quali caricare DLC in blocco",
- "ja_JP": "",
- "ko_KR": "파일 탐색기를 열어 DLC를 일괄 불러오기할 폴더를 하나 이상 선택",
- "no_NO": "Åpne en filutforsker for å velge en eller flere mapper å laste inn DLC fra",
- "pl_PL": "",
- "pt_BR": "Abre um explorador de arquivos para escolher uma ou mais pastas para carregar DLC em massa",
- "ru_RU": "Открывает проводник, для выбора одной или нескольких папок для массовой загрузки DLC",
- "sv_SE": "Öppna en filutforskare för att välja en eller flera mappar att läsa in alla DLC från",
- "th_TH": "เปิดตัวสำรวจไฟล์เพื่อเลือกหนึ่งโฟลเดอร์ขึ้นไปเพื่อโหลด DLC จำนวนมาก",
- "tr_TR": "",
- "uk_UA": "Відкриває Файловий провідник для обрання однієї або декількох тек для масового завантаження DLC",
- "zh_CN": "打开文件资源管理器以选择一个或多个文件夹来批量加载 DLC。",
- "zh_TW": "開啟檔案總管,選擇一個或多個資料夾來大量載入 DLC"
- }
- },
- {
- "ID": "LoadTitleUpdatesFromFolderTooltip",
- "Translations": {
- "ar_SA": "",
- "de_DE": "",
- "el_GR": "",
- "en_US": "Open a file explorer to choose one or more folders to bulk load title updates from",
- "es_ES": "Abrir un explorador de archivos para seleccionar una o más carpetas para cargar actualizaciones de título de forma masiva",
- "fr_FR": "Ouvre un explorateur de fichiers pour choisir un ou plusieurs dossiers afin de charger en masse des mises à jour de titre.",
- "he_IL": "",
- "it_IT": "Apri un selettore file per scegliere una o più cartelle dalle quali caricare aggiornamenti in blocco",
- "ja_JP": "",
- "ko_KR": "파일 탐색기를 열어 하나 이상의 폴더를 선택하여 대량으로 타이틀 업데이트 불러오기",
- "no_NO": "Åpne en filutforsker for å velge en eller flere mapper som du vil laste inn titteloppdateringer fra",
- "pl_PL": "",
- "pt_BR": "Abre um explorador de arquivos para escolher uma ou mais pastas para carregar em massa as atualizações de títulos",
- "ru_RU": "Открывает проводник, чтобы выбрать одну или несколько папок для массовой загрузки обновлений приложений",
- "sv_SE": "Öppna en filutforskare för att välja en eller flera mappar att läsa in alla titeluppdateringar från",
- "th_TH": "เปิดตัวสำรวจไฟล์เพื่อเลือกหนึ่งโฟลเดอร์ขึ้นไปเพื่อโหลดไฟล์อัปเดตจำนวนมาก",
- "tr_TR": "",
- "uk_UA": "Відкриває Файловий Провідник для обрання однієї або декількох тек для масового завантаження оновлень",
- "zh_CN": "打开文件资源管理器以选择一个或多个文件夹来批量加载游戏更新。",
- "zh_TW": "開啟檔案總管,選擇一個或多個資料夾來大量載入遊戲更新"
- }
- },
- {
- "ID": "ExitTooltip",
- "Translations": {
- "ar_SA": "الخروج من ريوجينكس",
- "de_DE": "Beendet Ryujinx",
- "el_GR": "Έξοδος από το Ryujinx",
- "en_US": "Exit Ryujinx",
- "es_ES": "Cierra Ryujinx",
- "fr_FR": "Quitter Ryujinx",
- "he_IL": "צא מריוג'ינקס",
- "it_IT": "Esci da Ryujinx",
- "ja_JP": "Ryujinx を終了します",
- "ko_KR": "Ryujinx 종료",
- "no_NO": "Avslutt Ryujinx",
- "pl_PL": "Wyjdź z Ryujinx",
- "pt_BR": "Sair do Ryujinx",
- "ru_RU": "Выйти из Ryujinx",
- "sv_SE": "Avsluta Ryujinx",
- "th_TH": "ออกจากโปรแกรม Ryujinx",
- "tr_TR": "Ryujinx'ten çıkış yapmayı sağlar",
- "uk_UA": "Закриває Ryujinx",
- "zh_CN": "退出 Ryujinx 模拟器",
- "zh_TW": "結束 Ryujinx"
- }
- },
- {
- "ID": "StopEmulationTooltip",
- "Translations": {
- "ar_SA": "إيقاف محاكاة اللعبة الحالية والعودة إلى اختيار اللعبة",
- "de_DE": "Beendet die Emulation des derzeitigen Spiels und kehrt zu der Spielauswahl zurück",
- "el_GR": "Σταματήστε την εξομοίωση του τρέχοντος παιχνιδιού και επιστρέψτε στην επιλογή παιχνιδιού",
- "en_US": "Stop emulation of the current game and return to game selection",
- "es_ES": "Detiene la emulación del juego actual y regresa a la selección de juegos",
- "fr_FR": "Arrêter l'émulation du jeu en cours et revenir à la sélection des jeux",
- "he_IL": "הפסק את הדמייה של המשחק הנוכחי וחזור למסך בחירת המשחק",
- "it_IT": "Ferma l'emulazione del gioco attuale e torna alla selezione dei giochi",
- "ja_JP": "ゲームのエミュレーションを中止してゲーム選択画面に戻ります",
- "ko_KR": "현재 게임의 에뮬레이션을 중지하고 게임 선택으로 돌아가기",
- "no_NO": "Stopp emuleringen av dette spillet og gå tilbake til spill valg",
- "pl_PL": "Zatrzymaj emulację bieżącej gry i wróć do wyboru gier",
- "pt_BR": "Parar emulação do jogo atual e voltar a seleção de jogos",
- "ru_RU": "Остановка эмуляции текущей игры с последующим возвратом к списку игр",
- "sv_SE": "Stoppa emulering av aktuellt spel och återgå till spelväljaren",
- "th_TH": "หยุดการจำลองของเกมที่เปิดอยู่ในปัจจุบันและกลับไปยังการเลือกเกม",
- "tr_TR": "Oynanmakta olan oyunun emülasyonunu durdurup oyun seçimine geri döndürür",
- "uk_UA": "Зупиняє емуляцію поточної гри та повертається до вибору гри",
- "zh_CN": "停止运行当前游戏,并回到主界面",
- "zh_TW": "停止模擬目前遊戲,返回遊戲選擇介面"
- }
- },
- {
- "ID": "CheckUpdatesTooltip",
- "Translations": {
- "ar_SA": "التحقق من وجود تحديثات لريوجينكس",
- "de_DE": "Sucht nach Updates für Ryujinx",
- "el_GR": "Ελέγξτε για ενημερώσεις του Ryujinx",
- "en_US": "Check for updates to Ryujinx",
- "es_ES": "Busca actualizaciones para Ryujinx",
- "fr_FR": "Vérifier les mises à jour de Ryujinx",
- "he_IL": "בדוק אם קיימים עדכונים לריוג'ינקס",
- "it_IT": "Controlla la presenza di aggiornamenti di Ryujinx",
- "ja_JP": "Ryujinx のアップデートを確認します",
- "ko_KR": "Ryujinx 업데이트 확인",
- "no_NO": "Se etter oppdateringer til Ryujinx",
- "pl_PL": "Sprawdź aktualizacje Ryujinx",
- "pt_BR": "Verificar por atualizações para o Ryujinx",
- "ru_RU": "Проверяет наличие обновлений Ryujinx",
- "sv_SE": "Leta efter uppdateringar för Ryujinx",
- "th_TH": "ตรวจสอบอัปเดตของ Ryujinx",
- "tr_TR": "Ryujinx güncellemelerini denetlemeyi sağlar",
- "uk_UA": "Перевіряє наявність оновлень для Ryujinx",
- "zh_CN": "检查 Ryujinx 新版本",
- "zh_TW": "檢查 Ryujinx 的更新"
- }
- },
- {
- "ID": "OpenAboutTooltip",
- "Translations": {
- "ar_SA": "فتح حول النافذة",
- "de_DE": "Öffnet das 'Über Ryujinx'-Fenster",
- "el_GR": "Ανοίξτε το Παράθυρο Σχετικά",
- "en_US": "Open About Window",
- "es_ES": "Abre la ventana \"Acerca de\"",
- "fr_FR": "Ouvrir la fenêtre À Propos",
- "he_IL": "פתח את חלון אודות היישום",
- "it_IT": "Apri la finestra delle informazioni",
- "ja_JP": "Ryujinx についてのウインドウを開きます",
- "ko_KR": "정보 창 열기",
- "no_NO": "Åpne Om Vindu",
- "pl_PL": "Otwórz Okno Informacje",
- "pt_BR": "Abrir Janela Sobre",
- "ru_RU": "Открывает окно «О программе»",
- "sv_SE": "Öppna Om-fönstret",
- "th_TH": "เปิดหน้าต่าง เกี่ยวกับ",
- "tr_TR": "Hakkında penceresini açar",
- "uk_UA": "Відкриває вікно «Про застосунок»",
- "zh_CN": "打开关于窗口",
- "zh_TW": "開啟關於視窗"
- }
- },
{
"ID": "GridSize",
"Translations": {
@@ -17500,7 +17250,7 @@
"el_GR": "Μέγεθος Πλέγματος",
"en_US": "Grid Size",
"es_ES": "Tamaño de cuadrícula",
- "fr_FR": "Taille de la grille",
+ "fr_FR": "Taille de la Grille",
"he_IL": "גודל רשת",
"it_IT": "Dimensione griglia",
"ja_JP": "グリッドサイズ",
@@ -17517,31 +17267,6 @@
"zh_TW": "網格尺寸"
}
},
- {
- "ID": "GridSizeTooltip",
- "Translations": {
- "ar_SA": "تغيير حجم عناصر الشبكة",
- "de_DE": "Ändert die Größe der Rasterelemente",
- "el_GR": "Αλλαγή μεγέθους στοιχείων πλέγματος",
- "en_US": "Change the size of grid items",
- "es_ES": "Cambia el tamaño de los objetos en la cuadrícula",
- "fr_FR": "Modifier la taille des éléments de la grille",
- "he_IL": "שנה את גודל המוצרים על הרשת.",
- "it_IT": "Cambia la dimensione dei riquadri della griglia",
- "ja_JP": "グリッドサイズを変更します",
- "ko_KR": "그리드 항목의 크기 변경",
- "no_NO": "Endre størrelsen på rutenettet elementer",
- "pl_PL": "Zmień rozmiar elementów siatki",
- "pt_BR": "Mudar tamanho dos items da grade",
- "ru_RU": "Меняет размер сетки элементов",
- "sv_SE": "Ändra objektstorleken för rutnätet",
- "th_TH": "เปลี่ยนขนาด ของตาราง",
- "tr_TR": "Grid ögelerinin boyutunu değiştirmeyi sağlar",
- "uk_UA": "Змінити розмір елементів сітки",
- "zh_CN": "调整网格项目的大小",
- "zh_TW": "調整網格的大小"
- }
- },
{
"ID": "SettingsTabSystemSystemLanguageBrazilianPortuguese",
"Translations": {
@@ -17575,7 +17300,7 @@
"el_GR": "Δείτε Όλους τους Συντελεστές",
"en_US": "See All Contributors",
"es_ES": "Ver todos los contribuidores",
- "fr_FR": "Voir tous les contributeurs",
+ "fr_FR": "Voir Tous les Contributeurs",
"he_IL": "צפה בכל התורמים",
"it_IT": "Mostra tutti i contributori",
"ja_JP": "すべての貢献者を確認",
@@ -17617,31 +17342,6 @@
"zh_TW": "音量:"
}
},
- {
- "ID": "AudioVolumeTooltip",
- "Translations": {
- "ar_SA": "تغيير مستوى الصوت",
- "de_DE": "Ändert die Lautstärke",
- "el_GR": "Αλλαγή Έντασης Ήχου",
- "en_US": "Change Audio Volume",
- "es_ES": "Ajusta el nivel de volumen",
- "fr_FR": "Modifier le volume audio",
- "he_IL": "שנה עוצמת קול",
- "it_IT": "Cambia volume audio",
- "ja_JP": "音量を変更します",
- "ko_KR": "음량 변경",
- "no_NO": "Endre lydenivå",
- "pl_PL": "Zmień Głośność Dźwięku",
- "pt_BR": "Mudar Volume do Áudio",
- "ru_RU": "Изменяет громкость звука",
- "sv_SE": "Ändra ljudvolym",
- "th_TH": "ปรับระดับเสียง",
- "tr_TR": "Ses seviyesini değiştirir",
- "uk_UA": "Регулювання гучності",
- "zh_CN": "调节音量",
- "zh_TW": "調節音量"
- }
- },
{
"ID": "SettingsTabSystemEnableInternetAccess",
"Translations": {
@@ -17683,7 +17383,7 @@
"no_NO": "Tillater emulert applikasjon å koble til Internett.\n\nSpill med en LAN-modus kan koble til hverandre når dette er aktivert og systemene er koblet til det samme tilgangspunktet. Dette inkluderer ekte konsoller også.\n\ntillater IKKE tilkobling til Nintendo servere. Kan forårsake krasjing i enkelte spill som prøver å koble til Internett.\n\nLa stå AV hvis du er usikker.",
"pl_PL": "Pozwala emulowanej aplikacji na łączenie się z Internetem.\n\nGry w trybie LAN mogą łączyć się ze sobą, gdy ta opcja jest włączona, a systemy są połączone z tym samym punktem dostępu. Dotyczy to również prawdziwych konsol.\n\nNie pozwala na łączenie się z serwerami Nintendo. Może powodować awarie niektórych gier, które próbują połączyć się z Internetem.\n\nPozostaw WYŁĄCZONE, jeśli nie masz pewności.",
"pt_BR": "Permite que o aplicativo emulado se conecte à Internet.\n\nJogos com modo LAN podem se conectar uns aos outros quando isso está habilitado e os sistemas estão conectados ao mesmo ponto de acesso. Isso inclui consoles reais também.\n\nNÃO permite a conexão com servidores Nintendo. Pode causar travamentos em certos jogos que tentam se conectar à Internet.\n\nDeixe DESLIGADO se não tiver certeza.",
- "ru_RU": "Позволяет эмулированному приложению подключаться к Интернету.\n\nПри включении этой функции игры с возможностью сетевой игры могут подключаться друг к другу, если все эмуляторы (или реальные консоли) подключены к одной и той же точке доступа.\n\nНЕ разрешает подключение к серверам Nintendo. Может вызвать сбой в некоторых играх, которые пытаются подключиться к Интернету.\n\nРекомендутеся оставить выключенным.",
+ "ru_RU": "Разрешает эмулируемому приложению подключаться к Интернету.\n\nКогда эта опция включена и устройства подключены к одной точке доступа, игры с режимом LAN могут подключаться друг к другу. Это также касается реальных консолей.\n\nНЕ позволяет подключаться к серверам Nintendo. Может вызвать сбои в некоторых играх, которые пытаются подключиться к Интернету.\n\nРекомендутеся оставить ВЫКЛЮЧЕННЫМ.",
"sv_SE": "Tillåter det emulerade programmet att ansluta till internet.\n\nSpel med ett LAN-läge kan ansluta till varandra när detta är aktiverat och systemen är anslutna till samma åtkomstpunkt. Detta inkluderar riktiga konsoler också.\n\nTillåter INTE anslutning till Nintendo-servrar. Kan orsaka kraschar i vissa spel som försöker ansluta till internet.\n\nLämna AV om du är osäker.",
"th_TH": "อนุญาตให้แอปพลิเคชันจำลองเชื่อมต่ออินเทอร์เน็ต\n\nเกมที่มีโหมด LAN สามารถเชื่อมต่อระหว่างกันได้เมื่อเปิดใช้งานและระบบเชื่อมต่อกับจุดเชื่อมต่อเดียวกัน รวมถึงคอนโซลจริงด้วย\n\nไม่อนุญาตให้มีการเชื่อมต่อกับเซิร์ฟเวอร์ Nintendo อาจทำให้เกิดการหยุดทำงานในบางเกมที่พยายามเชื่อมต่ออินเทอร์เน็ต\n\nปล่อยให้ปิดหากคุณไม่แน่ใจ",
"tr_TR": "Emüle edilen uygulamanın internete bağlanmasını sağlar.\n\nLAN modu bulunan oyunlar bu seçenek ile birbirine bağlanabilir ve sistemler aynı access point'e bağlanır. Bu gerçek konsolları da kapsar.\n\nNintendo sunucularına bağlanmayı sağlaMAZ. Internete bağlanmaya çalışan baz oyunların çökmesine sebep olabilr.\n\nEmin değilseniz devre dışı bırakın.",
@@ -17692,31 +17392,6 @@
"zh_TW": "允許模擬應用程式連線網際網路。\n\n當啟用此功能且系統連線到同一接入點時,具有區域網路模式的遊戲可相互連線。這也包括真正的遊戲機。\n\n不允許連接 Nintendo 伺服器。可能會導致某些嘗試連線網際網路的遊戲崩潰。\n\n如果不確定,請保持關閉狀態。"
}
},
- {
- "ID": "GameListContextMenuManageCheatToolTip",
- "Translations": {
- "ar_SA": "إدارة الغش",
- "de_DE": "Öffnet den Cheat-Manager",
- "el_GR": "Διαχείριση Κόλπων",
- "en_US": "Manage Cheats",
- "es_ES": "Activa o desactiva los cheats",
- "fr_FR": "Gérer les cheats",
- "he_IL": "נהל צ'יטים",
- "it_IT": "Gestisci trucchi",
- "ja_JP": "チートを管理します",
- "ko_KR": "치트 관리",
- "no_NO": "Administrer juksemoduser",
- "pl_PL": "Zarządzaj Kodami",
- "pt_BR": "Gerenciar Trapaças",
- "ru_RU": "Открывает окно управления читами",
- "sv_SE": "Hantera fusk",
- "th_TH": "ฟังก์ชั่นจัดการสูตรโกง",
- "tr_TR": "Hileleri yönetmeyi sağlar",
- "uk_UA": "Відкриває меню керування чит-кодами (cheats)",
- "zh_CN": "管理当前游戏的金手指",
- "zh_TW": "管理密技"
- }
- },
{
"ID": "GameListContextMenuManageCheat",
"Translations": {
@@ -17725,7 +17400,7 @@
"el_GR": "Διαχείριση Κόλπων",
"en_US": "Manage Cheats",
"es_ES": "Administrar cheats",
- "fr_FR": "Gérer les cheats",
+ "fr_FR": "Gérer les Cheats",
"he_IL": "נהל צ'יטים",
"it_IT": "Gestisci trucchi",
"ja_JP": "チートを管理",
@@ -17742,31 +17417,6 @@
"zh_TW": "管理密技"
}
},
- {
- "ID": "GameListContextMenuManageModToolTip",
- "Translations": {
- "ar_SA": "إدارة التعديلات",
- "de_DE": "Mods verwalten",
- "el_GR": "",
- "en_US": "Manage Mods",
- "es_ES": "Gestionar Mods",
- "fr_FR": "Gérer les mods",
- "he_IL": "נהל מודים",
- "it_IT": "Gestisci mod",
- "ja_JP": "Modを管理します",
- "ko_KR": "모드 관리",
- "no_NO": "Administrer modifikasjoner",
- "pl_PL": "Zarządzaj modyfikacjami",
- "pt_BR": "Gerenciar Mods",
- "ru_RU": "Открывает окно управления модами",
- "sv_SE": "Hantera moddar",
- "th_TH": "ฟังก์ชั่นจัดการม็อด",
- "tr_TR": "Modları Yönet",
- "uk_UA": "Відкриває меню керування модифікаціями (mods)",
- "zh_CN": "管理当前游戏的 MOD",
- "zh_TW": "管理模組"
- }
- },
{
"ID": "GameListContextMenuManageMod",
"Translations": {
@@ -17775,7 +17425,7 @@
"el_GR": "",
"en_US": "Manage Mods",
"es_ES": "Gestionar Mods",
- "fr_FR": "Gérer les mods",
+ "fr_FR": "Gérer les Mods",
"he_IL": "נהל מודים",
"it_IT": "Gestisci mod",
"ja_JP": "",
@@ -17825,7 +17475,7 @@
"el_GR": "{0} - Διακοπή εξομοίωσης",
"en_US": "{0} - Stop Emulation",
"es_ES": "{0} - Detener emulación",
- "fr_FR": "{0} - Arrêt de l'émulation",
+ "fr_FR": "{0} - Arrêt de l'Émulation",
"he_IL": "{0} - עצור אמולציה",
"it_IT": "{0} - Ferma emulazione",
"ja_JP": "{0} - エミュレーションを中止",
@@ -17889,7 +17539,7 @@
"tr_TR": "İşlemci",
"uk_UA": "Процесор",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -17900,7 +17550,7 @@
"el_GR": "Ήχος",
"en_US": "Audio",
"es_ES": "Sonido",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "שמע",
"it_IT": "",
"ja_JP": "音声",
@@ -17950,7 +17600,7 @@
"el_GR": "Σύνδεση δικτύου",
"en_US": "Network Connection",
"es_ES": "Conexión de red",
- "fr_FR": "Connexion réseau",
+ "fr_FR": "Connexion Réseau",
"he_IL": "חיבור רשת",
"it_IT": "Connessione di rete",
"ja_JP": "ネットワーク接続",
@@ -18025,7 +17675,7 @@
"el_GR": "Ο Διαχειριστής Ενημερώσεων Είναι Απενεργοποιημένος!",
"en_US": "Updater Disabled!",
"es_ES": "¡Actualizador deshabilitado!",
- "fr_FR": "Mises à jour désactivées !",
+ "fr_FR": "Mises à jour Désactivées !",
"he_IL": "מעדכן מושבת!",
"it_IT": "Updater disabilitato!",
"ja_JP": "アップデータは無効です!",
@@ -18033,7 +17683,7 @@
"no_NO": "Oppdatering Deaktivert!",
"pl_PL": "Aktualizator Wyłączony!",
"pt_BR": "Atualizador Desabilitado!",
- "ru_RU": "Средство обновления отключено",
+ "ru_RU": "Программа обновлений отключена!",
"sv_SE": "Uppdateringar inaktiverade!",
"th_TH": "ปิดใช้งานการอัปเดตแล้ว!",
"tr_TR": "Güncelleyici Devre Dışı!",
@@ -18050,7 +17700,7 @@
"el_GR": "",
"en_US": "{0} FPS ({1}ms)",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -18058,9 +17708,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": null,
"sv_SE": "{0} bilder/s ({1}ms)",
- "th_TH": "",
+ "th_TH": "{0} FPS ({1}มิลลิวินาที)",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "{0} FPS ({1}毫秒)",
@@ -18075,7 +17725,7 @@
"el_GR": "",
"en_US": "{0} FPS ({1}ms), Turbo ({2}%)",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -18083,9 +17733,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "{0} FPS ({1}ms), Турбо ({2}%)",
"sv_SE": "{0} bilder/s ({1}ms), Turbo ({2}%)",
- "th_TH": "",
+ "th_TH": "{0} FPS ({1} มิลลิวินาที), โหมดเทอร์โบ ({2}%)",
"tr_TR": "",
"uk_UA": "{0} FPS ({1}ms), Турбо ({2}%)",
"zh_CN": "{0} FPS ({1}ms), 涡轮 ({2}%)",
@@ -18100,7 +17750,7 @@
"el_GR": "",
"en_US": "Update Available!",
"es_ES": "",
- "fr_FR": "Mise à jour disponible !",
+ "fr_FR": "Mise à jour Disponible !",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -18110,7 +17760,7 @@
"pt_BR": "Atualização Disponível!",
"ru_RU": "Доступно обновление!",
"sv_SE": "Uppdatering finns tillgänglig!",
- "th_TH": "",
+ "th_TH": "อัปเดตใหม่พร้อมใช้งาน!",
"tr_TR": "",
"uk_UA": "Доступне оновлення!",
"zh_CN": "有可用的更新!",
@@ -18150,7 +17800,7 @@
"el_GR": "Μέγεθος Εικονιδίου",
"en_US": "Icon Size",
"es_ES": "Tamaño de iconos",
- "fr_FR": "Taille d'icône",
+ "fr_FR": "Taille d'Icône",
"he_IL": "גודל הסמל",
"it_IT": "Dimensioni icone",
"ja_JP": "アイコンサイズ",
@@ -18167,31 +17817,6 @@
"zh_TW": "圖示大小"
}
},
- {
- "ID": "IconSizeTooltip",
- "Translations": {
- "ar_SA": "تغيير حجم أيقونات اللعبة",
- "de_DE": "Ändert die Größe der Spiel-Cover",
- "el_GR": "Αλλάξτε μέγεθος εικονιδίων των παιχνιδιών",
- "en_US": "Change the size of game icons",
- "es_ES": "Cambia el tamaño de los iconos de juegos",
- "fr_FR": "Changer la taille des icônes de jeu",
- "he_IL": "שנה את גודל הסמלים של משחקים",
- "it_IT": "Cambia le dimensioni delle icone dei giochi",
- "ja_JP": "ゲームアイコンのサイズを変更します",
- "ko_KR": "게임 아이콘 크기 변경",
- "no_NO": "Endre størrelsen på spillikonene",
- "pl_PL": "Zmień rozmiar ikon gry",
- "pt_BR": "Muda o tamanho do ícone do jogo",
- "ru_RU": "Меняет размер обложек",
- "sv_SE": "Ändra storleken för spelikonerna",
- "th_TH": "เปลี่ยนขนาดของไอคอนเกม",
- "tr_TR": "Oyun ikonlarının boyutunu değiştirmeyi sağlar",
- "uk_UA": "Змінити розмір обкладинок (значків) ігор",
- "zh_CN": "更改游戏图标的显示尺寸",
- "zh_TW": "變更遊戲圖示的大小"
- }
- },
{
"ID": "MenuBarOptionsShowConsole",
"Translations": {
@@ -18200,7 +17825,7 @@
"el_GR": "Εμφάνιση Κονσόλας",
"en_US": "Show Console",
"es_ES": "Mostrar consola",
- "fr_FR": "Afficher la console",
+ "fr_FR": "Afficher la Console",
"he_IL": "הצג שורת פקודות",
"it_IT": "Mostra console",
"ja_JP": "コンソールを表示",
@@ -18483,7 +18108,7 @@
"no_NO": "Ryujinx kunne ikke finne en gyldig applikasjon på den gitte banen.",
"pl_PL": "Ryujinx nie mógł znaleźć prawidłowej aplikacji na podanej ścieżce.",
"pt_BR": "Ryujinx não conseguiu encontrar um aplicativo válido no caminho fornecido.",
- "ru_RU": "Ryujinx не удалось найти валидное приложение по указанному пути.",
+ "ru_RU": "Ryujinx не смог найти подходящее приложение по указанному пути.",
"sv_SE": "Ryujinx kunde inte hitta en giltig applikation i angiven sökväg.",
"th_TH": "Ryujinx ไม่พบแอปพลิเคชันที่ถูกต้องในที่เก็บไฟล์ที่กำหนด",
"tr_TR": "Ryujinx belirtilen yolda geçerli bir uygulama bulamadı.",
@@ -18533,7 +18158,7 @@
"no_NO": "En udefinert feil oppstod! Dette burde ikke skje, vennligst kontakt en utvikler!",
"pl_PL": "Wystąpił niezdefiniowany błąd! To nie powinno się zdarzyć, skontaktuj się z deweloperem!",
"pt_BR": "Um erro indefinido occoreu! Isso não deveria acontecer, por favor contate um desenvolvedor!",
- "ru_RU": "Произошла неизвестная ошибка. Этого не должно происходить, пожалуйста, свяжитесь с разработчиками.",
+ "ru_RU": "Произошла неизвестная ошибка. Этого не должно происходить, пожалуйста, свяжитесь с разработчиками!",
"sv_SE": "Ett odefinierat fel inträffade! Detta ska inte hända. Kontakta en utvecklare!",
"th_TH": "เกิดข้อผิดพลาดที่ไม่สามารถระบุได้! สิ่งนี้ไม่ควรเกิดขึ้น โปรดติดต่อผู้พัฒนา!",
"tr_TR": "Tanımlanmayan bir hata oluştu! Bu durum ile karşılaşılmamalıydı, lütfen bir geliştirici ile iletişime geçin!",
@@ -18550,7 +18175,7 @@
"el_GR": "Ανοίξτε τον Οδηγό Εγκατάστασης.",
"en_US": "Open the Setup Guide",
"es_ES": "Abrir la guía de instalación",
- "fr_FR": "Ouvrir le guide d'installation",
+ "fr_FR": "Ouvrir le Guide d'Installation",
"he_IL": "פתח מדריך התקנה",
"it_IT": "Apri la guida all'installazione",
"ja_JP": "セットアップガイドを開く",
@@ -18575,7 +18200,7 @@
"el_GR": "Καμία Eνημέρωση",
"en_US": "No Update",
"es_ES": "No actualizado",
- "fr_FR": "Aucune mise à jour",
+ "fr_FR": "Aucune Mise à Jour",
"he_IL": "אין עדכון",
"it_IT": "Nessun aggiornamento",
"ja_JP": "アップデートなし",
@@ -18600,7 +18225,7 @@
"el_GR": "",
"en_US": "Version {0}",
"es_ES": "Versión {0}",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "גרסה: {0}",
"it_IT": "Versione {0}",
"ja_JP": "バージョン {0}",
@@ -18633,9 +18258,9 @@
"no_NO": "Pakket: Versjon {0}",
"pl_PL": "",
"pt_BR": "Empacotado: Versão {0}",
- "ru_RU": "Баднл: Версия {0}",
+ "ru_RU": "В комплекте: Версия {0}",
"sv_SE": "Bundlad: Version {0}",
- "th_TH": "Bundled: เวอร์ชั่น {0}",
+ "th_TH": "บันเดิล: เวอร์ชัน {0}",
"tr_TR": "",
"uk_UA": "Комплектні: Версія {0}",
"zh_CN": "捆绑:版本 {0}",
@@ -18658,9 +18283,9 @@
"no_NO": "Pakket:",
"pl_PL": "",
"pt_BR": "Empacotado:",
- "ru_RU": "Бандл:",
+ "ru_RU": "В комплекте:",
"sv_SE": "Bundlad:",
- "th_TH": "",
+ "th_TH": "บันเดิล:",
"tr_TR": "",
"uk_UA": "Комплектні:",
"zh_CN": "捆绑:",
@@ -18685,7 +18310,7 @@
"pt_BR": "Parcial",
"ru_RU": "Частично",
"sv_SE": "Delvis",
- "th_TH": "",
+ "th_TH": "ยังไม่สมบูรณ์",
"tr_TR": "",
"uk_UA": "Часткові",
"zh_CN": "分区",
@@ -18700,7 +18325,7 @@
"el_GR": "",
"en_US": "Untrimmed",
"es_ES": "Sin recortar",
- "fr_FR": "Non réduit",
+ "fr_FR": "Non Réduit",
"he_IL": "",
"it_IT": "Dim. originale",
"ja_JP": "",
@@ -18710,7 +18335,7 @@
"pt_BR": "Não Reduzido",
"ru_RU": "Не обрезан",
"sv_SE": "Orörd",
- "th_TH": "",
+ "th_TH": "ยังไม่ได้ตัดแต่ง",
"tr_TR": "",
"uk_UA": "Необрізані",
"zh_CN": "没有瘦身的",
@@ -18735,7 +18360,7 @@
"pt_BR": "Reduzido",
"ru_RU": "Обрезан",
"sv_SE": "Optimerad",
- "th_TH": "",
+ "th_TH": "ตัดแต่งแล้ว",
"tr_TR": "",
"uk_UA": "Обрізані",
"zh_CN": "经过瘦身的",
@@ -18760,7 +18385,7 @@
"pt_BR": "Falhou",
"ru_RU": "(Ошибка)",
"sv_SE": "(misslyckades)",
- "th_TH": "",
+ "th_TH": "(ล้มเหลว)",
"tr_TR": "",
"uk_UA": "(Невдача)",
"zh_CN": "(失败)",
@@ -18775,17 +18400,17 @@
"el_GR": "",
"en_US": "Save {0:n0} Mb",
"es_ES": "Ahorra {0:n0} Mb",
- "fr_FR": "Économiser {0:n0} Mo",
+ "fr_FR": "Sauvegarde de {0:n0} Mo",
"he_IL": "",
"it_IT": "Risparmia {0:n0} MB",
"ja_JP": "",
- "ko_KR": "{0:n0} Mb 저장",
+ "ko_KR": "{0:n0}MB 저장",
"no_NO": "Spare {0:n0} Mb",
"pl_PL": "",
"pt_BR": "Salvar {0:n0} Mb",
- "ru_RU": "Сохранить {0:n0} Мб",
+ "ru_RU": "Освободить {0:n0} Мб",
"sv_SE": "Spara {0:n0} Mb",
- "th_TH": "",
+ "th_TH": "บันทึก {0:n0} เมกะไบต์",
"tr_TR": "",
"uk_UA": "Зберегти {0:n0} Мб",
"zh_CN": "能节约 {0:n0} Mb",
@@ -18800,17 +18425,17 @@
"el_GR": "",
"en_US": "Saved {0:n0} Mb",
"es_ES": "{0:n0} Mb ahorrado(s)",
- "fr_FR": "Économisé {0:n0} Mo",
+ "fr_FR": "Sauvegardé {0:n0} Mo",
"he_IL": "",
"it_IT": "Risparmiati {0:n0} MB",
"ja_JP": "",
- "ko_KR": "{0:n0}Mb 저장됨",
+ "ko_KR": "{0:n0}MB 저장됨",
"no_NO": "Spart {0:n0} Mb",
"pl_PL": "",
"pt_BR": "Salvo {0:n0} Mb",
- "ru_RU": "Сохранено {0:n0} Мб",
+ "ru_RU": "Освобождено {0:n0} Мб",
"sv_SE": "Sparade {0:n0} Mb",
- "th_TH": "",
+ "th_TH": "บันทึกแล้ว {0:n0} เมกะไบต์",
"tr_TR": "",
"uk_UA": "Збережено {0:n0} Мб",
"zh_CN": "节约了 {0:n0} Mb",
@@ -18825,7 +18450,7 @@
"el_GR": "{0} - Πληροφορίες",
"en_US": "{0} - Info",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "{0} - מידע",
"it_IT": "{0} - Informazioni",
"ja_JP": "{0} - 情報",
@@ -18850,7 +18475,7 @@
"el_GR": "{0} - Επιβεβαίωση",
"en_US": "{0} - Confirmation",
"es_ES": "{0} - Confirmación",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "{0} - אישור",
"it_IT": "{0} - Conferma",
"ja_JP": "{0} - 確認",
@@ -18875,7 +18500,7 @@
"el_GR": "Όλοι οι τύποι",
"en_US": "All types",
"es_ES": "Todos los tipos",
- "fr_FR": "Tous les types",
+ "fr_FR": "Tous les Types",
"he_IL": "כל הסוגים",
"it_IT": "Tutti i tipi",
"ja_JP": "すべての種別",
@@ -18985,7 +18610,7 @@
"pt_BR": "Diálogo do Gabinete",
"ru_RU": "Сообщение кабинета",
"sv_SE": "Cabinet-dialog",
- "th_TH": "",
+ "th_TH": "กล่องโต้ตอบไฟล์ Cabinet",
"tr_TR": "",
"uk_UA": "Сповіщення Cabinet",
"zh_CN": "档案对话框",
@@ -19010,7 +18635,7 @@
"pt_BR": "Digite o novo nome do seu Amiibo",
"ru_RU": "Введите новое имя вашего Amiibo",
"sv_SE": "Ange nya namnet för din Amiibo",
- "th_TH": "",
+ "th_TH": "กรุณาใส่ชื่อใหม่ของ Amiibo ของคุณ",
"tr_TR": "",
"uk_UA": "Вкажіть Ваше нове ім'я Amiibo",
"zh_CN": "输入你的 Amiibo 的新名字",
@@ -19033,9 +18658,9 @@
"no_NO": "Vennligst skann Amiiboene dine nå.",
"pl_PL": "",
"pt_BR": "Por favor, escaneie seu Amiibo agora.",
- "ru_RU": "Пожалуйста, отсканируйте свой Amiibo.",
+ "ru_RU": "Пожалуйста, сканируйте ваш Amiibo.",
"sv_SE": "Skanna din Amiibo nu.",
- "th_TH": "",
+ "th_TH": "กรุณาสแกน Amiibo ของคุณตอนนี้",
"tr_TR": "",
"uk_UA": "Будь ласка, проскануйте Ваш Amiibo.",
"zh_CN": "请现在扫描你的 Amiibo",
@@ -19050,7 +18675,7 @@
"el_GR": "Εικονικό Πληκτρολόγιο",
"en_US": "Software Keyboard",
"es_ES": "Teclado de software",
- "fr_FR": "Clavier logiciel",
+ "fr_FR": "Clavier Logiciel",
"he_IL": "מקלדת וירטואלית",
"it_IT": "Tastiera software",
"ja_JP": "ソフトウェアキーボード",
@@ -19104,7 +18729,7 @@
"he_IL": "מחויב להיות ללא אותיות CJK",
"it_IT": "Può contenere solo caratteri non CJK",
"ja_JP": "CJK文字以外のみ",
- "ko_KR": "CJK 문자가 아닌 문자만 가능",
+ "ko_KR": "한중일 문자 입력 불가",
"no_NO": "Må kun være uten CJK-tegn",
"pl_PL": "Nie może zawierać znaków CJK",
"pt_BR": "Apenas devem ser caracteres não CJK.",
@@ -19133,7 +18758,7 @@
"no_NO": "Må være kun ASCII-tekst",
"pl_PL": "Musi zawierać tylko tekst ASCII",
"pt_BR": "Deve ser apenas texto ASCII",
- "ru_RU": "Текст должен быть только в ASCII кодировке",
+ "ru_RU": "Текст должен быть только в кодировке ASCII",
"sv_SE": "Får endast vara ASCII-text",
"th_TH": "ต้องเป็นตัวอักษร ASCII เท่านั้น",
"tr_TR": "Sadece ASCII karakterler olabilir",
@@ -19150,7 +18775,7 @@
"el_GR": "",
"en_US": "Supported Controllers:",
"es_ES": "Controladores Compatibles:",
- "fr_FR": "Contrôleurs pris en charge :",
+ "fr_FR": "Manettes Pris en Charge :",
"he_IL": "בקרים נתמכים:",
"it_IT": "Controller supportati:",
"ja_JP": "サポートされているコントローラ:",
@@ -19208,7 +18833,7 @@
"no_NO": "Din nåværende konfigurasjon er ugyldig. Åpne innstillinger og konfigurer inndata.",
"pl_PL": "Twoja aktualna konfiguracja jest nieprawidłowa. Otwórz ustawienia i skonfiguruj swoje wejścia.",
"pt_BR": "Sua configuração atual é inválida. Abra as configurações e reconfigure suas entradas.",
- "ru_RU": "Текущая конфигурация некорректна. Откройте параметры и перенастройте управление.",
+ "ru_RU": "Ваша текущая конфигурация недействительна. Откройте параметры и перенастройте управление.",
"sv_SE": "Din aktuella konfiguration är ogiltig. Öppna inställningarna och konfigurera om din inmatning.",
"th_TH": "การกำหนดค่าปัจจุบันของคุณไม่ถูกต้อง กรุณาเปิดการตั้งค่าและกำหนดค่าอินพุตของคุณใหม่",
"tr_TR": "Halihazırdaki konfigürasyonunuz geçersiz. Ayarları açın ve girişlerinizi yeniden konfigüre edin.",
@@ -19225,7 +18850,7 @@
"el_GR": "",
"en_US": "Docked mode set. Handheld control should be disabled.",
"es_ES": "Modo acoplado activado. El modo portátil debería estar desactivado.",
- "fr_FR": "Mode station d'accueil défini. Le mode contrôle portable doit être désactivé.",
+ "fr_FR": "Mode Station d'Accueil défini. Le mode contrôle Portable doit être désactivé.",
"he_IL": "מצב עגינה מוגדר. כדאי ששליטה ניידת תהיה מושבתת.",
"it_IT": "Modalità TV attivata. Gli input della modalità portatile dovrebbero essere disabilitati.",
"ja_JP": "ドッキングモードが設定されています. 携帯コントロールは無効にする必要があります.",
@@ -19233,7 +18858,7 @@
"no_NO": "Docked modus. Håndholdt kontroll skal være deaktivert.",
"pl_PL": "Ustawiony tryb zadokowany. Sterowanie przenośne powinno być wyłączone.",
"pt_BR": "Modo TV definido. O controle portátil deve ser desabilitado.",
- "ru_RU": "Используется стационарный режим. Управление в портативном режиме должно быть отключено.",
+ "ru_RU": "Используется режим док-станции. Управление в портативном режиме должно быть отключено.",
"sv_SE": "Dockat läge angivet. Handhållna kontroller bör inaktiveras.",
"th_TH": "ตั้งค่าด็อกโหมด ควรปิดใช้งานการควบคุมแบบแฮนด์เฮลด์",
"tr_TR": "Docked mod ayarlandı. Portatif denetim devre dışı bırakılmalı.",
@@ -19250,7 +18875,7 @@
"el_GR": "Μετονομασία Παλαιών Αρχείων...",
"en_US": "Renaming Old Files...",
"es_ES": "Renombrando archivos viejos...",
- "fr_FR": "Renommage des anciens fichiers...",
+ "fr_FR": "Renommage des Anciens Fichiers...",
"he_IL": "משנה שמות של קבצים ישנים...",
"it_IT": "Ridenominazione dei vecchi file...",
"ja_JP": "古いファイルをリネーム中...",
@@ -19300,11 +18925,11 @@
"el_GR": "Προσθήκη Νέων Αρχείων...",
"en_US": "Adding New Files...",
"es_ES": "Añadiendo nuevos archivos...",
- "fr_FR": "Ajout des nouveaux fichiers...",
+ "fr_FR": "Ajout des Nouveaux Fichiers...",
"he_IL": "מוסיף קבצים חדשים...",
"it_IT": "Aggiunta dei nuovi file...",
"ja_JP": "新規ファイルを追加中...",
- "ko_KR": "새 파일 추가...",
+ "ko_KR": "신규 파일 추가...",
"no_NO": "Legger til nye filer...",
"pl_PL": "Dodawanie Nowych Plików...",
"pt_BR": "Adicionando Novos Arquivos...",
@@ -19325,7 +18950,7 @@
"el_GR": "Εξαγωγή Ενημέρωσης...",
"en_US": "Extracting Update...",
"es_ES": "Extrayendo actualización...",
- "fr_FR": "Extraction de la mise à jour…",
+ "fr_FR": "Extraction de la Mise à Jour…",
"he_IL": "מחלץ עדכון...",
"it_IT": "Estrazione dell'aggiornamento...",
"ja_JP": "アップデートを展開中...",
@@ -19350,7 +18975,7 @@
"el_GR": "Λήψη Ενημέρωσης...",
"en_US": "Downloading Update...",
"es_ES": "Descargando actualización...",
- "fr_FR": "Téléchargement de la mise à jour...",
+ "fr_FR": "Téléchargement de la Mise à Jour...",
"he_IL": "מוריד עדכון...",
"it_IT": "Download dell'aggiornamento...",
"ja_JP": "アップデートをダウンロード中...",
@@ -19375,7 +19000,7 @@
"el_GR": "Προσκολλημένο",
"en_US": "Docked",
"es_ES": "Dock/TV",
- "fr_FR": "Mode Docké",
+ "fr_FR": "Mode Station d'Accueil",
"he_IL": "בתחנת עגינה",
"it_IT": "TV",
"ja_JP": "ドッキング",
@@ -19383,7 +19008,7 @@
"no_NO": "Forankret",
"pl_PL": "Zadokowany",
"pt_BR": "Dock/TV",
- "ru_RU": "Стационарный режим",
+ "ru_RU": "Док-Станция",
"sv_SE": "Dockad",
"th_TH": "ด็อก",
"tr_TR": "",
@@ -19408,7 +19033,7 @@
"no_NO": "Håndholdt",
"pl_PL": "Przenośny",
"pt_BR": "Portátil",
- "ru_RU": "Портативный режим",
+ "ru_RU": "Портативный",
"sv_SE": "Handhållen",
"th_TH": "แฮนด์เฮลด์",
"tr_TR": "El tipi",
@@ -19425,7 +19050,7 @@
"el_GR": "Σφάλμα Σύνδεσης.",
"en_US": "Connection Error.",
"es_ES": "Error de conexión.",
- "fr_FR": "Erreur de connexion.",
+ "fr_FR": "Erreur de Connexion.",
"he_IL": "שגיאת חיבור",
"it_IT": "Errore di connessione.",
"ja_JP": "接続エラー.",
@@ -19550,7 +19175,7 @@
"el_GR": "Σύνταξη των Shaders",
"en_US": "Compiling Shaders",
"es_ES": "Compilando sombreadores",
- "fr_FR": "Compilation des shaders",
+ "fr_FR": "Compilation des Shaders",
"he_IL": "קימפול הצללות",
"it_IT": "Compilazione degli shader",
"ja_JP": "シェーダーをコンパイル中",
@@ -19575,7 +19200,7 @@
"el_GR": "Όλα τα πληκτρολόγια",
"en_US": "All Keyboards",
"es_ES": "Todos los teclados",
- "fr_FR": "Tous les claviers",
+ "fr_FR": "Tous les Claviers",
"he_IL": "כל המקלדות",
"it_IT": "Tutte le tastiere",
"ja_JP": "すべてのキーボード",
@@ -19650,7 +19275,7 @@
"el_GR": "Όλες Οι Υποστηριζόμενες Μορφές",
"en_US": "All Supported Formats",
"es_ES": "Todos los formatos soportados",
- "fr_FR": "Tous les formats supportés",
+ "fr_FR": "Tous les Formats Supportés",
"he_IL": "כל הפורמטים הנתמכים",
"it_IT": "Tutti i formati supportati",
"ja_JP": "すべての対応フォーマット",
@@ -19704,7 +19329,7 @@
"he_IL": "אתחול {0}",
"it_IT": "Riavvio di {0}",
"ja_JP": "{0} 再起動",
- "ko_KR": "{0} 재부팅",
+ "ko_KR": "{0} 다시 시작",
"no_NO": "Omstart av {0}",
"pl_PL": "Ponowne uruchomienie {0}",
"pt_BR": "Reinício de {0}",
@@ -19725,7 +19350,7 @@
"el_GR": "Συντομεύσεις Πληκτρολογίου",
"en_US": "Keyboard Hotkeys",
"es_ES": "Atajos de teclado",
- "fr_FR": "Raccourcis clavier",
+ "fr_FR": "Raccourcis Clavier",
"he_IL": "מקשי קיצור במקלדת",
"it_IT": "Tasti di scelta rapida",
"ja_JP": "キーボード ホットキー",
@@ -19750,7 +19375,7 @@
"el_GR": "Συντομεύσεις Πληκτρολογίου",
"en_US": "Keyboard Hotkeys",
"es_ES": "Atajos de teclado",
- "fr_FR": "Raccourcis clavier",
+ "fr_FR": "Raccourcis Clavier",
"he_IL": "מקשי קיצור במקלדת",
"it_IT": "Tasti di scelta rapida",
"ja_JP": "キーボード ホットキー",
@@ -19775,7 +19400,7 @@
"el_GR": "Στιγμιότυπο Οθόνης:",
"en_US": "Screenshot:",
"es_ES": "Captura de pantalla:",
- "fr_FR": "Capture d'écran :",
+ "fr_FR": "Capture d'Écran :",
"he_IL": "צילום מסך:",
"it_IT": "Cattura uno screenshot:",
"ja_JP": "スクリーンショット:",
@@ -19783,7 +19408,7 @@
"no_NO": "Skjermbilde",
"pl_PL": "Zrzut Ekranu:",
"pt_BR": "Captura de Tela:",
- "ru_RU": "Скриншот:",
+ "ru_RU": "Снимок экрана:",
"sv_SE": "Skärmbild:",
"th_TH": "ภาพหน้าจอ:",
"tr_TR": "Ekran Görüntüsü Al:",
@@ -19850,7 +19475,7 @@
"el_GR": "Σίγαση:",
"en_US": "Mute:",
"es_ES": "Silenciar:",
- "fr_FR": "Couper le son :",
+ "fr_FR": "Couper le Son :",
"he_IL": "השתק:",
"it_IT": "Disattiva l'audio:",
"ja_JP": "ミュート:",
@@ -19875,7 +19500,7 @@
"el_GR": "Ρυθμίσεις Ελέγχου Κίνησης",
"en_US": "Motion Control Settings",
"es_ES": "Opciones de controles de movimiento",
- "fr_FR": "Paramètres du contrôle de mouvement",
+ "fr_FR": "Paramètres du Contrôle de Mouvement",
"he_IL": "הגדרות שליטת תנועות ג'ירוסקופ",
"it_IT": "Impostazioni dei sensori di movimento",
"ja_JP": "モーションコントロール設定",
@@ -19900,7 +19525,7 @@
"el_GR": "Ρυθμίσεις Δόνησης",
"en_US": "Rumble Settings",
"es_ES": "Opciones de vibración",
- "fr_FR": "Paramètres de vibration",
+ "fr_FR": "Paramètres de Vibration",
"he_IL": "הגדרות רטט",
"it_IT": "Impostazioni di vibrazione",
"ja_JP": "振動設定",
@@ -19933,9 +19558,9 @@
"no_NO": "LED-innstillinger",
"pl_PL": "",
"pt_BR": "Configurações de LED",
- "ru_RU": "Настройки LED-подсветки",
+ "ru_RU": "Настройки LED-Подсветки",
"sv_SE": "LED-inställningar",
- "th_TH": "",
+ "th_TH": "ตั้งค่าไฟ LED",
"tr_TR": "",
"uk_UA": "Налаштування LED",
"zh_CN": "LED 设置",
@@ -19950,7 +19575,7 @@
"el_GR": "Επιλογή Αρχείου Θέματος",
"en_US": "Select Theme File",
"es_ES": "Selecciona un archivo de tema",
- "fr_FR": "Sélectionnez un fichier de thème",
+ "fr_FR": "Sélectionnez un Fichier de Thème",
"he_IL": "בחרו קובץ ערכת נושא",
"it_IT": "Seleziona file del tema",
"ja_JP": "テーマファイルを選択",
@@ -20025,7 +19650,7 @@
"el_GR": "",
"en_US": "Amiibo",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "אמיבו",
"it_IT": "",
"ja_JP": "",
@@ -20033,13 +19658,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "Амибо",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "อมิโบ้",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -20150,7 +19775,7 @@
"el_GR": "Επιλογή αρχείων ενημέρωσης",
"en_US": "Select update files",
"es_ES": "Selecciona archivo(s) de actualización",
- "fr_FR": "Sélectionnez les fichiers de mise à jour",
+ "fr_FR": "Sélectionnez les fichiers de Mise à Jour",
"he_IL": "בחרו קבצי עדכון",
"it_IT": "Seleziona file di aggiornamento",
"ja_JP": "アップデートファイルを選択",
@@ -20200,7 +19825,7 @@
"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",
+ "fr_FR": "Vérifier et Réduire le Fichier XCI",
"he_IL": "",
"it_IT": "Controlla e riduci la dimensione del file XCI",
"ja_JP": "",
@@ -20210,7 +19835,7 @@
"pt_BR": "Verifique e Reduza o Arquivo XCI",
"ru_RU": "Проверить и обрезать XCI файл",
"sv_SE": "Kontrollera och optimera XCI-filer",
- "th_TH": "",
+ "th_TH": "ตรวจสอบและตัดแต่งไฟล์ XCI",
"tr_TR": "",
"uk_UA": "Перевірити та Обрізати XCI файл",
"zh_CN": "检查并瘦身 XCI 文件",
@@ -20233,9 +19858,9 @@
"no_NO": "Denne funksjonen kontrollerer først hvor mye plass som er ledig, og trimmer deretter XCI-filen for å spare diskplass.",
"pl_PL": "",
"pt_BR": "Esta função primeiro verificará o espaço vazio e depois reduzirá o arquivo XCI para economizar espaço em disco.",
- "ru_RU": "Эта функция сначала проверит наличие пустого пространства, а затем обрежет файл XCI, чтобы сэкономить место на диске.",
+ "ru_RU": "Эта функция сначала проверит наличие пустого пространства, а затем обрежет XCI файл для экономии места на диске.",
"sv_SE": "Denna funktion kommer först att kontrollera ledigt utrymme och sedan optimera XCI-filen för att spara diskutrymme.",
- "th_TH": "",
+ "th_TH": "ฟังก์ชันนี้จะตรวจสอบพื้นที่ว่างก่อน จากนั้นจึงตัดแต่งไฟล์ XCI เพื่อประหยัดพื้นที่ดิสก์",
"tr_TR": "",
"uk_UA": "Ця функція спочатку перевірить наявність порожнього місця, після чого обріже файл XCI для економії місця на диску.",
"zh_CN": "这个功能将会先检查 XCI 文件,再对其执行瘦身操作以节约磁盘空间。",
@@ -20260,7 +19885,7 @@
"pt_BR": "Tamanho atual do arquivo: {0:n} MB\nTamanho dos dados do jogo: {1:n} MB\nEconomia de espaço em disco: {2:n} MB",
"ru_RU": "Размер текущего файла: {0:n} Мб\nРазмер игровых данных: {1:n} MB\nЭкономия дискового пространства: {2:n} Мб",
"sv_SE": "Aktuell filstorlek: {0:n} MB\nStorlek för speldata: {1:n} MB\nSparat diskutrymme: {2:n} MB",
- "th_TH": "",
+ "th_TH": "ขนาดไฟล์ปัจจุบัน: {0:n} เมกะไบต์\nขนาดข้อมูลเกม: {1:n} เมกะไบต์\nพื้นที่ดิสก์ที่ประหยัดได้: {2:n} เมกะไบต์",
"tr_TR": "",
"uk_UA": "Поточний розмір файла: {0:n} MB\nРозмір файлів гри: {1:n} MB\nЕкономія місця: {2:n} MB",
"zh_CN": "当前文件大小: {0:n} MB\n游戏数据大小: {1:n} MB\n节约的磁盘空间: {2:n} MB",
@@ -20275,7 +19900,7 @@
"el_GR": "",
"en_US": "XCI File does not need to be trimmed. Check logs for further details",
"es_ES": "El archivo XCI no necesita ser recortado. Verifica los logs para más detalles.",
- "fr_FR": "Le fichier XCI n’a pas besoin d’être réduit. Référez-vous aux journaux pour plus de détails.",
+ "fr_FR": "Le Fichier XCI n’a pas besoin d’être réduit. Référez-vous aux journaux pour plus de détails.",
"he_IL": "",
"it_IT": "Non è necessario ridurre la dimensione del file XCI. Controlla i log per ulteriori dettagli",
"ja_JP": "",
@@ -20283,9 +19908,9 @@
"no_NO": "XCI-filen trenger ikke å trimmes. Sjekk loggene for mer informasjon",
"pl_PL": "",
"pt_BR": "O arquivo XCI não precisa ser reduzido. Verifique os logs para mais detalhes",
- "ru_RU": "Файл XCI не нуждается в обрезке. Проверьте логи для получения более подробной информации",
+ "ru_RU": "XCI файл содержит недопустимые данные. Проверьте логи для получения дополнительной информации.",
"sv_SE": "XCI-filen behöver inte optimeras. Kontrollera loggen för mer information",
- "th_TH": "",
+ "th_TH": "ไฟล์ XCI ไม่จำเป็นต้องถูกตัดแต่ง โปรดตรวจสอบบันทึก (logs) สำหรับรายละเอียดเพิ่มเติม",
"tr_TR": "",
"uk_UA": "XCI файл не потребує обрізання. Перевірте журнали (logs) для отримання додаткової інформації",
"zh_CN": "XCI 文件不需要被瘦身。查看日志以获得更多细节。",
@@ -20310,7 +19935,7 @@
"pt_BR": "O arquivo XCI reduzido não pode ser desfeito. Verifique os logs para mais detalhes",
"ru_RU": "XCI файл не может быть обрезан. Проверьте логи для получения более подробной информации",
"sv_SE": "XCI-filen kan inte avoptimeras. Kontrollera loggen för mer information",
- "th_TH": "",
+ "th_TH": "ไฟล์ XCI ไม่สามารถคืนสภาพเดิม (untrimmed) ได้ โปรดตรวจสอบบันทึก (logs) สำหรับรายละเอียดเพิ่มเติม",
"tr_TR": "",
"uk_UA": "XCI файл не може бути обрізаний. Перевірте журнали (logs) для отримання додаткової інформації",
"zh_CN": "XCI 文件不能被瘦身。查看日志以获得更多细节。",
@@ -20333,9 +19958,9 @@
"no_NO": "XCI-filen er skrivebeskyttet og kunne ikke gjøres skrivbar. Sjekk loggene for mer informasjon",
"pl_PL": "",
"pt_BR": "O arquivo XCI é somente leitura e não pôde ser tornado gravável. Verifique os logs para mais detalhes",
- "ru_RU": "Файл XCI доступен только для чтения и его невозможно сделать доступным для записи. Проверьте логи для получения более подробной информации",
+ "ru_RU": "XCI файл доступен только для чтения и его невозможно сделать доступным для записи. Проверьте логи для получения более подробной информации",
"sv_SE": "XCI-filen är skrivskyddad och kunde inte göras skrivbar. Kontrollera loggen för mer information",
- "th_TH": "",
+ "th_TH": "ไฟล์ XCI เป็นแบบอ่านอย่างเดียว และไม่สามารถเปลี่ยนเป็นแบบเขียนได้ โปรดตรวจสอบบันทึก (logs) สำหรับรายละเอียดเพิ่มเติม",
"tr_TR": "",
"uk_UA": "XCI файл \"Тільки для Читання\" і не може бути прочитаним. Перевірте журнали (logs) для отримання додаткової інформації",
"zh_CN": "XCI 文件是只读的,且不可以被标记为可读取的。查看日志以获得更多细节。",
@@ -20350,7 +19975,7 @@
"el_GR": "",
"en_US": "XCI File has changed in size since it was scanned. Please check the file is not being written to and try again.",
"es_ES": "El archivo XCI ha cambiado de tamaño desde que fue escaneado. Verifica que no se esté escribiendo al archivo y vuelve a intentarlo.",
- "fr_FR": "La taille du fichier XCI a changé depuis son analyse. Veuillez vérifier que le fichier n’est pas en cours d’écriture, puis réessayez.",
+ "fr_FR": "La taille du Fichier XCI a changé depuis son analyse. Veuillez vérifier que le fichier n’est pas en cours d’écriture, puis réessayez.",
"he_IL": "",
"it_IT": "La dimensione del file XCI è cambiata da quando è stato scansionato. Controlla che il file non stia venendo scritto da qualche altro programma e poi riprova.",
"ja_JP": "",
@@ -20358,9 +19983,9 @@
"no_NO": "XCI File har endret størrelse siden den ble skannet. Kontroller at det ikke skrives til filen, og prøv på nytt.",
"pl_PL": "",
"pt_BR": "O arquivo XCI mudou de tamanho desde que foi escaneado. Verifique se o arquivo não está sendo gravado e tente novamente.",
- "ru_RU": "Файл XCI изменился в размере после сканирования. Проверьте, не производится ли запись в этот файл, и повторите попытку.",
+ "ru_RU": "XCI файл изменился в размере после сканирования. Проверьте, не производится ли запись в этот файл, и повторите попытку.",
"sv_SE": "XCI-filen har ändrats i storlek sedan den lästes av. Kontrollera att filen inte skrivs till och försök igen.",
- "th_TH": "",
+ "th_TH": "ขนาดไฟล์ XCI มีการเปลี่ยนแปลงตั้งแต่ที่สแกนครั้งล่าสุด กรุณาตรวจสอบว่าไฟล์ไม่ได้ถูกเขียนข้อมูล และลองใหม่อีกครั้ง",
"tr_TR": "",
"uk_UA": "Розмір файлу XCI змінився з моменту сканування. Перевірте, чи не записується файл, та спробуйте знову",
"zh_CN": "XCI 文件在扫描后大小发生了变化。请检查文件是否未被写入,然后重试。",
@@ -20385,7 +20010,7 @@
"pt_BR": "O arquivo XCI tem dados na área de espaço livre, não é seguro reduzi-lo",
"ru_RU": "XCI файл содержит данные в пустой зоне, обрезать его небезопасно",
"sv_SE": "XCI-filen har data i det lediga utrymmet. Den är inte säker att optimera",
- "th_TH": "",
+ "th_TH": "ไฟล์ XCI มีข้อมูลในพื้นที่ว่าง จึงไม่ปลอดภัยที่จะทำการตัดแต่ง",
"tr_TR": "",
"uk_UA": "Файл XCI містить дані в зоні вільного простору, тому обрізка небезпечна",
"zh_CN": "XCI 文件的空闲区域内有数据,不能安全瘦身。",
@@ -20408,9 +20033,9 @@
"no_NO": "XCI-filen inneholder ugyldige data. Sjekk loggene for ytterligere detaljer",
"pl_PL": "",
"pt_BR": "O arquivo XCI contém dados inválidos. Verifique os logs para obter mais detalhes",
- "ru_RU": "Файл XCI содержит недопустимые данные. Проверьте логи для получения дополнительной информации",
+ "ru_RU": "XCI файл содержит недопустимые данные. Проверьте логи для получения дополнительной информации",
"sv_SE": "XCI-filen innehåller ogiltig data. Kontrollera loggen för mer information",
- "th_TH": "",
+ "th_TH": "ไฟล์ XCI มีข้อมูลที่ไม่ถูกต้อง โปรดตรวจสอบบันทึก (logs) สำหรับรายละเอียดเพิ่มเติม",
"tr_TR": "",
"uk_UA": "XCI Файл містить недійсні дані. Перевірте журнали (logs) для отримання додаткової інформації",
"zh_CN": "XCI 文件含有无效数据。查看日志以获得更多细节。",
@@ -20425,7 +20050,7 @@
"el_GR": "",
"en_US": "XCI File could not be opened for writing. Check logs for further details",
"es_ES": "El archivo XCI no se puede abrir para escribirlo. Lee el registro para más información.",
- "fr_FR": "Fichier XCI n'a pas pu été ouvert pour écriture. Regarder les journaux pour plus de détails",
+ "fr_FR": "Fichier XCI n'a pas pu être ouvert pour écriture. Regarder les journaux pour plus de détails",
"he_IL": "",
"it_IT": "Il file XCI non può essere aperto in scrittura. Controlla i log per ulteriori dettagli",
"ja_JP": "",
@@ -20433,9 +20058,9 @@
"no_NO": "XCI-filen kunne ikke åpnes for skriving. Sjekk loggene for ytterligere detaljer",
"pl_PL": "",
"pt_BR": "O arquivo XCI não pôde ser aberto para gravação. Verifique os logs para mais detalhes",
- "ru_RU": "XCI файл не удалось открыть для записи. Проверьте логи для получения дополнительной информации",
+ "ru_RU": "Не удалось открыть XCI файл для записи. Проверьте журналы для получения дополнительной информации",
"sv_SE": "XCI-filen kunde inte öppnas för skrivning. Kontrollera loggen för mer information",
- "th_TH": "",
+ "th_TH": "ไม่สามารถเปิดไฟล์ XCI เพื่อเขียนข้อมูลได้ โปรดตรวจสอบบันทึก (logs) สำหรับรายละเอียดเพิ่มเติม",
"tr_TR": "",
"uk_UA": "XCI Файл файл не вдалося відкрити для запису. Перевірте журнали для додаткової інформації",
"zh_CN": "XCI 文件不能被读写。查看日志以获得更多细节。",
@@ -20458,9 +20083,9 @@
"no_NO": "Trimming av XCI-filen mislyktes",
"pl_PL": "",
"pt_BR": "A redução do arquivo XCI falhou",
- "ru_RU": "Обрезка файла XCI не удалась",
+ "ru_RU": "Обрезка XCI файла не удалась",
"sv_SE": "Optimering av XCI-filen misslyckades",
- "th_TH": "",
+ "th_TH": "การตัดแต่งไฟล์ XCI ล้มเหลว",
"tr_TR": "",
"uk_UA": "Не вдалося обрізати файл XCI",
"zh_CN": "XCI 文件瘦身失败",
@@ -20485,7 +20110,7 @@
"pt_BR": "A operação foi cancelada",
"ru_RU": "Операция была отменена",
"sv_SE": "Åtgärden avbröts",
- "th_TH": "",
+ "th_TH": "การดำเนินการถูกยกเลิกแล้ว",
"tr_TR": "",
"uk_UA": "Операція перервана",
"zh_CN": "操作已取消",
@@ -20510,7 +20135,7 @@
"pt_BR": "Nenhuma operação foi realizada",
"ru_RU": "Операция не была проведена",
"sv_SE": "Ingen åtgärd genomfördes",
- "th_TH": "",
+ "th_TH": "ไม่มีการดำเนินการใด ๆ ถูกทำขึ้น",
"tr_TR": "",
"uk_UA": "Операція не проводилася",
"zh_CN": "未执行操作",
@@ -20525,7 +20150,7 @@
"el_GR": "Διαχειριστής Προφίλ Χρήστη",
"en_US": "User Profiles Manager",
"es_ES": "Administrar perfiles de usuario",
- "fr_FR": "Gestionnaire de profils utilisateur",
+ "fr_FR": "Gestionnaire de Profils d'Utilisateurs",
"he_IL": "ניהול פרופילי משתמש",
"it_IT": "Gestione profili utente",
"ja_JP": "ユーザプロファイルを管理",
@@ -20533,7 +20158,7 @@
"no_NO": "Bruker Profiler Behandler",
"pl_PL": "Menedżer Profili Użytkowników",
"pt_BR": "Gerenciador de Perfis de Usuário",
- "ru_RU": "Менеджер учётных записей",
+ "ru_RU": "Управление профилями",
"sv_SE": "Hanterare för användarprofiler",
"th_TH": "จัดการโปรไฟล์ผู้ใช้",
"tr_TR": "Kullanıcı Profillerini Yönet",
@@ -20550,7 +20175,7 @@
"el_GR": "Διαχειριστής των Cheats",
"en_US": "Cheats Manager",
"es_ES": "Administrar cheats",
- "fr_FR": "Gestionnaire de cheats",
+ "fr_FR": "Gestionnaire de Cheats",
"he_IL": "נהל צ'יטים למשחק",
"it_IT": "Gestione trucchi",
"ja_JP": "チート管理",
@@ -20558,7 +20183,7 @@
"no_NO": "Juksing behandler",
"pl_PL": "Menedżer Kodów",
"pt_BR": "Gerenciador de Trapaças",
- "ru_RU": "Менеджер читов",
+ "ru_RU": "Управление читами",
"sv_SE": "Fuskhanterare",
"th_TH": "จัดการสูตรโกง",
"tr_TR": "Oyun Hilelerini Yönet",
@@ -20572,10 +20197,10 @@
"Translations": {
"ar_SA": "إدارة المحتوى القابل للتنزيل لـ {0} ({1})",
"de_DE": "Spiel-DLC verwalten",
- "el_GR": "Downloadable Content Manager",
+ "el_GR": "",
"en_US": "Manage Downloadable Content for {0} ({1})",
"es_ES": "Administrar contenido descargable",
- "fr_FR": "Gérer le contenu téléchargeable pour {0} ({1})",
+ "fr_FR": "Gérer le Contenu Téléchargeable pour {0} ({1})",
"he_IL": "נהל הרחבות משחק עבור {0} ({1})",
"it_IT": "Gestisci DLC per {0} ({1})",
"ja_JP": "DLC 管理",
@@ -20600,7 +20225,7 @@
"el_GR": "",
"en_US": "Manage Mods for {0} ({1})",
"es_ES": "Administrar Mods para {0} ({1})",
- "fr_FR": "Gérer les mods pour {0} ({1})",
+ "fr_FR": "Gérer les Mods pour {0} ({1})",
"he_IL": "",
"it_IT": "Gestisci mod per {0} ({1})",
"ja_JP": "",
@@ -20625,7 +20250,7 @@
"el_GR": "Διαχειριστής Ενημερώσεων Τίτλου",
"en_US": "Title Update Manager",
"es_ES": "Administrar actualizaciones",
- "fr_FR": "Gestionnaire de mises à jour",
+ "fr_FR": "Gestionnaire de Mises à Jour",
"he_IL": "נהל עדכוני משחקים",
"it_IT": "Gestione aggiornamenti",
"ja_JP": "アップデート管理",
@@ -20633,7 +20258,7 @@
"no_NO": "Tittel oppdatering behandler",
"pl_PL": "Menedżer Aktualizacji Tytułu",
"pt_BR": "Gerenciador de Atualização de Título",
- "ru_RU": "Менеджер обновлений игр",
+ "ru_RU": "Управление обновлений игр",
"sv_SE": "Hanterare för speluppdateringar",
"th_TH": "จัดการอัปเดตหัวข้อ",
"tr_TR": "Oyun Güncellemelerini Yönet",
@@ -20650,7 +20275,7 @@
"el_GR": "",
"en_US": "XCI File Trimmer",
"es_ES": "Recortador de archivos XCI",
- "fr_FR": "Réducteur de fichiers XCI",
+ "fr_FR": "Réducteur de Fichiers XCI",
"he_IL": "",
"it_IT": "Riduci dimensioni dei file XCI",
"ja_JP": "",
@@ -20658,9 +20283,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "Redutor de Arquivo XCI",
- "ru_RU": "Уменьшение размера XCI файлов",
+ "ru_RU": "Триммер XCI файлов",
"sv_SE": "Optimera XCI-filer",
- "th_TH": "",
+ "th_TH": "เครื่องมือตัดแต่งไฟล์ XCI",
"tr_TR": "",
"uk_UA": "Обрізка XCI Файлів",
"zh_CN": "XCI 文件瘦身器",
@@ -20683,9 +20308,9 @@
"no_NO": "{0} av {1} Valgte tittel(er)",
"pl_PL": "",
"pt_BR": "{0} de {1} Título(s) Selecionado(s)",
- "ru_RU": "{0} из {1} файла(ов) выбрано",
+ "ru_RU": "{0} из {1} файл(а/ов) выбран(о)",
"sv_SE": "{0} av {1} spel markerade",
- "th_TH": "",
+ "th_TH": "เลือก {0} จาก {1} รายการ",
"tr_TR": "",
"uk_UA": "{0} з {1} тайтл(ів) обрано",
"zh_CN": "在 {1} 中选中了 {0} 个游戏 ",
@@ -20708,9 +20333,9 @@
"no_NO": "{0} av {1} Tittel(er) valgt ({2} vises)",
"pl_PL": "",
"pt_BR": "{0} de {1} Título(s) Selecionado(s) ({2} exibidos)",
- "ru_RU": "{0} из {1} файла(ов) выбрано ({2} показано)",
+ "ru_RU": "{0} из {1} файл(а/ов) выбран(о) ({2} показан(о))",
"sv_SE": "{0} av {1} spel markerade ({2} visade)",
- "th_TH": "",
+ "th_TH": "เลือก {0} จาก {1} รายการ (แสดงผล {2} รายการ)",
"tr_TR": "",
"uk_UA": "{0} з {1} тайтл(ів) обрано ({2} відображається)",
"zh_CN": "在 {1} 中选中了 {0} 个游戏 (显示了 {2} 个)",
@@ -20735,7 +20360,7 @@
"pt_BR": "Reduzindo {0} Título(s)...",
"ru_RU": "Обрезка {0} файла(ов)...",
"sv_SE": "Optimerar {0} spel...",
- "th_TH": "",
+ "th_TH": "กำลังตัดแต่ง {0} รายการ...",
"tr_TR": "",
"uk_UA": "Обрізка {0} тайтл(ів)...",
"zh_CN": "{0} 个游戏瘦身中。。。",
@@ -20760,7 +20385,7 @@
"pt_BR": "Desfazendo redução {0} Título(s)...",
"ru_RU": "Отмена обрезки {0} файла(ов)...",
"sv_SE": "Avoptimerar {0} spel...",
- "th_TH": "",
+ "th_TH": "กำลังยกเลิกการตัดแต่ง {0} รายการ...",
"tr_TR": "",
"uk_UA": "Необрізаних {0} тайтл(ів)...",
"zh_CN": "正在精简 {0} 个游戏",
@@ -20785,7 +20410,7 @@
"pt_BR": "Falhou",
"ru_RU": "Ошибка",
"sv_SE": "Misslyckades",
- "th_TH": "",
+ "th_TH": "ล้มเหลว",
"tr_TR": "",
"uk_UA": "Невдача",
"zh_CN": "失败",
@@ -20808,9 +20433,9 @@
"no_NO": "Potensielle besparelser",
"pl_PL": "",
"pt_BR": "Economia Potencial",
- "ru_RU": "Потенциально освобождено места",
+ "ru_RU": "Потенциальная экономия места",
"sv_SE": "Möjlig besparning",
- "th_TH": "",
+ "th_TH": "พื้นที่ประหยัดได้",
"tr_TR": "",
"uk_UA": "Потенційна економія",
"zh_CN": "潜在的储存空间节省",
@@ -20833,9 +20458,9 @@
"no_NO": "Faktiske besparelser",
"pl_PL": "",
"pt_BR": "Economia Real",
- "ru_RU": "Реально освобождено места",
+ "ru_RU": "Фактическая экономия места",
"sv_SE": "Faktisk besparning",
- "th_TH": "",
+ "th_TH": "พื้นที่ที่ประหยัดจริง",
"tr_TR": "",
"uk_UA": "Зекономлено",
"zh_CN": "实际的储存空间节省",
@@ -20860,11 +20485,11 @@
"pt_BR": "",
"ru_RU": "{0:n0} Мб",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "{0:n0} เมกะไบต์",
"tr_TR": "",
"uk_UA": "{0:n0} Мб",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -20883,9 +20508,9 @@
"no_NO": "Velg vist",
"pl_PL": "",
"pt_BR": "Marcar Todos",
- "ru_RU": "Выбрать то что показано",
+ "ru_RU": "Выбрать видимое",
"sv_SE": "Markera visade",
- "th_TH": "",
+ "th_TH": "เลือกรายการที่แสดง",
"tr_TR": "",
"uk_UA": "Вибрати показані",
"zh_CN": "选定显示的",
@@ -20908,9 +20533,9 @@
"no_NO": "Opphev valg av Vist",
"pl_PL": "",
"pt_BR": "Desmarcar Todos",
- "ru_RU": "Отменить выбор показанного",
+ "ru_RU": "Отменить выбор видимого",
"sv_SE": "Avmarkera visade",
- "th_TH": "",
+ "th_TH": "ยกเลิกการเลือกรายการที่แสดง",
"tr_TR": "",
"uk_UA": "Скасувати вибір показаного",
"zh_CN": "反选显示的",
@@ -20933,9 +20558,9 @@
"no_NO": "Tittel",
"pl_PL": "",
"pt_BR": "Título",
- "ru_RU": "Приложение",
+ "ru_RU": "Название",
"sv_SE": "Titel",
- "th_TH": "",
+ "th_TH": "ชื่อไฟล์",
"tr_TR": "",
"uk_UA": "Назва",
"zh_CN": "标题",
@@ -20954,13 +20579,13 @@
"he_IL": "",
"it_IT": "Spazio risparmiato",
"ja_JP": "",
- "ko_KR": "공간 절약s",
+ "ko_KR": "공간 절약",
"no_NO": "Plassbesparelser",
"pl_PL": "",
"pt_BR": "Economia de Espaço",
- "ru_RU": "Сохранение места на диске",
+ "ru_RU": "Экономия места на диске",
"sv_SE": "Utrymmesbesparning",
- "th_TH": "",
+ "th_TH": "ลดการใช้พื้นที่",
"tr_TR": "",
"uk_UA": "Економія місця",
"zh_CN": "节省空间",
@@ -20985,7 +20610,7 @@
"pt_BR": "Reduzir XCI",
"ru_RU": "Обрезать",
"sv_SE": "Optimera",
- "th_TH": "",
+ "th_TH": "ตัดแต่ง",
"tr_TR": "",
"uk_UA": "Обрізка",
"zh_CN": "瘦身",
@@ -21008,9 +20633,9 @@
"no_NO": "Utrim",
"pl_PL": "",
"pt_BR": "Desfazer Redução",
- "ru_RU": "Отмена обрезки",
+ "ru_RU": "Отменить обрезку",
"sv_SE": "Avoptimera",
- "th_TH": "",
+ "th_TH": "ยกเลิกการตัดแต่ง",
"tr_TR": "",
"uk_UA": "Зшивання",
"zh_CN": "取消精简",
@@ -21029,13 +20654,13 @@
"he_IL": "",
"it_IT": "{0} nuovo/i aggiornamento/i aggiunto/i",
"ja_JP": "",
- "ko_KR": "{0}개의 새 업데이트가 추가됨",
+ "ko_KR": "{0}개의 신규 업데이트가 추가됨",
"no_NO": "{0} ny(e) oppdatering(er) lagt til",
"pl_PL": "",
"pt_BR": "{0} nova(s) atualização(ões) adicionada(s)",
"ru_RU": "Добавлено {0} новых обновлений",
"sv_SE": "{0} nya uppdatering(ar) lades till",
- "th_TH": "{0} อัพเดตที่เพิ่มมาใหม่",
+ "th_TH": "มีอัปเดตใหม่เข้ามา {0} รายการ",
"tr_TR": "",
"uk_UA": "{0} нових оновлень додано",
"zh_CN": "{0} 个更新被添加",
@@ -21058,7 +20683,7 @@
"no_NO": "Medfølgende oppdateringer kan ikke fjernes, bare deaktiveres.",
"pl_PL": "",
"pt_BR": "Atualizações incorporadas não podem ser removidas, apenas desativadas.",
- "ru_RU": "Обновления бандлов не могут быть удалены, только отключены.",
+ "ru_RU": "Встроенные обновления нельзя удалить, только отключить.",
"sv_SE": "Bundlade uppdateringar kan inte tas bort, endast inaktiveras.",
"th_TH": "แพ็คที่อัพเดตมาไม่สามารถลบทิ้งได้ สามารถปิดใช้งานได้เท่านั้น",
"tr_TR": "",
@@ -21104,13 +20729,13 @@
"he_IL": "מזהה בניה:",
"it_IT": "ID Build",
"ja_JP": "ビルドID:",
- "ko_KR": "빌드ID:",
+ "ko_KR": "빌드 ID:",
"no_NO": "VersjonsId:",
"pl_PL": "Identyfikator wersji:",
"pt_BR": "ID da Build:",
"ru_RU": "ID версии:",
"sv_SE": "Bygg-id:",
- "th_TH": "รหัสการสร้าง:",
+ "th_TH": "หมายเลขบิลด์:",
"tr_TR": "",
"uk_UA": "ID збірки:",
"zh_CN": "游戏版本 ID:",
@@ -21125,7 +20750,7 @@
"el_GR": "",
"en_US": "Bundled DLC cannot be removed, only disabled.",
"es_ES": "",
- "fr_FR": "Le DLC inclus ne peut être supprimé, seulement désactivé.",
+ "fr_FR": "Les DLC inclus ne peuvent pas être supprimé, seulement désactivé.",
"he_IL": "",
"it_IT": "I DLC inclusi non possono essere rimossi, ma solo disabilitati.",
"ja_JP": "",
@@ -21133,7 +20758,7 @@
"no_NO": "Medfølgende DLC kan ikke fjernes, bare deaktiveres.",
"pl_PL": "",
"pt_BR": "DLCs incorporadas não podem ser removidas, apenas desativadas.",
- "ru_RU": "DLC бандлов не могут быть удалены, только отключены.",
+ "ru_RU": "Встроенный DLC нельзя удалить, только отключить.",
"sv_SE": "Bundlade DLC kan inte tas bort, endast inaktiveras.",
"th_TH": "แพ็ค DLC ไม่สามารถลบทิ้งได้ สามารถปิดใช้งานได้เท่านั้น",
"tr_TR": "",
@@ -21158,9 +20783,9 @@
"no_NO": "{0} Nedlastbare innhold(er)",
"pl_PL": "",
"pt_BR": "{0} DLC(s) disponíveis",
- "ru_RU": "{0} доступных DLC",
+ "ru_RU": "{0} доступное/ых DLC",
"sv_SE": "{0} DLC(er) tillgängliga",
- "th_TH": "",
+ "th_TH": "มี DLC จำนวน {0} รายการ",
"tr_TR": "",
"uk_UA": "{0} DLC доступно",
"zh_CN": "{0} 个 DLC",
@@ -21183,9 +20808,9 @@
"no_NO": "{0} nytt nedlastbart innhold lagt til",
"pl_PL": "",
"pt_BR": "{0} novo(s) conteúdo(s) para download adicionado(s)",
- "ru_RU": "Добавлено {0} новых DLC",
+ "ru_RU": "Добавлено {0} новое/ых DLC",
"sv_SE": "{0} nya hämtningsbara innehåll lades till",
- "th_TH": "{0} DLC ใหม่ที่เพิ่มเข้ามา",
+ "th_TH": "มีเนื้อหาเสริมใหม่ {0} รายการ",
"tr_TR": "",
"uk_UA": "{0} нового завантажувального вмісту додано",
"zh_CN": "{0} 个 DLC 被添加",
@@ -21208,9 +20833,9 @@
"no_NO": "{0} nytt nedlastbart innhold lagt til",
"pl_PL": "",
"pt_BR": "{0} novo(s) conteúdo(s) para download adicionado(s)",
- "ru_RU": "Добавлено {0} новых DLC",
+ "ru_RU": "Добавлено {0} новое/ых DLC",
"sv_SE": "{0} nya hämtningsbara innehåll lades till",
- "th_TH": "{0} ใหม่ที่เพิ่มเข้ามา",
+ "th_TH": "เพิ่มเนื้อหาเสริมดาวน์โหลดใหม่ {0} รายการ",
"tr_TR": "",
"uk_UA": "{0} нового завантажувального вмісту додано",
"zh_CN": "{0} 个 DLC 被添加",
@@ -21233,9 +20858,9 @@
"no_NO": "{0} manglende nedlastbart innhold fjernet",
"pl_PL": "",
"pt_BR": "{0} conteúdo(s) para download ausente(s) removido(s)",
- "ru_RU": "{0} отсутствующих DLC удалено",
+ "ru_RU": "Убрано {0} отсутствующие/х DLC",
"sv_SE": "{0} saknade hämtningsbara innehåll togs bort",
- "th_TH": "",
+ "th_TH": "ลบเนื้อหาเสริมที่หายไปจำนวน {0} รายการ",
"tr_TR": "",
"uk_UA": "{0} відсутнього завантажувального вмісту видалено",
"zh_CN": "{0} 个失效的 DLC 已移除",
@@ -21254,13 +20879,13 @@
"he_IL": "",
"it_IT": "{0} nuovo/i aggiornamento/i aggiunto/i",
"ja_JP": "",
- "ko_KR": "{0}개의 새 업데이트가 추가됨",
+ "ko_KR": "{0}개의 신규 업데이트가 추가됨",
"no_NO": "{0} ny(e) oppdatering(er) lagt til",
"pl_PL": "",
"pt_BR": "{0} nova(s) atualização(ões) adicionada(s)",
- "ru_RU": "{0} новых обновлений добавлено",
+ "ru_RU": "Добавлено {0} новое/ых обновление/й",
"sv_SE": "{0} nya uppdatering(ar) lades till",
- "th_TH": "{0} อัพเดตใหม่ที่เพิ่มเข้ามา",
+ "th_TH": "เพิ่มการอัปเดตใหม่ {0} รายการ",
"tr_TR": "",
"uk_UA": "{0} нових оновлень додано",
"zh_CN": "{0} 个游戏更新被添加",
@@ -21283,9 +20908,9 @@
"no_NO": "{0} manglende oppdatering(er) fjernet",
"pl_PL": "",
"pt_BR": "{0} atualização(ões) ausente(s) removida(s)",
- "ru_RU": "{0} отсутствующих обновлений удалено",
+ "ru_RU": "Убрано {0} отсутствующие/х обновление/й",
"sv_SE": "{0} saknade uppdatering(ar) togs bort",
- "th_TH": "",
+ "th_TH": "ลบการอัปเดตที่หายไปจำนวน {0} รายการ",
"tr_TR": "",
"uk_UA": "{0} відсутніх оновлень видалено",
"zh_CN": "{0} 个失效的游戏更新已移除",
@@ -21300,7 +20925,7 @@
"el_GR": "",
"en_US": "{0} Mod(s)",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "{0} מוד(ים)",
"it_IT": "{0} mod",
"ja_JP": "",
@@ -21308,7 +20933,7 @@
"no_NO": "{0} Modifikasjoner(s)",
"pl_PL": "{0} Mod(y/ów)",
"pt_BR": "",
- "ru_RU": "Моды для {0} ",
+ "ru_RU": "{0} Мод(а/ов)",
"sv_SE": "{0} modd(ar)",
"th_TH": "{0} ม็อด",
"tr_TR": "{0} Mod(lar)",
@@ -21325,7 +20950,7 @@
"el_GR": "Επεξεργασία Επιλεγμένων",
"en_US": "Edit Selected",
"es_ES": "Editar selección",
- "fr_FR": "Éditer la sélection",
+ "fr_FR": "Éditer la Sélection",
"he_IL": "ערוך נבחר/ים",
"it_IT": "Modifica selezionati",
"ja_JP": "編集",
@@ -21360,7 +20985,7 @@
"pt_BR": "Continuar",
"ru_RU": "Продолжить",
"sv_SE": "Fortsätt",
- "th_TH": "",
+ "th_TH": "ดำเนินการต่อ",
"tr_TR": "",
"uk_UA": "Продовжити",
"zh_CN": "继续",
@@ -21475,7 +21100,7 @@
"el_GR": "Ορισμός Εικόνας Προφίλ",
"en_US": "Set Profile Image",
"es_ES": "Elegir Imagen de Perfil ",
- "fr_FR": "Définir l'image de profil",
+ "fr_FR": "Définir l'Image de Profil",
"he_IL": "הגדר תמונת פרופיל",
"it_IT": "Imposta immagine profilo",
"ja_JP": "プロファイル画像を設定",
@@ -21508,7 +21133,7 @@
"no_NO": "Navn er påkrevd",
"pl_PL": "Nazwa jest wymagana",
"pt_BR": "Nome é obrigatório",
- "ru_RU": "Необходимо ввести никнейм",
+ "ru_RU": "Необходимо ввести имя",
"sv_SE": "Namn krävs",
"th_TH": "จำเป็นต้องระบุชื่อ",
"tr_TR": "İsim gerekli",
@@ -21525,7 +21150,7 @@
"el_GR": "Η εικόνα προφίλ πρέπει να οριστεί",
"en_US": "Profile image must be set",
"es_ES": "Debe establecerse la imagen de perfil",
- "fr_FR": "L'image du profil doit être définie",
+ "fr_FR": "L'Image du Profil doit être définie",
"he_IL": "נדרשת תמונת פרופיל",
"it_IT": "Dev'essere impostata un'immagine profilo",
"ja_JP": "プロファイル画像が必要です",
@@ -21550,7 +21175,7 @@
"el_GR": "{0} Update(s) available for {1} ({2})",
"en_US": "Manage Updates for {0} ({1})",
"es_ES": "Actualizaciones disponibles para {0} [{1}]",
- "fr_FR": "Gérer les mises à jour pour {0} ({1})",
+ "fr_FR": "Gérer les Mises à Jour pour {0} ({1})",
"he_IL": "נהל עדכונים עבור {0} ({1})",
"it_IT": "Gestisci aggiornamenti per {0} ({1})",
"ja_JP": "利用可能なアップデート {0} [{1}]",
@@ -21558,7 +21183,7 @@
"no_NO": "Administrer oppdateringer for {0} ({1})",
"pl_PL": "{0} Aktualizacje dostępne dla {1} ({2})",
"pt_BR": "{0} atualizações disponíveis para {1} ({2})",
- "ru_RU": "Доступные обновления для {0} ({1})",
+ "ru_RU": "Управление обновлениями для {0} ({1})",
"sv_SE": "Hantera uppdateringar för {0} ({1})",
"th_TH": "จัดการอัพเดตสำหรับ {0} ({1})",
"tr_TR": "{0} için güncellemeler mevcut [{1}]",
@@ -21575,7 +21200,7 @@
"el_GR": "Αύξηση της ανάλυσης:",
"en_US": "Increase Resolution:",
"es_ES": "Aumentar la resolución:",
- "fr_FR": "Augmenter la résolution :",
+ "fr_FR": "Augmenter la Résolution :",
"he_IL": "שפר רזולוציה:",
"it_IT": "Aumenta la risoluzione:",
"ja_JP": "解像度を上げる:",
@@ -21600,7 +21225,7 @@
"el_GR": "Μείωση της ανάλυσης:",
"en_US": "Decrease Resolution:",
"es_ES": "Disminuir la resolución:",
- "fr_FR": "Diminuer la résolution :",
+ "fr_FR": "Diminuer la Résolution :",
"he_IL": "הפחת רזולוציה:",
"it_IT": "Riduci la risoluzione:",
"ja_JP": "解像度を下げる:",
@@ -21633,7 +21258,7 @@
"no_NO": "Navn:",
"pl_PL": "Nazwa:",
"pt_BR": "Nome:",
- "ru_RU": "Никнейм:",
+ "ru_RU": "Имя:",
"sv_SE": "Namn:",
"th_TH": "ชื่อ:",
"tr_TR": "İsim:",
@@ -21650,7 +21275,7 @@
"el_GR": "User Id:",
"en_US": "User ID:",
"es_ES": "Id de Usuario:",
- "fr_FR": "Identifiant utilisateur : ",
+ "fr_FR": "Identifiant Utilisateur :",
"he_IL": "מזהה משתמש:",
"it_IT": "ID utente:",
"ja_JP": "ユーザID:",
@@ -21683,7 +21308,7 @@
"no_NO": "Grafikk Backend",
"pl_PL": "Backend Graficzny",
"pt_BR": "Renderizador Gráfico",
- "ru_RU": "Графический бэкенд",
+ "ru_RU": "Графический бэкенд:",
"sv_SE": "Grafikbakände",
"th_TH": "กราฟิกเบื้องหลัง",
"tr_TR": "Grafik Arka Ucu",
@@ -21700,7 +21325,7 @@
"el_GR": "",
"en_US": "Select the graphics backend that will be used in the emulator.\n\nVulkan is overall better for all modern graphics cards, as long as their drivers are up to date. Vulkan also features faster shader compilation (less stuttering) on all GPU vendors.\n\nOpenGL may achieve better results on old Nvidia GPUs, on old AMD GPUs on Linux, or on GPUs with lower VRAM, though shader compilation stutters will be greater.\n\nSet to Vulkan if unsure. Set to OpenGL if your GPU does not support Vulkan even with the latest graphics drivers.",
"es_ES": "Seleccione el backend gráfico que utilizará el emulador.\n\nVulkan, en general, es mejor para todas las tarjetas gráficas modernas, mientras que sus controladores estén actualizados. Vulkan también cuenta con complicación más rápida de sombreadores (menos tirones) en todos los proveredores de GPU.\n\nOpenGL puede lograr mejores resultados en GPU Nvidia antiguas, GPU AMD antiguas en Linux o en GPUs con menor VRAM, aunque tirones de compilación de sombreadores serán mayores.\n\nSetear en Vulkan si no sabe que hacer. Setear en OpenGL si su GPU no tiene soporte para Vulkan aún con los últimos controladores gráficos.",
- "fr_FR": "Sélectionnez le moteur graphique à utiliser dans l’émulateur.\n\nVulkan est généralement préférable pour toutes les cartes graphiques modernes, à condition que leurs pilotes soient à jour. Vulkan offre également une compilation des shaders plus rapide (moins de saccades) chez tous les fabricants de GPU.\n\nOpenGL peut donner de meilleurs résultats sur d’anciennes cartes Nvidia, sur de vieux GPU AMD sous Linux, ou sur des GPU avec moins de mémoire vidéo, mais la compilation des shaders provoquera davantage de saccade\n\nChoisissez Vulkan si vous n’êtes pas sûr. Optez pour OpenGL si votre GPU ne prend pas en charge Vulkan, même avec les derniers pilotes graphiques.",
+ "fr_FR": "Sélectionne le moteur graphique à utiliser dans l’émulateur.\n\nVulkan est généralement préférable pour toutes les cartes graphiques modernes, à condition que leurs pilotes soient à jour. Vulkan offre également une compilation des shaders plus rapide (moins de saccades) chez tous les fabricants de GPU.\n\nOpenGL peut donner de meilleurs résultats sur d’anciennes cartes Nvidia, sur de vieux GPU AMD sous Linux, ou sur des GPU avec moins de mémoire vidéo, mais la compilation des shaders provoquera davantage de saccade\n\nChoisissez Vulkan si vous n’êtes pas sûr. Optez pour OpenGL si votre GPU ne prend pas en charge Vulkan, même avec les derniers pilotes graphiques.",
"he_IL": "",
"it_IT": "Seleziona il backend grafico che verrà utilizzato nell'emulatore.\n\nVulkan è nel complesso migliore per tutte le schede grafiche moderne, a condizione che i relativi driver siano aggiornati. Vulkan dispone anche di una compilazione degli shader più veloce (con minore stuttering) su tutte le marche di GPU.\n\nOpenGL può ottenere risultati migliori su vecchie GPU Nvidia, su vecchie GPU AMD su Linux, o su GPU con poca VRAM, anche se lo stuttering dovuto alla compilazione degli shader sarà maggiore.\n\nNel dubbio, scegli Vulkan. Seleziona OpenGL se la GPU non supporta Vulkan nemmeno con i driver grafici più recenti.",
"ja_JP": "エミュレーションに使用するグラフィックスバックエンドを選択します.\n\nVulkanは, 最近のグラフィックカードでドライバが最新であれば, 全体的に優れています. すべてのGPUベンダーで, シェーダーコンパイルがより高速で, スタッタリングが少ないのが特徴です.\n\n古いNvidia GPU, Linuxでの古いAMD GPU, VRAMの少ないGPUなどでは, OpenGLの方が良い結果が得られるかもしれません. ですが, シェーダーコンパイルのスタッターは大きくなります.\n\n不明な場合はVulkanに設定してください。最新のグラフィックドライバでもVulkanをサポートしていないGPUの場合は, OpenGLに設定してください.",
@@ -21717,56 +21342,6 @@
"zh_TW": "選擇模擬器將使用的圖形後端。\n\n只要驅動程式是最新的,Vulkan 對所有現代顯示卡來說都更好用。Vulkan 還能在所有 GPU 廠商上實現更快的著色器編譯 (減少卡頓)。\n\nOpenGL 在舊式 Nvidia GPU、Linux 上的舊式 AMD GPU 或 VRAM 較低的 GPU 上可能會取得更好的效果,不過著色器編譯的卡頓會更嚴重。\n\n如果不確定,請設定為 Vulkan。如果您的 GPU 使用最新的圖形驅動程式也不支援 Vulkan,請設定為 OpenGL。"
}
},
- {
- "ID": "SettingsTabGraphicsBackendAuto",
- "Translations": {
- "ar_SA": "",
- "de_DE": "",
- "el_GR": "",
- "en_US": "Auto",
- "es_ES": "",
- "fr_FR": "",
- "he_IL": "",
- "it_IT": "Automatico",
- "ja_JP": "",
- "ko_KR": "자동",
- "no_NO": "",
- "pl_PL": "",
- "pt_BR": "Automático",
- "ru_RU": "Авто",
- "sv_SE": "Automatiskt",
- "th_TH": "",
- "tr_TR": "",
- "uk_UA": "Автоматично",
- "zh_CN": "自动",
- "zh_TW": "自動"
- }
- },
- {
- "ID": "SettingsTabGraphicsBackendAutoTooltip",
- "Translations": {
- "ar_SA": "",
- "de_DE": "",
- "el_GR": "",
- "en_US": "Uses Vulkan.\nOn an ARM Mac, and when playing a game that runs well under it, uses the Metal backend.",
- "es_ES": "",
- "fr_FR": "Utilise Vulkan.\nSur un Mac ARM, et lorsqu’un jeu fonctionne bien avec, utilise le moteur Metal.",
- "he_IL": "",
- "it_IT": "Utilizza Vulkan.\nSu un Mac con processore ARM, utilizza il backend Metal nei giochi che funzionano bene con quest'ultimo.",
- "ja_JP": "",
- "ko_KR": "Vulkan을 사용합니다.\nARM 맥에서 해당 플랫폼에서 잘 실행되는 게임을 플레이하는 경우 Metal 후단부를 사용합니다.",
- "no_NO": "Bruker Vulkan \nPå en ARM Mac, og når du spiller et spill som kjører bra under den, bruker du Metal-backend.",
- "pl_PL": "",
- "pt_BR": "Usa Vulkan.\nEm um Mac ARM, e ao jogar um jogo que roda bem nele, usa o renderizador Metal.",
- "ru_RU": "Использует Vulkan.\nНа Mac с ARM процессорами используется Metal, если игра с ним совместима и хорошо работает.",
- "sv_SE": "Använder Vulkan.\nPå en ARM Mac och vid spel som körs bra på den så används Metal-bakänden.",
- "th_TH": "",
- "tr_TR": "",
- "uk_UA": "Використовує Vulkan.\nНа Mac з процесором ARM використовується графічний API Metal, якщо гра під нього оптимізована.",
- "zh_CN": "使用 Vulkan。\n在 ARM Mac 上,当玩在其下运行良好的游戏时,使用 Metal 后端。",
- "zh_TW": "使用Vulkan。\n在 ARM Mac 上,如果遊戲執行性能良好時,則將使用 Metal 後端。"
- }
- },
{
"ID": "SettingsEnableTextureRecompression",
"Translations": {
@@ -21775,7 +21350,7 @@
"el_GR": "Ενεργοποίηση Επανασυμπίεσης Των Texture",
"en_US": "Enable Texture Recompression",
"es_ES": "Activar recompresión de texturas",
- "fr_FR": "Activer la recompression des textures",
+ "fr_FR": "Activer la recompression des Textures",
"he_IL": "אפשר דחיסה מחדש של המרקם",
"it_IT": "Attiva la ricompressione delle texture",
"ja_JP": "テクスチャの再圧縮を有効にする",
@@ -21821,11 +21396,11 @@
"ID": "SettingsTabGraphicsPreferredGpu",
"Translations": {
"ar_SA": "وحدة معالجة الرسوميات المفضلة",
- "de_DE": "Bevorzugte GPU:",
+ "de_DE": "Bevorzugte GPU",
"el_GR": "Προτιμώμενη GPU",
"en_US": "Preferred GPU",
"es_ES": "GPU preferida",
- "fr_FR": "GPU préféré",
+ "fr_FR": "GPU Préféré",
"he_IL": "כרטיס גראפי מועדף",
"it_IT": "GPU preferita",
"ja_JP": "優先使用するGPU",
@@ -21850,7 +21425,7 @@
"el_GR": "Επιλέξτε την κάρτα γραφικών η οποία θα χρησιμοποιηθεί από το Vulkan.\n\nΔεν επηρεάζει το OpenGL.\n\nΔιαλέξτε την GPU που διαθέτει την υπόδειξη \"dGPU\" αν δεν είστε βέβαιοι. Αν δεν υπάρχει κάποιαν, το πειράξετε",
"en_US": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
"es_ES": "Selecciona la tarjeta gráfica que se utilizará con los back-end de gráficos Vulkan.\n\nNo afecta la GPU que utilizará OpenGL.\n\nFije a la GPU marcada como \"dGUP\" ante dudas. Si no hay una, no haga modificaciones.",
- "fr_FR": "Sélectionnez la carte graphique qui sera utilisée avec le moteur graphique Vulkan.\n\nCela n’affecte pas le GPU utilisé par OpenGL.\n\nChoisissez le GPU identifié comme « dGPU » si vous n’êtes pas sûr. S’il n’y en a pas, laissez tel quel.",
+ "fr_FR": "Sélectionne la carte graphique qui sera utilisée avec l'interface graphique Vulkan.\n\nCela ne change pas le GPU qu'OpenGL utilisera.\n\nChoisissez le GPU noté \"dGPU\" si vous n'êtes pas sûr. S'il n'y en a pas, ne pas modifier.",
"he_IL": "בחר את הכרטיס הגראפי שישומש עם הגראפיקה של וולקאן.\n\nדבר זה לא משפיע על הכרטיס הגראפי שישומש עם OpenGL.\n\nמוטב לבחור את ה-GPU המסומן כ-\"dGPU\" אם אינכם בטוחים, אם זו לא אופצייה, אל תשנו דבר.",
"it_IT": "Seleziona la scheda grafica che verrà usata con il backend grafico Vulkan.\n\nL'opzione non modifica la GPU usata da OpenGL.\n\nNel dubbio, seleziona la GPU contrassegnata come \"dGPU\". Se non ce n'è una, lascia intatta questa opzione.",
"ja_JP": "Vulkanグラフィックスバックエンドで使用されるグラフィックスカードを選択します.\n\nOpenGLが使用するGPUには影響しません.\n\n不明な場合は, \"dGPU\" としてフラグが立っているGPUに設定します. ない場合はそのままにします.",
@@ -21875,7 +21450,7 @@
"el_GR": "Απαιτείται Επανεκκίνηση Του Ryujinx",
"en_US": "Ryujinx Restart Required",
"es_ES": "Reinicio de Ryujinx requerido.",
- "fr_FR": "Redémarrage de Ryujinx requis",
+ "fr_FR": "Redémarrage de Ryujinx Requis",
"he_IL": "ריוג'ינקס דורש אתחול מחדש",
"it_IT": "È richiesto un riavvio di Ryujinx",
"ja_JP": "Ryujinx の再起動が必要です",
@@ -21925,7 +21500,7 @@
"el_GR": "Θέλετε να κάνετε επανεκκίνηση τώρα;",
"en_US": "Do you want to restart now?",
"es_ES": "¿Quieres reiniciar ahora?",
- "fr_FR": "\n\nVoulez-vous redémarrer maintenant ?",
+ "fr_FR": "Voulez-vous redémarrer maintenant ?",
"he_IL": "האם ברצונך להפעיל מחדש כעט?",
"it_IT": "Vuoi riavviare ora?",
"ja_JP": "今すぐ再起動しますか?",
@@ -21979,7 +21554,7 @@
"he_IL": "הגבר את עוצמת הקול:",
"it_IT": "Alza il volume:",
"ja_JP": "音量を上げる:",
- "ko_KR": "음량 증가 :",
+ "ko_KR": "소리 크게 :",
"no_NO": "Øk Volum:",
"pl_PL": "Zwiększ Głośność:",
"pt_BR": "Aumentar Volume:",
@@ -22000,11 +21575,11 @@
"el_GR": "Μείωση Έντασης:",
"en_US": "Decrease Volume:",
"es_ES": "Disminuir volumen:",
- "fr_FR": "Diminuer le volume :",
+ "fr_FR": "Diminuer le Volume :",
"he_IL": "הנמך את עוצמת הקול:",
"it_IT": "Abbassa il volume:",
"ja_JP": "音量を下げる:",
- "ko_KR": "음량 감소 :",
+ "ko_KR": "소리 작게 :",
"no_NO": "Reduser Volum:",
"pl_PL": "Zmniejsz Głośność:",
"pt_BR": "Diminuir Volume:",
@@ -22033,7 +21608,7 @@
"no_NO": "Aktiver Makro HLE",
"pl_PL": "Włącz Macro HLE",
"pt_BR": "Habilitar Macro HLE",
- "ru_RU": "Использовать макрос высокоуровневой эмуляции видеоадаптера",
+ "ru_RU": "Включить Macro HLE",
"sv_SE": "Aktivera Macro HLE",
"th_TH": "เปิดใช้งาน มาโคร HLE",
"tr_TR": "Macro HLE'yi Aktifleştir",
@@ -22050,7 +21625,7 @@
"el_GR": "Προσομοίωση του κώδικα GPU Macro .\n\nΒελτιώνει την απόδοση, αλλά μπορεί να προκαλέσει γραφικά προβλήματα σε μερικά παιχνίδια.\n\nΑφήστε ΕΝΕΡΓΟ αν δεν είστε σίγουροι.",
"en_US": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.",
"es_ES": "Emulación alto-nivel del código de Macros de GPU\n\nIncrementa el rendimiento, pero puede causar errores gráficos en algunos juegos.\n\nDeja esta opción activada si no estás seguro.",
- "fr_FR": "Émulation de haut niveau du code de Macro GPU.\n\nAméliore les performances, mais peut causer des artefacts graphiques dans certains jeux.\n\nLaissez ACTIVÉ si vous n'êtes pas sûr.",
+ "fr_FR": "Émulation de haut niveau du code de Macro GPU.\n\nAméliore la performance, mais peut causer des artefacts graphiques dans certains jeux.\n\nLaissez ACTIVÉ si vous n'êtes pas sûr.",
"he_IL": "אמולצייה ברמה גבוהה של כרטיס גראפי עם קוד מקרו.\n\nמשפר את ביצועי היישום אך עלול לגרום לגליצ'ים חזותיים במשחקים מסויימים.\n\nמוטב להשאיר דלוק אם אינך בטוח.",
"it_IT": "Emulazione di alto livello del codice macro della GPU.\n\nMigliora le prestazioni, ma può causare anomalie grafiche in alcuni giochi.\n\nNel dubbio, lascia l'opzione attiva.",
"ja_JP": "GPU マクロコードの高レベルエミュレーションです.\n\nパフォーマンスを向上させますが, 一部のゲームでグラフィックに不具合が発生する可能性があります.\n\nよくわからない場合はオンのままにしてください.",
@@ -22075,7 +21650,7 @@
"el_GR": "Διέλευση Χρωματικού Χώρου",
"en_US": "Color Space Passthrough",
"es_ES": "Paso de espacio de color",
- "fr_FR": "Traversée de l'espace colorimétrique",
+ "fr_FR": "Traversée de l'Espace Colorimétrique",
"he_IL": "שקיפות מרחב צבע",
"it_IT": "Passthrough dello spazio dei colori",
"ja_JP": "色空間をパススルー",
@@ -22083,7 +21658,7 @@
"no_NO": "Fargeromsgjennomgang",
"pl_PL": "Przekazywanie przestrzeni kolorów",
"pt_BR": "Passagem do Espaço de Cores",
- "ru_RU": "Пропускать цветовое пространство",
+ "ru_RU": "Пропуск цветового пространства",
"sv_SE": "Genomströmning av färgrymd",
"th_TH": "ทะลุผ่านพื้นที่สี",
"tr_TR": "Renk Alanı Geçişi",
@@ -22108,7 +21683,7 @@
"no_NO": "Dirigerer Vulkan backenden til å gå gjennom farge informasjonen uten og spesifisere en fargeromsgjennomgang. For brukere med en bred spillvisning kan dette resultere i mer vibrerende farger og få riktig farge.",
"pl_PL": "Nakazuje API Vulkan przekazywać informacje o kolorze bez określania przestrzeni kolorów. Dla użytkowników z wyświetlaczami o szerokim zakresie kolorów może to skutkować bardziej żywymi kolorami, kosztem ich poprawności.",
"pt_BR": "Direciona o renderizador Vulkan para passar informações de cores sem especificar um espaço de cores. Para usuários com telas de ampla gama, isso pode resultar em cores mais vibrantes, ao custo da correção de cores.",
- "ru_RU": "Направляет бэкенд Vulkan на передачу информации о цвете без указания цветового пространства. Для пользователей с экранами с расширенной гаммой данная настройка приводит к получению более ярких цветов за счет снижения корректности цветопередачи.",
+ "ru_RU": "Направляет бэкенд Vulkan передавать цветовую информацию без указания цветового пространства. Для пользователей с экранами с широким цветовым охватом это может привести к более насыщенным цветам, но за счёт потери точности цветопередачи.",
"sv_SE": "Dirigerar Vulkan-bakänden att skicka genom färginformation utan att ange en färgrymd. För användare med breda gamut-skärmar kan detta resultera i mer levande färger på bekostnad av färgkorrekthet.",
"th_TH": "สั่งให้แบ็กเอนด์ Vulkan ส่งผ่านข้อมูลสีโดยไม่ต้องระบุค่าของสี สำหรับผู้ใช้ที่มีการแสดงกระจายตัวของสี อาจส่งผลให้สีสดใสมากขึ้น โดยต้องแลกกับความถูกต้องของสี",
"tr_TR": "Vulkan Backend'ini renk alanı belirtmeden renk bilgisinden geçmeye yönlendirir. Geniş gam ekranlı kullanıcılar için bu, renk doğruluğu pahasına daha canlı renklerle sonuçlanabilir.",
@@ -22125,7 +21700,7 @@
"el_GR": "Έντ.",
"en_US": "Vol",
"es_ES": "Volumen",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "שמע",
"it_IT": "",
"ja_JP": "音量",
@@ -22150,7 +21725,7 @@
"el_GR": "Διαχείριση Των Save",
"en_US": "Manage Saves",
"es_ES": "Administrar mis partidas guardadas",
- "fr_FR": "Gérer les sauvegardes",
+ "fr_FR": "Gérer les Sauvegardes",
"he_IL": "נהל שמורים",
"it_IT": "Gestisci i salvataggi",
"ja_JP": "セーブデータの管理",
@@ -22225,7 +21800,7 @@
"el_GR": "Manage Saves for {0}",
"en_US": "Manage Saves for {0} ({1})",
"es_ES": "Administrar partidas guardadas para {0}",
- "fr_FR": "Gérer les sauvegardes pour {0} ({1})",
+ "fr_FR": "Gérer les Sauvegardes pour {0} ({1})",
"he_IL": "נהל שמורי משחק עבור {0} ({1})",
"it_IT": "Gestisci salvataggi per {0} ({1})",
"ja_JP": "{0} のセーブデータを管理",
@@ -22250,7 +21825,7 @@
"el_GR": "Διαχειριστής Save",
"en_US": "Save Manager",
"es_ES": "Administrador de datos de guardado.",
- "fr_FR": "Gestionnaire de sauvegarde",
+ "fr_FR": "Gestionnaire de Sauvegarde",
"he_IL": "מנהל שמירות",
"it_IT": "Gestione salvataggi",
"ja_JP": "セーブデータマネージャ",
@@ -22258,7 +21833,7 @@
"no_NO": "Lagre behandler",
"pl_PL": "Menedżer Zapisów",
"pt_BR": "Gerenciador de Jogos Salvos",
- "ru_RU": "Менеджер сохранений",
+ "ru_RU": "Управление сохранений",
"sv_SE": "Sparhanterare",
"th_TH": "จัดการบันทึก",
"tr_TR": "Kayıt Yöneticisi",
@@ -22275,7 +21850,7 @@
"el_GR": "Όνομα",
"en_US": "Name",
"es_ES": "Nombre",
- "fr_FR": "Nom\u00A0",
+ "fr_FR": "Nom",
"he_IL": "שם",
"it_IT": "Nome",
"ja_JP": "名称",
@@ -22350,7 +21925,7 @@
"el_GR": "Ανάκτηση Χαμένων Λογαριασμών",
"en_US": "Recover Lost Accounts",
"es_ES": "Recuperar cuentas perdidas",
- "fr_FR": "Récupérer les profils perdus",
+ "fr_FR": "Récupérer les Profils Perdus",
"he_IL": "שחזר חשבון שאבד",
"it_IT": "Recupera account persi",
"ja_JP": "アカウントの復旧",
@@ -22383,7 +21958,7 @@
"no_NO": "Gjenopprett",
"pl_PL": "Odzyskaj",
"pt_BR": "Recuperar",
- "ru_RU": "Восстановление",
+ "ru_RU": "Восстановить",
"sv_SE": "Återskapa",
"th_TH": "กู้คืน",
"tr_TR": "Kurtar",
@@ -22500,7 +22075,7 @@
"el_GR": "Φίλτρο Κλιμάκωσης:",
"en_US": "Scaling Filter:",
"es_ES": "Filtro de escalado:",
- "fr_FR": "Filtre de mise à l'échelle :",
+ "fr_FR": "Filtre de Mise à l'Échelle :",
"he_IL": "מסנן מידת איכות:",
"it_IT": "Filtro di scaling:",
"ja_JP": "スケーリングフィルタ:",
@@ -22525,7 +22100,7 @@
"el_GR": "Choose the scaling filter that will be applied when using resolution scale.\n\nBilinear works well for 3D games and is a safe default option.\n\nNearest is recommended for pixel art games.\n\nFSR 1.0 is merely a sharpening filter, not recommended for use with FXAA or SMAA.\n\nThis option can be changed while a game is running by clicking \"Apply\" below; you can simply move the settings window aside and experiment until you find your preferred look for a game.\n\nLeave on BILINEAR if unsure.",
"en_US": "Choose the scaling filter that will be applied when using resolution scale.\n\nBilinear works well for 3D games and is a safe default option.\n\nNearest is recommended for pixel art games.\n\nFSR 1.0 is merely a sharpening filter, not recommended for use with FXAA or SMAA.\n\nArea scaling is recommended when downscaling resolutions that are larger than the output window. It can be used to achieve a supersampled anti-aliasing effect when downscaling by more than 2x.\n\nThis option can be changed while a game is running by clicking \"Apply\" below; you can simply move the settings window aside and experiment until you find your preferred look for a game.\n\nLeave on BILINEAR if unsure.",
"es_ES": "Elija el filtro de escala que se aplicará al utilizar la escala de resolución.\n\nBilinear funciona bien para juegos 3D y es una opción predeterminada segura.\n\nSe recomienda el bilinear para juegos de pixel art.\n\nFSR 1.0 es simplemente un filtro de afilado, no se recomienda su uso con FXAA o SMAA.\n\nEsta opción se puede cambiar mientras se ejecuta un juego haciendo clic en \"Aplicar\" a continuación; simplemente puedes mover la ventana de configuración a un lado y experimentar hasta que encuentres tu estilo preferido para un juego.\n\nDéjelo en BILINEAR si no está seguro.",
- "fr_FR": "Choisissez le filtre de mise à l'échelle qui sera appliqué lors de l'utilisation de la mise à l'échelle de la résolution.\n\nLe filtre bilinéaire fonctionne bien pour les jeux en 3D et constitue une option par défaut sûre.\n\nLe filtre le plus proche est recommandé pour les jeux de pixel art.\n\nFSR 1.0 est simplement un filtre de netteté, non recommandé pour une utilisation avec FXAA ou SMAA.\n\nCette option peut être modifiée pendant qu'un jeu est en cours d'exécution en cliquant sur \"Appliquer\" ci-dessous ; vous pouvez simplement déplacer la fenêtre des paramètres de côté et expérimenter jusqu'à ce que vous trouviez l'aspect souhaité pour un jeu.\n\nLaissez sur BILINÉAIRE si vous n'êtes pas sûr.",
+ "fr_FR": "Choisis le filtre de mise à l'échelle qui sera appliqué lors de l'utilisation de la mise à l'échelle de la résolution.\n\nLe filtre bilinéaire fonctionne bien pour les jeux en 3D et constitue une option par défaut sûre.\n\nLe filtre le plus proche est recommandé pour les jeux de pixel art.\n\nFSR 1.0 est simplement un filtre de netteté, non recommandé pour une utilisation avec FXAA ou SMAA.\n\nCette option peut être modifiée pendant qu'un jeu est en cours d'exécution en cliquant sur \"Appliquer\" ci-dessous ; vous pouvez simplement déplacer la fenêtre des paramètres de côté et expérimenter jusqu'à ce que vous trouviez l'aspect souhaité pour un jeu.\n\nLaissez sur BILINÉAIRE si vous n'êtes pas sûr.",
"he_IL": "Choose the scaling filter that will be applied when using resolution scale.\n\nBilinear works well for 3D games and is a safe default option.\n\nNearest is recommended for pixel art games.\n\nFSR 1.0 is merely a sharpening filter, not recommended for use with FXAA or SMAA.\n\nThis option can be changed while a game is running by clicking \"Apply\" below; you can simply move the settings window aside and experiment until you find your preferred look for a game.\n\nLeave on BILINEAR if unsure.",
"it_IT": "Scegli il filtro di scaling che verrà applicato quando si utilizza lo scaling della risoluzione.\n\nBilineare funziona bene per i giochi 3D ed è un'opzione predefinita affidabile.\n\nNearest è consigliato per i giochi in pixel art.\n\nFSR 1.0 è solo un filtro di nitidezza, sconsigliato per l'uso con FXAA o SMAA.\n\nLo scaling ad area è consigliato quando si riducono delle risoluzioni che sono più grandi della finestra di output. Può essere usato per ottenere un effetto di anti-aliasing supercampionato quando si riduce di più di 2x.\n\nQuesta opzione può essere modificata mentre un gioco è in esecuzione facendo clic su \"Applica\" qui sotto; puoi semplicemente spostare la finestra delle impostazioni da parte e sperimentare fino a quando non trovi il tuo look preferito per un gioco.\n\nNel dubbio, lascia su Bilineare.",
"ja_JP": "解像度変更時に適用されるスケーリングフィルタを選択します.\n\nBilinearは3Dゲームに適しており, 安全なデフォルトオプションです.\n\nピクセルアートゲームにはNearestを推奨します.\n\nFSR 1.0は単なるシャープニングフィルタであり, FXAAやSMAAとの併用は推奨されません.\n\nこのオプションは, ゲーム実行中に下の「適用」をクリックすることで変更できます. 設定ウィンドウを脇に移動し, ゲームが好みの表示になるように試してみてください.\n\n不明な場合はBilinearのままにしておいてください.",
@@ -22560,7 +22135,7 @@
"pt_BR": "",
"ru_RU": "Билинейная",
"sv_SE": "Bilinjär",
- "th_TH": "",
+ "th_TH": "บิไลเนียร์",
"tr_TR": "",
"uk_UA": "Білінійний (Bilinear)",
"zh_CN": "Bilinear(双线性过滤)",
@@ -22585,7 +22160,7 @@
"pt_BR": "Mais Próximo",
"ru_RU": "Ступенчатая",
"sv_SE": "Närmaste",
- "th_TH": "ใกล้สุด",
+ "th_TH": "นีเรสต์",
"tr_TR": "",
"uk_UA": "Найближчий (Nearest)",
"zh_CN": "Nearest(邻近过滤)",
@@ -22610,7 +22185,7 @@
"pt_BR": null,
"ru_RU": null,
"sv_SE": null,
- "th_TH": null,
+ "th_TH": "FSR (เพิ่มความคมชัดภาพ)",
"tr_TR": null,
"uk_UA": null,
"zh_CN": "FSR(超级分辨率锐画技术)",
@@ -22635,7 +22210,7 @@
"pt_BR": "Área",
"ru_RU": "Зональная",
"sv_SE": "Yta",
- "th_TH": "",
+ "th_TH": "พื้นที่",
"tr_TR": "",
"uk_UA": "Зональна",
"zh_CN": "Area(区域过滤)",
@@ -22650,7 +22225,7 @@
"el_GR": "Επίπεδο",
"en_US": "Level",
"es_ES": "Nivel",
- "fr_FR": "Niveau ",
+ "fr_FR": "Niveau",
"he_IL": "רמה",
"it_IT": "Livello",
"ja_JP": "レベル",
@@ -22675,7 +22250,7 @@
"el_GR": "",
"en_US": "Set FSR 1.0 sharpening level. Higher is sharper.",
"es_ES": "Ajuste el nivel de nitidez FSR 1.0. Mayor es más nítido.",
- "fr_FR": "Définir le niveau de netteté FSR 1.0. Plus la valeur est élevée, plus l'image est nette.",
+ "fr_FR": "Définis le niveau de netteté FSR 1.0. Plus la valeur est élevée, plus l'image est nette.",
"he_IL": "",
"it_IT": "Imposta il livello di nitidezza di FSR 1.0. Valori più alti comportano una maggiore nitidezza.",
"ja_JP": "FSR 1.0のシャープ化レベルを設定します. 高い値ほどシャープになります.",
@@ -22683,7 +22258,7 @@
"no_NO": "Definer FSR 1,0 skarpere nivå. Høyere er skarpere.",
"pl_PL": "Ustaw poziom ostrzeżenia FSR 1.0. Wyższy jest ostrzejszy.",
"pt_BR": "Defina o nível de nitidez do FSR 1.0. Quanto maior, mais nítido.",
- "ru_RU": "Выбор режима работы FSR 1.0. Выше — четче.",
+ "ru_RU": "Выбор режима работы FSR 1.0. Выше — чётче.",
"sv_SE": "Ställ in nivå för FSR 1.0 sharpening. Högre är skarpare.",
"th_TH": "ตั้งค่าระดับความคมชัด FSR 1.0 ยิ่งสูงกว่าจะยิ่งคมชัดกว่า",
"tr_TR": "",
@@ -22710,7 +22285,7 @@
"pt_BR": "SMAA Baixo",
"ru_RU": "SMAA Низкое",
"sv_SE": "SMAA låg",
- "th_TH": "SMAA ต่ำ",
+ "th_TH": "ลดรอยหยัก (SMAA ต่ำ)",
"tr_TR": "Düşük SMAA",
"uk_UA": "SMAA Низький",
"zh_CN": "SMAA 低质量",
@@ -22725,7 +22300,7 @@
"el_GR": " Μεσαίο SMAA",
"en_US": "SMAA Medium",
"es_ES": "SMAA Medio",
- "fr_FR": "SMAA Moyenne",
+ "fr_FR": "SMAA Moyen",
"he_IL": "SMAA בינוני",
"it_IT": "SMAA Medio",
"ja_JP": "",
@@ -22735,7 +22310,7 @@
"pt_BR": "SMAA Médio",
"ru_RU": "SMAA Среднее",
"sv_SE": "SMAA medium",
- "th_TH": "SMAA ปานกลาง",
+ "th_TH": "ลดรอยหยัก (SMAA ปานกลาง)",
"tr_TR": "Orta SMAA",
"uk_UA": "SMAA Середній",
"zh_CN": "SMAA 中质量",
@@ -22750,7 +22325,7 @@
"el_GR": "Υψηλό SMAA",
"en_US": "SMAA High",
"es_ES": "SMAA Alto",
- "fr_FR": "SMAA Élevée",
+ "fr_FR": "SMAA Élevé",
"he_IL": "SMAA גבוהה",
"it_IT": "SMAA Alto",
"ja_JP": "",
@@ -22760,7 +22335,7 @@
"pt_BR": "SMAA Alto",
"ru_RU": "SMAA Высокое",
"sv_SE": "SMAA hög",
- "th_TH": "SMAA สูง",
+ "th_TH": "ลดรอยหยัก (SMAA สูง)",
"tr_TR": "Yüksek SMAA",
"uk_UA": "SMAA Високий",
"zh_CN": "SMAA 高质量",
@@ -22775,7 +22350,7 @@
"el_GR": "Oύλτρα SMAA",
"en_US": "SMAA Ultra",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "SMAA אולטרה",
"it_IT": "",
"ja_JP": "",
@@ -22785,7 +22360,7 @@
"pt_BR": "",
"ru_RU": "SMAA Ультра",
"sv_SE": "SMAA ultra",
- "th_TH": "SMAA สูงมาก",
+ "th_TH": "ลดรอยหยัก (SMAA สูงทาก)",
"tr_TR": "En Yüksek SMAA",
"uk_UA": "SMAA Ультра",
"zh_CN": "SMAA 超高质量",
@@ -22804,7 +22379,7 @@
"he_IL": "ערוך משתמש",
"it_IT": "Modifica utente",
"ja_JP": "ユーザを編集",
- "ko_KR": "사용자 편집",
+ "ko_KR": "아이디 편집",
"no_NO": "Rediger bruker",
"pl_PL": "Edytuj użytkownika",
"pt_BR": "Editar Usuário",
@@ -22829,7 +22404,7 @@
"he_IL": "צור משתמש",
"it_IT": "Crea utente",
"ja_JP": "ユーザを作成",
- "ko_KR": "사용자 만들기",
+ "ko_KR": "아이디 만들기",
"no_NO": "Opprett bruker",
"pl_PL": "Utwórz użytkownika",
"pt_BR": "Criar usuário",
@@ -22950,7 +22525,7 @@
"el_GR": "",
"en_US": "View Changelog",
"es_ES": "",
- "fr_FR": "Voir Changelog",
+ "fr_FR": "Afficher les Changements",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -22958,9 +22533,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "Ver Registro",
- "ru_RU": "",
+ "ru_RU": "Посмотреть список изменений",
"sv_SE": "Visa ändringslogg",
- "th_TH": "ด",
+ "th_TH": "ตรวจสอบการเปลี่ยนแปลงเวอร์ชัน",
"tr_TR": "",
"uk_UA": "Показати список змін",
"zh_CN": "查看更新日志",
@@ -22983,7 +22558,7 @@
"no_NO": "Klikk for å åpne endringsloggen for denne versjonen i din nettleser.",
"pl_PL": "Kliknij, aby otworzyć listę zmian dla tej wersji w domyślnej przeglądarce.",
"pt_BR": "Clique para abrir o relatório de alterações para esta versão no seu navegador padrão.",
- "ru_RU": "Нажмите, чтобы открыть список изменений для этой версии",
+ "ru_RU": "ННажмите, чтобы открыть журнал изменений этой версии в вашем браузере.",
"sv_SE": "Klicka för att öppna ändringsloggen för denna version i din standardwebbläsare.",
"th_TH": "คลิกเพื่อเปิดประวัติการเปลี่ยนแปลงสำหรับเวอร์ชั่นนี้ บนเบราว์เซอร์เริ่มต้นของคุณ",
"tr_TR": "Kullandığınız versiyon için olan değişiklikleri varsayılan tarayıcınızda görmek için tıklayın",
@@ -23050,15 +22625,15 @@
"el_GR": "",
"en_US": "Change LDN multiplayer mode.\n\nLdnMitm will modify local wireless/local play functionality in games to function as if it were LAN, allowing for local, same-network connections with other Ryujinx instances and hacked Nintendo Switch consoles that have the ldn_mitm module installed.\n\nMultiplayer requires all players to be on the same game version (i.e. Super Smash Bros. Ultimate v13.0.1 can't connect to v13.0.0).\n\nLeave DISABLED if unsure.",
"es_ES": "Cambiar modo LDN multijugador.\n\nLdnMitm modificará la funcionalidad local de juego inalámbrico para funcionar como si fuera LAN, permitiendo locales conexiones de la misma red con otras instancias de Ryujinx y consolas hackeadas de Nintendo Switch que tienen instalado el módulo ldn_mitm.\n\nMultijugador requiere que todos los jugadores estén en la misma versión del juego (por ejemplo, Super Smash Bros. Ultimate v13.0.1 no se puede conectar a v13.0.0).\n\nDejar DESACTIVADO si no está seguro.",
- "fr_FR": "Changer le mode multijoueur LDN.\n\nLdnMitm modifiera la fonctionnalité de jeu sans fil local/jeu local dans les jeux pour fonctionner comme s'il s'agissait d'un LAN, permettant des connexions locales sur le même réseau avec d'autres instances de Ryujinx et des consoles Nintendo Switch piratées ayant le module ldn_mitm installé.\n\nLe multijoueur nécessite que tous les joueurs soient sur la même version du jeu (par exemple, Super Smash Bros. Ultimate v13.0.1 ne peut pas se connecter à v13.0.0).\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.",
+ "fr_FR": "Change le mode multijoueur LDN.\n\nLdnMitm modifiera la fonctionnalité de jeu sans fil local/jeu local dans les jeux pour fonctionner comme s'il s'agissait d'un LAN, permettant des connexions locales sur le même réseau avec d'autres instances de Ryujinx et des consoles Nintendo Switch piratées ayant le module ldn_mitm installé.\n\nLe multijoueur nécessite que tous les joueurs soient sur la même version du jeu (par exemple, Super Smash Bros. Ultimate v13.0.1 ne peut pas se connecter à v13.0.0).\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.",
"he_IL": "",
"it_IT": "Cambia la modalità multigiocatore LDN.\n\nLdnMitm modificherà la funzionalità locale wireless/local play nei giochi per funzionare come se fosse in modalità LAN, consentendo connessioni locali sulla stessa rete con altre istanze di Ryujinx e console Nintendo Switch modificate che hanno il modulo ldn_mitm installato.\n\nLa modalità multigiocatore richiede che tutti i giocatori usino la stessa versione del gioco (es. Super Smash Bros. Ultimate v13.0.1 non può connettersi con la v13.0.0).\n\nNel dubbio, lascia l'opzione su Disabilitato.",
"ja_JP": "LDNマルチプレイヤーモードを変更します.\n\nldn_mitmモジュールがインストールされた, 他のRyujinxインスタンスや,ハックされたNintendo Switchコンソールとのローカル/同一ネットワーク接続を可能にします.\n\nマルチプレイでは, すべてのプレイヤーが同じゲームバージョンである必要があります(例:Super Smash Bros. Ultimate v13.0.1はv13.0.0に接続できません).\n\n不明な場合は「無効」のままにしてください.",
- "ko_KR": "LDN 멀티플레이어 모드를 변경합니다.\n\nLdnMitm은 게임의 로컬 무선/로컬 플레이 기능을 LAN처럼 작동하도록 수정하여 다른 Ryujinx 인스턴스나 ldn_mitm 모듈이 설치된 해킹된 Nintendo Switch 콘솔과 로컬, 동일 네트워크 연결이 가능합니다.\n\n멀티플레이어는 모든 플레이어가 동일한 게임 버전을 사용해야 합니다(예: Super Smash Bros. Ultimate v13.0.1은 v13.0.0에 연결할 수 없음).\n\n모르면 비활성화 상태로 두세요.",
+ "ko_KR": "LDN 멀티플레이어 모드를 변경합니다.\n\nLdnMitm은 게임의 로컬 무선/로컬 플레이 기능을 LAN처럼 작동하도록 수정하여 다른 Ryujinx 인스턴스나 ldn_mitm 모듈이 설치된 해킹된 Nintendo Switch 콘솔과 로컬, 동일 네트워크 연결이 가능합니다.\n\n멀티플레이어는 모든 플레이어가 동일한 게임 버전을 사용해야 합니다(예 : 슈퍼 스매시브라더스 얼티밋 v13.0.1은 v13.0.0에 연결할 수 없음).\n\n모르면 비활성화 상태로 두세요.",
"no_NO": "Endre LDN flerspillermodus.\n\nLdnMitm vil endre lokal trådløst/lokal spillfunksjonalitet i spill som skal fungere som om den var LAN, noe som tillater lokal, samme nettverk forbindelser med andre Ryujinx instanser og hacket Nintendo Switch konsoller som har installert ldn_mitm-modulen.\n\nFlerspiller krever at alle spillerne er på samme versjon (dvs. Super Smash Bros. Ultimat v13.0.1 kan ikke koble til v13.0.0).\n\nForlat DEAKTIVERT hvis usikker.",
"pl_PL": "",
"pt_BR": "Alterar o modo multiplayer LDN.\n\nLdnMitm modificará a funcionalidade de jogo sem fio/local nos jogos para funcionar como se fosse LAN, permitindo conexões locais, na mesma rede, com outras instâncias do Ryujinx e consoles Nintendo Switch hackeados que possuem o módulo ldn_mitm instalado.\n\nO multiplayer exige que todos os jogadores estejam na mesma versão do jogo (ex.: Super Smash Bros. Ultimate v13.0.1 não consegue se conectar à v13.0.0).\n\nDeixe DESATIVADO se estiver em dúvida.",
- "ru_RU": "Меняет многопользовательский режим LDN.\n\nLdnMitm модифицирует функциональность локальной беспроводной/игры на одном устройстве в играх, позволяя играть с другими пользователями Ryujinx или взломанными консолями Nintendo Switch с установленным модулем ldn_mitm, находящимися в одной локальной сети друг с другом.\n\nМногопользовательская игра требует наличия у всех игроков одной и той же версии игры (т.е. Super Smash Bros. Ultimate v13.0.1 не может подключиться к v13.0.0).\n\nРекомендуется оставить выключенным.",
+ "ru_RU": "Меняет многопользовательский режим LDN.\n\nLdnMitm модифицирует функциональность локальной беспроводной игры на одном устройстве в играх, позволяя играть с другими пользователями Ryujinx или взломанными консолями Nintendo Switch с установленным модулем ldn_mitm, находящимися в одной локальной сети друг с другом.\n\nМногопользовательская игра требует наличия у всех игроков одной и той же версии игры (т.е. Super Smash Bros. Ultimate v13.0.1 не может подключиться к v13.0.0).\n\nРекомендуется оставить выключенным.",
"sv_SE": "Ändra LDN-flerspelarläge\n\nLdnMitm kommer att ändra lokal funktionalitet för trådlös/lokalt spel att fungera som om det vore ett LAN, vilket ger stöd för anslutningar med local och same-network med andra Ryujinx-instanser och hackade Nintendo Switch-konsoller som har modulen ldn_mitm installerad.\n\nFlerspelare kräver att alla spelare har samma spelversion (t.ex. Super Smash Bros. Ultimate v13.0.1 kan inte ansluta till v13.0.0).\n\nLämna INAKTIVERAD om du är osäker.",
"th_TH": "เปลี่ยนโหมดผู้เล่นหลายคนของ LDN\n\nLdnMitm จะปรับเปลี่ยนฟังก์ชันการเล่นแบบไร้สาย/ภายใน จะให้เกมทำงานเหมือนกับว่าเป็น LAN ช่วยให้สามารถเชื่อมต่อภายในเครือข่ายเดียวกันกับอินสแตนซ์ Ryujinx อื่น ๆ และคอนโซล Nintendo Switch ที่ถูกแฮ็กซึ่งมีโมดูล ldn_mitm ติดตั้งอยู่\n\nผู้เล่นหลายคนต้องการให้ผู้เล่นทุกคนอยู่ในเกมเวอร์ชันเดียวกัน (เช่น Super Smash Bros. Ultimate v13.0.1 ไม่สามารถเชื่อมต่อกับ v13.0.0)\n\nปล่อยให้ปิดการใช้งานหากไม่แน่ใจ",
"tr_TR": "",
@@ -23160,7 +22735,7 @@
"pt_BR": "Desabilitar hospedagem de rede P2P (pode aumentar a latência)",
"ru_RU": "Отключить хостинг P2P-сетей (может увеличить задержку)",
"sv_SE": "Inaktivera P2P-nätverkshosting (kan öka latens)",
- "th_TH": "",
+ "th_TH": "ปิดการโฮสต์เครือข่ายแบบ P2P (อาจเพิ่มความหน่วง)",
"tr_TR": "",
"uk_UA": "Вимкнути хостинг P2P мережі (може збільшити затримку)",
"zh_CN": "禁用 P2P 网络连接 (也许会增加延迟)",
@@ -23175,7 +22750,7 @@
"el_GR": "",
"en_US": "Disable P2P network hosting, peers will proxy through the master server instead of connecting to you directly.",
"es_ES": "Desactivar el hosteo de red P2P, pares se conectarán a través del servidor maestro en lugar de conectarse directamente contigo.",
- "fr_FR": "Désactiver PàP hébergement de réseau, les postes vont proxy avec le serveur principal au lieu de se connecter directement à vous.",
+ "fr_FR": "Désactive PàP hébergement de réseau, les postes vont proxy avec le serveur principal au lieu de se connecter directement à vous.",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -23185,7 +22760,7 @@
"pt_BR": "Desabilite a hospedagem de rede P2P, os pares farão proxy através do servidor mestre em vez de se conectarem a você diretamente.",
"ru_RU": "Отключая хостинг P2P-сетей, пользователи будут проксироваться через главный сервер, а не подключаться к вам напрямую.",
"sv_SE": "Inaktivera P2P-nätverkshosting, motparter kommer skickas genom masterservern isället för att ansluta direkt till dig.",
- "th_TH": "",
+ "th_TH": "ปิดการโฮสต์เครือข่ายแบบ P2P โดยที่ผู้เล่นคนอื่นจะเชื่อมต่อผ่านเซิร์ฟเวอร์กลางแทนที่จะเชื่อมต่อโดยตรงกับคุณ",
"tr_TR": "",
"uk_UA": "Вимкнути хостинг P2P мережі, піри будуть підключатися через майстер-сервер замість прямого з'єднання з вами.",
"zh_CN": "禁用 P2P 网络连接,对方将通过主服务器进行连接,而不是直接连接到您。",
@@ -23210,7 +22785,7 @@
"pt_BR": "Senha de Rede:",
"ru_RU": "Cетевой пароль:",
"sv_SE": "Lösenfras för nätverk:",
- "th_TH": "",
+ "th_TH": "รหัสผ่านสำหรับเครือข่าย:",
"tr_TR": "",
"uk_UA": "Мережевий пароль:",
"zh_CN": "网络密码:",
@@ -23235,7 +22810,7 @@
"pt_BR": "Você só poderá ver jogos hospedados com a mesma senha que você.",
"ru_RU": "Вы сможете видеть только те игры, в которых используется тот же пароль, что и у вас.",
"sv_SE": "Du kommer endast kunna se hostade spel med samma lösenfras som du.",
- "th_TH": "",
+ "th_TH": "คุณจะสามารถเห็นเกมที่โฮสต์โดยใช้รหัสผ่านเครือข่ายเดียวกับคุณเท่านั้น",
"tr_TR": "",
"uk_UA": "Ви зможете бачити лише ті ігри, які мають такий самий пароль, як і у вас.",
"zh_CN": "您只能看到与您使用相同密码的游戏房间。",
@@ -23260,7 +22835,7 @@
"pt_BR": "Insira uma frase-senha no formato Ryujinx-<8 hex chars>. Você só poderá ver jogos hospedados com a mesma frase-senha que você.",
"ru_RU": "Введите пароль в формате Ryujinx-<8 шестнадцатеричных символов>. Вы сможете видеть только те игры, в которых используется тот же пароль, что и у вас.",
"sv_SE": "Ange en lösenfras i formatet Ryujinx-<8 hextecken>. Du kommer endast kunna se hostade spel med samma lösenfras som du.",
- "th_TH": "",
+ "th_TH": "กรุณาใส่รหัสผ่านในรูปแบบ Ryujinx-<8 หลักเลขฐานสิบหก> คุณจะสามารถเห็นเกมที่โฮสต์โดยใช้รหัสผ่านเดียวกับคุณเท่านั้น",
"tr_TR": "",
"uk_UA": "Введіть пароль у форматі Ryujinx-<8 символів>. Ви зможете бачити лише ті ігри, які мають такий самий пароль, як і у вас.",
"zh_CN": "以 Ryujinx-<8个十六进制字符> 的格式输入密码。您只能看到与您使用相同密码的游戏房间。",
@@ -23285,7 +22860,7 @@
"pt_BR": "(público)",
"ru_RU": "(публичный)",
"sv_SE": "(publik)",
- "th_TH": "",
+ "th_TH": "(สาธารณะ)",
"tr_TR": "",
"uk_UA": "(публічний)",
"zh_CN": "(公开的)",
@@ -23308,9 +22883,9 @@
"no_NO": "Generer tilfeldig",
"pl_PL": "",
"pt_BR": "Gerar Aleatório",
- "ru_RU": "Сгенерировать рандомно",
+ "ru_RU": "Сгенерировать рандомный",
"sv_SE": "Generera slumpmässigt",
- "th_TH": "",
+ "th_TH": "สร้างแบบสุ่มขึ้นมา",
"tr_TR": "",
"uk_UA": "Згенерувати випадкову",
"zh_CN": "随机生成",
@@ -23335,7 +22910,7 @@
"pt_BR": "Gera uma nova senha, que pode ser compartilhada com outros jogadores.",
"ru_RU": "Генерирует новый пароль, который можно передать другим игрокам.",
"sv_SE": "Genererar en ny lösenfras som kan delas med andra spelare.",
- "th_TH": "",
+ "th_TH": "สร้างรหัสผ่านใหม่ ซึ่งสามารถแชร์กับผู้เล่นคนอื่นได้",
"tr_TR": "",
"uk_UA": "Генерує новий пароль, яким можна поділитися з іншими гравцями.",
"zh_CN": "生成一个新的密码,可以与其他玩家共享。",
@@ -23360,7 +22935,7 @@
"pt_BR": "Limpar",
"ru_RU": "Очистить",
"sv_SE": "Töm",
- "th_TH": "",
+ "th_TH": "ล้าง",
"tr_TR": "",
"uk_UA": "Очистити",
"zh_CN": "清除",
@@ -23385,7 +22960,7 @@
"pt_BR": "Limpa a senha atual, retornando à rede pública.",
"ru_RU": "Очищает текущий пароль, возвращаясь в публичную сеть.",
"sv_SE": "Tömmer aktuell lösenfras och återgår till det publika nätverket.",
- "th_TH": "",
+ "th_TH": "ลบรหัสผ่านปัจจุบัน เพื่อกลับไปใช้เครือข่ายสาธารณะ",
"tr_TR": "",
"uk_UA": "Очищає поточну пароль, повертаючись до публічної мережі.",
"zh_CN": "清除当前密码,返回公共网络。",
@@ -23400,7 +22975,7 @@
"el_GR": "",
"en_US": "Invalid Passphrase! Must be in the format \"Ryujinx-<8 hex chars>\"",
"es_ES": "Frase de Contraseña Inválida! Debe ser en formato \"Ryujinx-<8 caracteres hexadecimales>\"",
- "fr_FR": "Mot de passe invalide! Il doit être dans le format \"Ryujinx-<8 hex chars>\"",
+ "fr_FR": "Mot de passe invalide ! Il doit être dans le format \"Ryujinx-<8 hex chars>\"",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -23410,7 +22985,7 @@
"pt_BR": "Frase-senha inválida! Deve estar no formato \"Ryujinx-<8 hex chars>\"",
"ru_RU": "Неверный пароль! Пароль должен быть в формате «Ryujinx-<8 шестнадцатеричных символов>»",
"sv_SE": "Ogiltig lösenfras! Måste vara i formatet \"Ryujinx-<8 hextecken>\"",
- "th_TH": "",
+ "th_TH": "รหัสผ่านไม่ถูกต้อง! ต้องอยู่ในรูปแบบ \"Ryujinx-<8 หลักเลขฐานสิบหก>\"",
"tr_TR": "",
"uk_UA": "Невірний пароль! Має бути в форматі \"Ryujinx-<8 символів>\"",
"zh_CN": "无效密码!密码的格式必须是\"Ryujinx-<8个十六进制字符>\"",
@@ -23433,9 +23008,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "Вертикальная синхронизация:",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "วีซิงค์:",
"tr_TR": "",
"uk_UA": "Вертикальна синхронізація (VSync):",
"zh_CN": "垂直同步(VSync)",
@@ -23458,9 +23033,9 @@
"no_NO": "Aktiver egendefinert oppdateringsfrekvens (eksperimentell)",
"pl_PL": "",
"pt_BR": "Habilitar taxa de atualização personalizada (Experimental)",
- "ru_RU": "Включить пользовательскую частоту кадров (Экспериментально)",
+ "ru_RU": "Включить пользовательскую частоту кадров (Экспериментальная функция)",
"sv_SE": "Aktivera anpassad uppdateringsfrekvens (experimentell)",
- "th_TH": "",
+ "th_TH": "เปิดใช้อัตรารีเฟรชแบบกำหนดเอง (ทดลองใช้)",
"tr_TR": "",
"uk_UA": "Увімкнути користувацьку частоту оновлення (Експериментально)",
"zh_CN": "启动自定义刷新率(实验性功能)",
@@ -23475,7 +23050,7 @@
"el_GR": "",
"en_US": "Switch",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -23483,13 +23058,13 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "Консоль",
+ "ru_RU": null,
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "เปลี่ยนโหมด",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
- "zh_TW": ""
+ "zh_TW": null
}
},
{
@@ -23510,7 +23085,7 @@
"pt_BR": "Ilimitado",
"ru_RU": "Без ограничений",
"sv_SE": "Obunden",
- "th_TH": "",
+ "th_TH": "ไม่มีข้อจำกัด",
"tr_TR": "",
"uk_UA": "Необмежена",
"zh_CN": "无限制",
@@ -23535,7 +23110,7 @@
"pt_BR": "Taxa de Atualização Personalizada",
"ru_RU": "Пользовательская частота кадров",
"sv_SE": "Anpassad uppdateringsfrekvens",
- "th_TH": "",
+ "th_TH": "อัตรารีเฟรชแบบกำหนดเอง",
"tr_TR": "",
"uk_UA": "Користувацька",
"zh_CN": "自定义刷新率",
@@ -23558,9 +23133,9 @@
"no_NO": "Emulert vertikal synkronisering. «Switch» emulerer Switchs oppdateringsfrekvens på 60 Hz. «Ubegrenset» er en ubegrenset oppdateringsfrekvens.",
"pl_PL": "",
"pt_BR": "Sincronização vertical emulada. 'Switch' emula a taxa de atualização de 60 Hz do Switch. 'Ilimitada' é uma taxa de atualização sem limite.",
- "ru_RU": "Эмулированная вертикальная синхронизация. «Консоль» эмулирует частоту обновления консоли, равную 60 Гц. «Без ограничений» — неограниченная частота кадров.",
+ "ru_RU": "Эмулированная вертикальная синхронизация (VSync). \"Switch\" эмулирует частоту обновления консоли, равную 60 Гц. \"Без ограничений\" — неограниченная частота кадров.",
"sv_SE": "Emulerad vertikal synk. 'Switch' emulerar Switchens uppdateringsfrekvens på 60Hz. 'Obunden' är en obegränsad uppdateringsfrekvens.",
- "th_TH": "",
+ "th_TH": "การซิงค์ภาพแนวตั้งแบบจำลอง ('Emulated Vertical Sync') 'Switch' จำลองอัตรารีเฟรชของเครื่อง Nintendo Switch ที่ 60Hz 'Unbounded' คืออัตรารีเฟรชที่ไม่จำกัด",
"tr_TR": "",
"uk_UA": "Емульована вертикальна синхронізація кадрів. \"Switch\" емулює частоту оновлення консолі Nintendo Switch (60 Гц). \"Необмежена\" — частота оновлення не матиме обмежень.",
"zh_CN": "模拟垂直同步。“Switch”模拟了 Switch 的 60Hz 刷新率。“无限制”没有刷新率限制。",
@@ -23583,9 +23158,9 @@
"no_NO": "Emulert vertikal synkronisering. «Switch» emulerer Switchs oppdateringsfrekvens på 60 Hz. «Ubegrenset» er en ubegrenset oppdateringsfrekvens. «Egendefinert» emulerer den angitte egendefinerte oppdateringsfrekvensen.",
"pl_PL": "",
"pt_BR": "Sincronização Vertical Emulada. 'Switch' emula a taxa de atualização de 60 Hz do Switch. 'Ilimitada' é uma taxa de atualização sem limite. 'Taxa de atualização personalizada' emula a taxa de atualização personalizada especificada.",
- "ru_RU": "Эмулированная вертикальная синхронизация. «Консоль» эмулирует частоту обновления консоли, равную 60 Гц. «Без ограничений» — неограниченная частота кадров. «Пользовательска частота кадров» эмулирует выбранную пользователем частоту кадров.",
+ "ru_RU": "Эмулированная вертикальная синхронизация (VSync). 'Switch' эмулирует частоту обновления консоли, равную 60 Гц. 'Без ограничений' — неограниченная частота кадров. 'Пользовательска частота кадров' эмулирует выбранную пользователем частоту кадров.",
"sv_SE": "Emulerad vertikal synk. 'Switch' emulerar Switchens uppdateringsfrekvens på 60Hz. 'Obunden' är en obegränsad uppdateringsfrekvens. 'Anpassad uppdateringsfrekvens' emulerar den angivna anpassade uppdateringsfrekvensen.",
- "th_TH": "",
+ "th_TH": "การซิงค์ภาพแนวตั้งแบบจำลอง การซิงค์ภาพแนวตั้งแบบจำลอง 'Unbounded' คืออัตรารีเฟรชที่ไม่จำกัด 'Custom Refresh Rate' จำลองอัตรารีเฟรชแบบกำหนดเองที่ระบุไว้",
"tr_TR": "",
"uk_UA": "Емульована вертикальна синхронізація кадрів. \"Switch\" емулює частоту оновлення консолі Nintendo Switch (60 Гц). \"Необмежена\" — частота оновлення не матиме обмежень. \"Користувацька\" емулює вказану користувачем частоту оновлення.",
"zh_CN": "模拟垂直同步。“Switch”模拟了 Switch 的 60Hz 刷新率。“无限制”没有刷新率限制。“自定义刷新率”模拟指定的自定义刷新率。",
@@ -23610,7 +23185,7 @@
"pt_BR": "Permite que o usuário especifique uma taxa de atualização emulada. Em alguns títulos, isso pode acelerar ou desacelerar a taxa de lógica do jogo. Em outros títulos, pode permitir limitar o FPS em algum múltiplo da taxa de atualização ou levar a um comportamento imprevisível. Este é um recurso experimental, sem garantias de como o jogo será afetado. \n\nDeixe OFF se não tiver certeza.",
"ru_RU": "Позволяет пользователю указать эмулируемую частоту кадров. В некоторых играх это может ускорить или замедлить скорость логики игрового процесса. В других играх это может позволить ограничить FPS на уровне, кратном частоте обновления, или привести к непредсказуемому поведению. Это экспериментальная функция, и нет никаких гарантий того, как она повлияет на игровой процесс. \n\nОставьте выключенным, если не уверены.",
"sv_SE": "Låter användaren ange en emulerad uppdateringsfrekvens. För vissa spel så kan detta snabba upp eller ner frekvensen för spellogiken. I andra spel så kan detta tillåta att bildfrekvensen kapas för delar av uppdateringsfrekvensen eller leda till oväntat beteende. Detta är en experimentell funktion utan några garantier för hur spelet påverkas. \n\nLämna AV om du är osäker.",
- "th_TH": "",
+ "th_TH": "อนุญาตให้ผู้ใช้กำหนดอัตรารีเฟรชแบบจำลองได้ ในบางเกมอาจทำให้เกมทำงานเร็วขึ้นหรือช้าลงตามตรรกะของเกม ในบางเกมอาจช่วยจำกัด FPS ให้อยู่ที่ค่าคูณของอัตรารีเฟรช หรืออาจทำให้เกิดพฤติกรรมที่ไม่คาดคิดได้ ฟีเจอร์นี้ยังเป็นการทดลอง และไม่มีการรับประกันว่าการเล่นเกมจะได้รับผลกระทบอย่างไร\n\nปล่อยปิดไว้ถ้าไม่แน่ใจ",
"tr_TR": "",
"uk_UA": "Дозволяє користувачу вказати емульовану частоту оновлення. У деяких іграх це може прискорити або сповільнити логіку гри. Натомість в інших іграх ця функція може дозволити обмежити FPS на певні кратні частоти оновлення або призвести до непередбачуваної поведінки. Це експериментальна функція, без гарантій того, як вона вплине на ігровий процес. \n\nЗалиште ВИМКНЕНИМ, якщо не впевнені.",
"zh_CN": "允许用户指定模拟刷新率。在某些游戏中,这可能会加快或减慢游戏逻辑的速度。在其他游戏中,它可能允许将 FPS 限制在刷新率的某个倍数,或者导致不可预测的行为。这是一个实验性功能,无法保证游戏会受到怎样的影响。\n\n如果不确定,请关闭。",
@@ -23635,7 +23210,7 @@
"pt_BR": "O valor de meta da taxa de atualização personalizada.",
"ru_RU": "Заданное значение частоты кадров",
"sv_SE": "Målvärde för anpassad uppdateringsfrekvens.",
- "th_TH": "",
+ "th_TH": "ค่าตั้งเป้าอัตรารีเฟรชแบบกำหนดเอง",
"tr_TR": "",
"uk_UA": "Цільове значення користувацької частоти оновлення.",
"zh_CN": "目标自定义刷新率值。",
@@ -23660,7 +23235,7 @@
"pt_BR": "A taxa de atualização personalizada, como uma porcentagem da taxa de atualização normal do Switch.",
"ru_RU": "Пользовательская частота кадров в процентах от обычной частоты обновления на консоли.",
"sv_SE": "Anpassad uppdateringsfrekvens, som en procentdel av den normala uppdateringsfrekvensen för Switch.",
- "th_TH": "",
+ "th_TH": "อัตรารีเฟรชแบบกำหนดเอง ในรูปแบบเปอร์เซ็นต์ของอัตรารีเฟรชปกติของเครื่อง Switch",
"tr_TR": "",
"uk_UA": "Користувацька частота оновлення, як відсоток від стандартної частоти оновлення Switch.",
"zh_CN": "自定义刷新率,占正常SWitch刷新率的百分比值。",
@@ -23675,7 +23250,7 @@
"el_GR": "",
"en_US": "Custom Refresh Rate %:",
"es_ES": "",
- "fr_FR": "% du taux de rafraîchissement personnalisé :",
+ "fr_FR": "% du Taux de Rafraîchissement Personnalisé :",
"he_IL": "",
"it_IT": "Frequenza di aggiornamento personalizzata (%):",
"ja_JP": "",
@@ -23685,7 +23260,7 @@
"pt_BR": "Taxa de Atualização Personalizada %:",
"ru_RU": "Пользовательская частота кадров %:",
"sv_SE": "Anpassad uppdateringsfrekvens %:",
- "th_TH": "",
+ "th_TH": "เปอร์เซ็นต์อัตรารีเฟรชแบบกำหนดเอง:",
"tr_TR": "",
"uk_UA": "Користувацька частота оновлення %:",
"zh_CN": "自定义刷新率值 %:",
@@ -23710,7 +23285,7 @@
"pt_BR": "Valor da Taxa de Atualização Personalizada:",
"ru_RU": "Значение пользовательской частоты кадров:",
"sv_SE": "Värde för anpassad uppdateringsfrekvens:",
- "th_TH": "",
+ "th_TH": "ค่าของอัตรารีเฟรชแบบกำหนดเอง:",
"tr_TR": "",
"uk_UA": "Значення користувацької частоти оновлення:",
"zh_CN": "自定义刷新率值:",
@@ -23735,7 +23310,7 @@
"pt_BR": "Intervalo",
"ru_RU": "Интервал",
"sv_SE": "Intervall",
- "th_TH": "",
+ "th_TH": "ความถี่",
"tr_TR": "",
"uk_UA": "Інтервал",
"zh_CN": "间隔",
@@ -23750,7 +23325,7 @@
"el_GR": "",
"en_US": "Toggle VSync Mode:",
"es_ES": "",
- "fr_FR": "Basculer le mode VSync :",
+ "fr_FR": "Basculer le Mode VSync :",
"he_IL": "",
"it_IT": "Cambia modalità VSync:",
"ja_JP": "",
@@ -23758,9 +23333,9 @@
"no_NO": "Veksle mellom VSync-modus:",
"pl_PL": "",
"pt_BR": "Alternar Modo VSync:",
- "ru_RU": "Выбрать режим вертикальной синхронизации:",
+ "ru_RU": "Переключить VSync:",
"sv_SE": "Växla VSync-läge:",
- "th_TH": "",
+ "th_TH": "สลับโหมด วีซิงค์:",
"tr_TR": "",
"uk_UA": "Перемкнути VSync режим:",
"zh_CN": "设置 VSync 模式:",
@@ -23775,7 +23350,7 @@
"el_GR": "",
"en_US": "Raise Custom Refresh Rate",
"es_ES": "",
- "fr_FR": "Augmenter le taux de rafraîchissement customisé :",
+ "fr_FR": "Augmenter le Taux de Rafraîchissement Customisé :",
"he_IL": "",
"it_IT": "Aumenta la frequenza di aggiornamento personalizzata:",
"ja_JP": "",
@@ -23783,9 +23358,9 @@
"no_NO": "Øk den egendefinerte oppdateringsfrekvensen",
"pl_PL": "",
"pt_BR": "Aumentar Taxa de Atualização:",
- "ru_RU": "Повышение пользовательской частоты кадров",
+ "ru_RU": "Увеличить пользовательскую частоту кадров:",
"sv_SE": "Höj anpassad uppdateringsfrekvens",
- "th_TH": "",
+ "th_TH": "เพิ่มอัตรารีเฟรชแบบกำหนดเอง",
"tr_TR": "",
"uk_UA": "Підвищити користувацьку частоту оновлення",
"zh_CN": "提高自定义刷新率:",
@@ -23800,7 +23375,7 @@
"el_GR": "",
"en_US": "Lower Custom Refresh Rate:",
"es_ES": "",
- "fr_FR": "Baisser le taux de rafraîchissement customisé :",
+ "fr_FR": "Baisser le Taux de Rafraîchissement Customisé :",
"he_IL": "",
"it_IT": "Riduci la frequenza di aggiornamento personalizzata:",
"ja_JP": "",
@@ -23808,9 +23383,9 @@
"no_NO": "Lavere tilpasset oppdateringsfrekvens",
"pl_PL": "",
"pt_BR": "Reduzir Taxa de Atualização:",
- "ru_RU": "Понижение пользовательской частоты кадров",
+ "ru_RU": "Уменьшить пользовательскую частоту кадров:",
"sv_SE": "Sänk anpassad uppdateringsfrekvens",
- "th_TH": "",
+ "th_TH": "ลดอัตรารีเฟรชแบบกำหนดเอง:",
"tr_TR": "",
"uk_UA": "Понизити користувацьку частоту оновлення",
"zh_CN": "降低自定义刷新率:",
@@ -23833,9 +23408,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "Modo Turbo:",
- "ru_RU": "",
+ "ru_RU": "Турбо режим:",
"sv_SE": "Turboläge:",
- "th_TH": "",
+ "th_TH": "โหมดเทอร์โบ:",
"tr_TR": "",
"uk_UA": "Турборежим:",
"zh_CN": "涡轮模式: ",
@@ -23858,9 +23433,9 @@
"no_NO": "Hurtigtasten for turbo-modus.\nKonfigurer oppførselen til turbo-modus i Ryujinx CPU-innstillinger.\n\nLa være ubundet hvis du er usikker.",
"pl_PL": "",
"pt_BR": "Tecla de atalho do Modo Turbo.\nConfigure o comportamento do Modo Turbo nas configurações de CPU do Ryujinx.\n\nDeixe Não Atribuído se não tiver certeza.",
- "ru_RU": "",
+ "ru_RU": "Горячая клавиша режима Турбо.\nНастройте поведение режима Турбо в параметрах 'Процессор' Ryujinx.\n\nРекомендуется оставить НЕ ПРИВЯЗАНО.",
"sv_SE": "Snabbtangenten för turboläge.\nKonfigurera beteendet för turboläge i Ryujinx CPU-inställningar.\n\nLämna Obunden om du är osäker.",
- "th_TH": "",
+ "th_TH": "ปุ่มลัดสำหรับโหมดเทอร์โบ กำหนดพฤติกรรมของโหมดเทอร์โบในการตั้งค่า CPU ของ Ryujinx\n\nปล่อยเป็น “ไม่จำกัด” (Unbound) หากไม่แน่ใจ",
"tr_TR": "",
"uk_UA": "Гаряча клавіша Турборежиму.\nКонфігурацію поведінки турборежиму можна знайти в пункті меню \"Процесор\" в налаштуваннях Ryujinx.\n\nЗалиште неприв'язаною, якщо не впевнені.",
"zh_CN": "涡轮模式热键。\n可以在 Ryujinx CPU 设置中配置涡轮模式的行为。\n\n如果不确定请保留为未绑定。",
@@ -23875,7 +23450,7 @@
"el_GR": "",
"en_US": "Only While Pressed",
"es_ES": "",
- "fr_FR": "Uniquement en appuyant",
+ "fr_FR": "Seulement Quand le Raccourci est Maintenu",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -23883,9 +23458,9 @@
"no_NO": "Bare mens du trykker på",
"pl_PL": "",
"pt_BR": "Somente enquanto pressionado.",
- "ru_RU": "",
+ "ru_RU": "Только при удержании",
"sv_SE": "Endast när du trycker ner",
- "th_TH": "",
+ "th_TH": "ทำงานเฉพาะขณะกดปุ่ม",
"tr_TR": "",
"uk_UA": "Лише під час натискання",
"zh_CN": "仅在按下时",
@@ -23900,7 +23475,7 @@
"el_GR": "",
"en_US": "Last updated: {0}",
"es_ES": "",
- "fr_FR": "Dernière mise à jour : {0}",
+ "fr_FR": "Dernière Mise à Jour : {0}",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -23910,7 +23485,7 @@
"pt_BR": "Última atualização: {0}",
"ru_RU": "Последнее обновление: {0}",
"sv_SE": "Senast uppdaterad: {0}",
- "th_TH": "",
+ "th_TH": "อัปเดตล่าสุด: {0}",
"tr_TR": "",
"uk_UA": "Останнє оновлення: {0}",
"zh_CN": "最后更新于: {0}",
@@ -23935,7 +23510,7 @@
"pt_BR": "Lista de Compatibilidade - {0} registros",
"ru_RU": "Список совместимости — записей: {0}",
"sv_SE": "Kompatibilitetslista - {0} poster",
- "th_TH": "",
+ "th_TH": "รายการความเข้ากันได้ - {0} รายการ",
"tr_TR": "",
"uk_UA": "Список сумісності — {0} ігор",
"zh_CN": "兼容性列表 - {0} 条",
@@ -23958,9 +23533,9 @@
"no_NO": "Denne kompatibilitetslisten kan inneholde oppføringer som er tomme for data.\nVær ikke imot å teste spill i statusen «Ingame».",
"pl_PL": "",
"pt_BR": "Esta lista de compatibilidade pode estar desatualizada.\nNão se oponha a testar os jogos",
- "ru_RU": "В списке совместимости могут содержаться устаревшие записи.\nНе стестняйтесь тестировать игр в статусе «Запускается»",
+ "ru_RU": "В списке совместимости могут содержаться устаревшие записи.\nНе стестняйтесь тестировать игр в статусе \"Запускается\"",
"sv_SE": "Denna kompatibilitetslista kan innehålla utdaterade poster.\nTesta gärna spelen som listas med \"Spelproblem\"-status.",
- "th_TH": "",
+ "th_TH": "รายการความเข้ากันได้นี้อาจมีข้อมูลที่ล้าสมัย\nโปรดอย่าลังเลที่จะทดสอบเกมที่มีสถานะเป็น \"Ingame\"",
"tr_TR": "",
"uk_UA": "Цей список сумісності може містити застарілі дані.\nНе відмовляйтеся від тестування ігор що мають статус \"Запускаються\".",
"zh_CN": "此兼容性列表可能包含过时的条目。\n不要只测试 \"进入游戏\" 状态的游戏。",
@@ -23975,7 +23550,7 @@
"el_GR": "",
"en_US": "Search compatibility entries...",
"es_ES": "",
- "fr_FR": "Rechercher des entrées de compatibilité...",
+ "fr_FR": "Rechercher les entrées de compatibilité...",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -23985,7 +23560,7 @@
"pt_BR": "Pesquisa de compatibilidade",
"ru_RU": "Поиск записей о совместимости...",
"sv_SE": "Sök i kompatibilitetsposter...",
- "th_TH": "",
+ "th_TH": "ค้นหารายการความเข้ากันได้...",
"tr_TR": "",
"uk_UA": "Перевірити сумісність гри...",
"zh_CN": "正在搜索兼容性条目...",
@@ -24000,7 +23575,7 @@
"el_GR": "",
"en_US": "Search {0} compatibility entries...",
"es_ES": "",
- "fr_FR": "Rechercher parmi {0} entrées de compatibilité...",
+ "fr_FR": "Rechercher {0} entrées de compatibilité...",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -24010,7 +23585,7 @@
"pt_BR": "Procurando {0} registros de compatibilidade...",
"ru_RU": "Поиск среди {0} записей о совместимости...",
"sv_SE": "Sök i {0} kompatibilitetsposter...",
- "th_TH": "",
+ "th_TH": "ค้นหารายการความเข้ากันได้ {0} รายการ...",
"tr_TR": "",
"uk_UA": "Шукати серед {0} перевірених ігор...",
"zh_CN": "搜索 {0} 兼容性条目...",
@@ -24033,9 +23608,9 @@
"no_NO": "Åpne kompatibilitetslisten",
"pl_PL": "",
"pt_BR": "Lista de Compatibilidade",
- "ru_RU": "Открыть список совместимости",
+ "ru_RU": "Список совместимости",
"sv_SE": "Öppna kompatibilitetslistan",
- "th_TH": "",
+ "th_TH": "เปิดรายการความเข้ากันได้",
"tr_TR": "",
"uk_UA": "Відкрити Список Сумісності",
"zh_CN": "打开兼容性列表",
@@ -24060,7 +23635,7 @@
"pt_BR": "Jogos e Aplicativos",
"ru_RU": "Игры и Приложения",
"sv_SE": "Spel och applikationer",
- "th_TH": "",
+ "th_TH": "เกมและแอปพลิเคชัน",
"tr_TR": "Oyunlar ve Uygulamalar",
"uk_UA": "Ігри та Додатки",
"zh_CN": "游戏和应用程序",
@@ -24108,9 +23683,9 @@
"no_NO": "Problemer og Egenskaper",
"pl_PL": "Problemy i Cechy",
"pt_BR": "Problemas e Características",
- "ru_RU": "Проблемы и Особенности",
+ "ru_RU": "Проблемы & Особенности",
"sv_SE": "Problem och egenskaper",
- "th_TH": "",
+ "th_TH": "ข้อผิดพลาดและคุณสมบัติ",
"tr_TR": "Sorunlar ve Özellikler",
"uk_UA": "Проблеми та Особливості",
"zh_CN": "问题和特性",
@@ -24118,28 +23693,28 @@
}
},
{
- "ID": "CompatibilityListInfo",
+ "ID": "CompatibilityListStats",
"Translations": {
"ar_SA": "",
"de_DE": "",
- "el_GR": "Πληροφορίες",
- "en_US": "Info",
- "es_ES": "Información",
- "fr_FR": "",
- "he_IL": "מידע",
+ "el_GR": "",
+ "en_US": "Stats",
+ "es_ES": null,
+ "fr_FR": null,
+ "he_IL": "",
"it_IT": "",
- "ja_JP": "情報",
- "ko_KR": "정보",
+ "ja_JP": "",
+ "ko_KR": "",
"no_NO": "",
- "pl_PL": "Informacja",
+ "pl_PL": "",
"pt_BR": "",
- "ru_RU": "Инфо",
+ "ru_RU": "Данные",
"sv_SE": "",
"th_TH": "",
- "tr_TR": "Bilgi",
- "uk_UA": "Інфо",
- "zh_CN": "信息",
- "zh_TW": "資訊"
+ "tr_TR": "",
+ "uk_UA": "",
+ "zh_CN": "",
+ "zh_TW": ""
}
},
{
@@ -24160,7 +23735,7 @@
"pt_BR": "Mostrar apenas jogos disponíveis",
"ru_RU": "Показывать только свои игры",
"sv_SE": "Visa endast ägda spel",
- "th_TH": "",
+ "th_TH": "แสดงเฉพาะเกมที่เป็นเจ้าของ",
"tr_TR": "",
"uk_UA": "Показувати лише ігри в наявності",
"zh_CN": "仅显示拥有的游戏",
@@ -24185,7 +23760,7 @@
"pt_BR": "Jogável",
"ru_RU": "Играбельно",
"sv_SE": "Spelbart",
- "th_TH": "",
+ "th_TH": "สามารถเล่นได้",
"tr_TR": "",
"uk_UA": "Справна",
"zh_CN": "可游玩",
@@ -24210,7 +23785,7 @@
"pt_BR": "No jogo",
"ru_RU": "Запускается",
"sv_SE": "Spelproblem",
- "th_TH": "",
+ "th_TH": "กำลังอยู่ในเกม",
"tr_TR": "",
"uk_UA": "З недоліками",
"zh_CN": "进入游戏",
@@ -24225,7 +23800,7 @@
"el_GR": "",
"en_US": "Menus",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "Menu",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -24235,7 +23810,7 @@
"pt_BR": "Menu",
"ru_RU": "Меню",
"sv_SE": "Menyer",
- "th_TH": "",
+ "th_TH": "เมนู",
"tr_TR": "",
"uk_UA": "Меню",
"zh_CN": "菜单",
@@ -24260,7 +23835,7 @@
"pt_BR": "Inicializa",
"ru_RU": "Стартует",
"sv_SE": "Startar",
- "th_TH": "",
+ "th_TH": "บูต",
"tr_TR": "",
"uk_UA": "Запускається",
"zh_CN": "启动",
@@ -24285,7 +23860,7 @@
"pt_BR": "Nada",
"ru_RU": "Ничего",
"sv_SE": "Ingenting",
- "th_TH": "",
+ "th_TH": "ว่างเปล่า",
"tr_TR": "",
"uk_UA": "Не працює",
"zh_CN": "什么都没有",
@@ -24300,7 +23875,7 @@
"el_GR": "",
"en_US": "Boots and plays without any crashes or GPU bugs of any kind, and at a speed fast enough to reasonably enjoy on an average PC.",
"es_ES": "",
- "fr_FR": "Démarre et fonctionne sans aucun plantage ni bug graphique, à une vitesse suffisante pour être apprécié raisonnablement sur un PC moyen.",
+ "fr_FR": "Démarre et fonctionne aucun crash ou bugs graphiques, et à une vitesse raisonable pour pouvoir en profiter sur un PC ordinaire.",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -24308,9 +23883,9 @@
"no_NO": "Starter opp og spiller uten krasj eller GPU-feil av noe slag, og med en hastighet som er rask nok til å ha rimelig glede av på en gjennomsnittlig PC.",
"pl_PL": "",
"pt_BR": "Inicializa e roda sem travamentos ou bugs de GPU de qualquer tipo, e em uma velocidade rápida o suficiente para ser aproveitado em um PC comum.",
- "ru_RU": "Запускается и работает без любого рода сбоев или графисечких ошибок и на скорости, достаточной для работы на обычном ПК.",
+ "ru_RU": "Запускается и работает без каких-либо сбоев или графических ошибок, а также с достаточной скоростью для комфортной игры на обычном ПК.",
"sv_SE": "Startar upp och spelas utan några krascher eller GPU-fel av några slag och med en hastighet som är snabb nog för bra upplevelse på en genomsnittlig PC.",
- "th_TH": "",
+ "th_TH": "สามารถบูตและเล่นได้โดยไม่มีการแครชหรือบั๊กของ GPU ใด ๆ และมีความเร็วเพียงพอที่จะเล่นได้อย่างสนุกสนานบนพีซีทั่วไป",
"tr_TR": "",
"uk_UA": "Запускається та оптимально працює (без збоїв або графічних багів) на середньостатистичному комп'ютері.",
"zh_CN": "启动和游戏时不会出现任何崩溃或任何类型的 GPU bug 且速度足够快可以在一般 PC 上尽情游玩。",
@@ -24325,7 +23900,7 @@
"el_GR": "",
"en_US": "Boots and goes in-game but suffers from one or more of the following: crashes, deadlocks, GPU bugs, distractingly bad audio, or is simply too slow. Game still might able to be played all the way through, but not as the game is intended to play.",
"es_ES": "",
- "fr_FR": "Démarre et lance le jeu, mais souffre d’un ou plusieurs des problèmes suivants : plantages, blocages, bugs graphiques, audio très désagréable, ou performances trop lentes. Le jeu peut encore être jouable jusqu’au bout, mais pas dans les conditions prévues.",
+ "fr_FR": "Démarre et va en jeux mais souffre d'un ou plusieurs des éléments suivants: crashs, bloacages, bugs graphiques, problèmes audios, ou est trop lent. Le jeu peut toujours être joué jusqu'au bout, mais pas dans des conditions prévues.",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -24333,9 +23908,9 @@
"no_NO": "Starter og går i gang i spillet, men lider av ett eller flere av følgende: krasjer, fastlåser, GPU-feil, distraherende dårlig lyd eller er rett og slett for tregt. Spillet kan fortsatt spilles helt til ende, men ikke slik det er ment å spilles.",
"pl_PL": "",
"pt_BR": "Inicializa e entra no jogo, mas sofre de um ou mais dos seguintes: travamentos, deadlocks, bugs de GPU, áudio ruim que distrai ou é simplesmente muito lento. O jogo ainda pode ser jogado até o fim, mas não da forma como foi criado para ser jogado.",
- "ru_RU": "Запускается и работает, но возникает одна или несколько из следующих проблем: сбои, взаимоблокировки, ошибки GPU, отвлекающие звуки или просто слишком медленная работа. Возможно, игру всё же удастся пройти до конца, но не так, как она задумана.",
+ "ru_RU": "Запускается и входит в игру, но при этом страдает от одного или нескольких из следующих проблем: сбои, зависания, графические ошибки, сильно искажённый звук или слишком низкая скорость. Игра всё ещё может быть пройдена полностью, но не так, как задумано разработчиками.",
"sv_SE": "Startar och går in i spelet men lider av ett eller flera av följande: kraschar, deadlocks, GPU-buggar, distraherande dåligt ljud eller är helt enkelt för långsamt. Spelet kan fortfarande spelas hela vägen igenom, men inte så som spelet är avsett att spelas.",
- "th_TH": "",
+ "th_TH": "สามารถบูตและเข้าเล่นเกมได้ แต่พบปัญหาหนึ่งหรือมากกว่านี้ เช่น แครช, ระบบหยุดทำงาน, บั๊กของ GPU, เสียงแย่จนรบกวน หรือช้าเกินไปเกมอาจยังเล่นจบได้ แต่ไม่สามารถเล่นได้ตามที่เกมตั้งใจไว้",
"tr_TR": "",
"uk_UA": "Запускається, але в грі на вас чекатимуть одна або декілька наступних проблем: збої, зависання, графічні баги, спотворений звук або ж гра загалом працюватиме надто повільно. Можливо, гру все ще можна буде пройти, але досвід буде не найкращим.",
"zh_CN": "可以成功启动并进入游戏但可能会遇到以下一种或多种问题: 崩溃、卡死、GPU bug、令人无法接受的音频,或者只是太慢。仍然可以继续进行游戏,但是可能无法达到预期。",
@@ -24350,7 +23925,7 @@
"el_GR": "",
"en_US": "Boots and goes past the title screen but does not make it into main gameplay.",
"es_ES": "",
- "fr_FR": "Démarre et dépasse l’écran titre, mais n’atteint pas le gameplay principal.",
+ "fr_FR": "Démarre et dépasse l'écran titre, mais n'arrive pas au gameplay principal.",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -24358,9 +23933,9 @@
"no_NO": "Starter opp og går forbi tittelskjermen, men kommer ikke inn i hovedspillet.",
"pl_PL": "",
"pt_BR": "Inicializa e passa da tela de título, mas não entra no jogo principal.",
- "ru_RU": "Загружается титульный экран и можно перейти дальше, но сама игра не работает.",
+ "ru_RU": "Запускается и проходит экран заголовки, но не переходит к основному игровому процессу.",
"sv_SE": "Startar upp och går förbi titelskärmen men tar sig inte in i huvudspelet.",
- "th_TH": "",
+ "th_TH": "สามารถบูตและผ่านหน้าจอชื่อเกมได้ แต่ไม่สามารถเข้าสู่การเล่นเกมหลักได้",
"tr_TR": "",
"uk_UA": "Запускається та проходить початковий екран, проте зіграти у вас не вийде.",
"zh_CN": "可以启动并通过标题画面但是无法进入到主要的游戏流程。",
@@ -24375,7 +23950,7 @@
"el_GR": "",
"en_US": "Boots but does not make it past the title screen.",
"es_ES": "",
- "fr_FR": "Démarre mais ne dépasse pas l’écran titre.",
+ "fr_FR": "Démarre mais ne dépasse pas l'écran titre.",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -24383,9 +23958,9 @@
"no_NO": "Starter, men kommer ikke lenger enn til tittelskjermen.",
"pl_PL": "",
"pt_BR": "Inizializa, mas não passa da tela de título.",
- "ru_RU": "Загружается, но не проходит дальше титульного экрана.",
+ "ru_RU": "Запускается, но не выходит за пределы экрана заголовки.",
"sv_SE": "Startar upp men tar sig inte förbi titelskärmen.",
- "th_TH": "",
+ "th_TH": "บูตได้แต่ไม่ผ่านหน้าจอชื่อเกม",
"tr_TR": "",
"uk_UA": "Запускається, але не відображає навіть початкового екрану.",
"zh_CN": "可以启动但是无法通过标题画面。",
@@ -24400,7 +23975,7 @@
"el_GR": "",
"en_US": "Does not boot or shows no signs of activity.",
"es_ES": "",
- "fr_FR": "Ne démarre pas et ne montre aucun signe d’activité.",
+ "fr_FR": "Ne démarre pas ou ne montre aucun signe d'activité.",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -24408,9 +23983,9 @@
"no_NO": "Starter ikke opp eller viser ingen tegn til aktivitet.",
"pl_PL": "",
"pt_BR": "Não inicializa ou não mostra sinais de atividade.",
- "ru_RU": "Не запускается или не подаёт признаков жизни.",
+ "ru_RU": "Не запускается или не проявляет никаких признаков активности.",
"sv_SE": "Startar inte upp eller visar någon form av aktivitet.",
- "th_TH": "",
+ "th_TH": "ไม่สามารถบูตได้หรือไม่มีสัญญาณการทำงานใด ๆ",
"tr_TR": "",
"uk_UA": "Взагалі не запускається.",
"zh_CN": "无法启动或显示无任何动静。",
@@ -24425,7 +24000,7 @@
"el_GR": "",
"en_US": "Custom Config",
"es_ES": "",
- "fr_FR": "Configuration personnalisée",
+ "fr_FR": "Configuration Personnalisée",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -24433,9 +24008,9 @@
"no_NO": "Tilpasset konfigurasjon",
"pl_PL": "",
"pt_BR": "Configurações Customizadas",
- "ru_RU": "Индивидуальные параметры",
+ "ru_RU": "Индивидуальная конфигурация",
"sv_SE": "Anpassad konfiguration",
- "th_TH": "",
+ "th_TH": "การตั้งค่าแบบกำหนดเอง",
"tr_TR": "",
"uk_UA": "Власна конфігурація",
"zh_CN": "自定义配置",
@@ -24450,7 +24025,7 @@
"el_GR": "",
"en_US": "(Global)",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": null,
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -24458,9 +24033,9 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "(Глобальный)",
+ "ru_RU": "(Глобальная)",
"sv_SE": "",
- "th_TH": "",
+ "th_TH": "(ทั่วทั้งระบบ)",
"tr_TR": "",
"uk_UA": "(Глобальні)",
"zh_CN": "(全局)",
@@ -24475,7 +24050,7 @@
"el_GR": "",
"en_US": "Select a DLC to Extract",
"es_ES": "",
- "fr_FR": "Choisissez un DLC à extraire",
+ "fr_FR": "Choisissez un DLC à Extraire",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -24485,7 +24060,7 @@
"pt_BR": "Selecione um DLC para Extrair",
"ru_RU": "Выберите DLC для извлечения",
"sv_SE": "Välj en DLC att extrahera",
- "th_TH": "",
+ "th_TH": "เลือก DLC สำหรับการแยกไฟล์",
"tr_TR": "",
"uk_UA": "Оберіть DLC які бажаєте вилучити",
"zh_CN": "选择一个要解压的 DLC",
@@ -24510,7 +24085,7 @@
"pt_BR": "Imagem da Presença do Discord",
"ru_RU": "Изображение для статуса активности",
"sv_SE": "Bild för Rich Presence",
- "th_TH": "",
+ "th_TH": "ภาพสถานะ Rich Presence",
"tr_TR": "",
"uk_UA": "Зображення картки активності Discord",
"zh_CN": "Rich Presence 图像",
@@ -24535,12 +24110,212 @@
"pt_BR": "Presença Dinâmica do Discord",
"ru_RU": "Динамический статус активности",
"sv_SE": "Dynamisk Rich Presence",
- "th_TH": "",
+ "th_TH": "สถานะ Rich Presence แบบไดนามิก",
"tr_TR": "",
"uk_UA": "Динамічна картка активності Discord",
"zh_CN": "动态 Rich Presence",
"zh_TW": "動態 Rich Presence"
}
+ },
+ {
+ "ID": "SettingsTabDebug",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Debug",
+ "es_ES": "",
+ "fr_FR": null,
+ "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": "SettingsTabDebugTitle",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Debug",
+ "es_ES": "",
+ "fr_FR": null,
+ "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": "SettingsTabDebugNote",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "WARNING: For developer use only, will reduce performance",
+ "es_ES": "",
+ "fr_FR": "ATTENTION: Uniquement pour les développeurs, réduit la performance",
+ "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": "SettingsTabDebugEnableGDBStub",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Enable GDB Stub",
+ "es_ES": "",
+ "fr_FR": "Activer GDB Stub",
+ "he_IL": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "GDB Stub 활성화",
+ "no_NO": "",
+ "pl_PL": "",
+ "pt_BR": "",
+ "ru_RU": "Включить GDB-Отладчик",
+ "sv_SE": "",
+ "th_TH": "",
+ "tr_TR": "",
+ "uk_UA": "",
+ "zh_CN": "开启 GDB Stub",
+ "zh_TW": ""
+ }
+ },
+ {
+ "ID": "SettingsTabDebugGDBStubToggleTooltip",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Enables the GDB stub which makes it possible to debug the running application. For development use only!",
+ "es_ES": "",
+ "fr_FR": "Active le GDB stub, ce qui rend le débogage de l'application possible. Pour les développeurs uniquement !",
+ "he_IL": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "GDB Stub을 활성화하여 실행 중인 응용 프로그램을 디버그할 수 있도록 합니다. 개발 용도로만 사용하십시오!",
+ "no_NO": "",
+ "pl_PL": "",
+ "pt_BR": "",
+ "ru_RU": "Активирует GDB-заглушку, позволяя выполнять отладку работающего приложения. Использовать только для разработки!",
+ "sv_SE": "",
+ "th_TH": "",
+ "tr_TR": "",
+ "uk_UA": "",
+ "zh_CN": "启用 GDB stub 使得可以调试正在运行的应用程序。仅限开发用途!",
+ "zh_TW": ""
+ }
+ },
+ {
+ "ID": "SettingsTabDebugGDBStubPort",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "GDB Stub Port:",
+ "es_ES": "",
+ "fr_FR": "Port du GDB Stub :",
+ "he_IL": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "GDB Stub 포트 :",
+ "no_NO": "",
+ "pl_PL": "",
+ "pt_BR": "",
+ "ru_RU": "Порт GDB-Заглушки:",
+ "sv_SE": "",
+ "th_TH": "",
+ "tr_TR": "",
+ "uk_UA": "",
+ "zh_CN": "GDB Stub 端口:",
+ "zh_TW": ""
+ }
+ },
+ {
+ "ID": "SettingsTabDebugSuspendOnStart",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Suspend Application on Start",
+ "es_ES": "",
+ "fr_FR": "Mettre en Pause l'Application au Démarrage",
+ "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": "SettingsTabDebugSuspendOnStartTooltip",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Suspends the application before executing the first instruction, allowing for debugging from the earliest point.",
+ "es_ES": "",
+ "fr_FR": "Met en pause l'application avant d'éxécuter la première instruction, permet de déboger au plus tôt que possible.",
+ "he_IL": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "1번째 명령어를 실행하기 전에 앱앱을 일시 중지하여 가장 초기의 단계에서 디버깅을 가능하게 합니다.",
+ "no_NO": "",
+ "pl_PL": "",
+ "pt_BR": "",
+ "ru_RU": "Приостанавливает приложения до выполнения первой инструкции, позволяя начать отладку с самого раннего этапа.",
+ "sv_SE": "",
+ "th_TH": "",
+ "tr_TR": "",
+ "uk_UA": "",
+ "zh_CN": "在执行首条指令前挂起应用程序,这样就可以从最早的点开始调试。",
+ "zh_TW": ""
+ }
}
]
-}
\ No newline at end of file
+}
diff --git a/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs b/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs
index f67668da4..d0871b29f 100644
--- a/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs
+++ b/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs
@@ -143,6 +143,12 @@ namespace ARMeilleure.Instructions
public static void EmitCall(ArmEmitterContext context, ulong immediate)
{
+ if (context.IsSingleStep)
+ {
+ context.Return(Const(immediate));
+ return;
+ }
+
bool isRecursive = immediate == context.EntryAddress;
if (isRecursive)
@@ -157,12 +163,24 @@ namespace ARMeilleure.Instructions
public static void EmitVirtualCall(ArmEmitterContext context, Operand target)
{
- EmitTableBranch(context, target, isJump: false);
+ if (context.IsSingleStep)
+ {
+ if (target.Type == OperandType.I32)
+ {
+ target = context.ZeroExtend32(OperandType.I64, target);
+ }
+
+ context.Return(target);
+ }
+ else
+ {
+ EmitTableBranch(context, target, isJump: false);
+ }
}
public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn)
{
- if (isReturn)
+ if (isReturn || context.IsSingleStep)
{
if (target.Type == OperandType.I32)
{
diff --git a/src/ARMeilleure/Instructions/NativeInterface.cs b/src/ARMeilleure/Instructions/NativeInterface.cs
index b4922629b..d43e20d83 100644
--- a/src/ARMeilleure/Instructions/NativeInterface.cs
+++ b/src/ARMeilleure/Instructions/NativeInterface.cs
@@ -3,6 +3,7 @@ using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using System.Runtime.InteropServices;
+using ExecutionContext = ARMeilleure.State.ExecutionContext;
namespace ARMeilleure.Instructions
{
@@ -200,7 +201,11 @@ namespace ARMeilleure.Instructions
ExecutionContext context = GetContext();
- context.CheckInterrupt();
+ // If debugging, we'll handle interrupts outside
+ if (!Optimizations.EnableDebugging)
+ {
+ context.CheckInterrupt();
+ }
Statistics.ResumeTimer();
diff --git a/src/ARMeilleure/Optimizations.cs b/src/ARMeilleure/Optimizations.cs
index 18390de31..6dd7befe7 100644
--- a/src/ARMeilleure/Optimizations.cs
+++ b/src/ARMeilleure/Optimizations.cs
@@ -12,6 +12,7 @@ namespace ARMeilleure
public static bool AllowLcqInFunctionTable { get; set; } = true;
public static bool UseUnmanagedDispatchLoop { get; set; } = true;
+ public static bool EnableDebugging { get; set; } = false;
public static bool UseAdvSimdIfAvailable { get; set; } = true;
public static bool UseArm64AesIfAvailable { get; set; } = true;
diff --git a/src/ARMeilleure/State/ExecutionContext.cs b/src/ARMeilleure/State/ExecutionContext.cs
index 223e59d79..fa1a4a032 100644
--- a/src/ARMeilleure/State/ExecutionContext.cs
+++ b/src/ARMeilleure/State/ExecutionContext.cs
@@ -1,4 +1,5 @@
using ARMeilleure.Memory;
+using System.Threading;
namespace ARMeilleure.State
{
@@ -10,7 +11,7 @@ namespace ARMeilleure.State
internal nint NativeContextPtr => _nativeContext.BasePtr;
- private bool _interrupted;
+ internal bool Interrupted { get; private set; }
private readonly ICounter _counter;
@@ -65,6 +66,8 @@ namespace ARMeilleure.State
public bool IsAarch32 { get; set; }
+ public ulong ThreadUid { get; set; }
+
internal ExecutionMode ExecutionMode
{
get
@@ -90,14 +93,19 @@ namespace ARMeilleure.State
private readonly ExceptionCallbackNoArgs _interruptCallback;
private readonly ExceptionCallback _breakCallback;
+ private readonly ExceptionCallbackNoArgs _stepCallback;
private readonly ExceptionCallback _supervisorCallback;
private readonly ExceptionCallback _undefinedCallback;
+ internal int ShouldStep;
+ public ulong DebugPc { get; set; }
+
public ExecutionContext(
IJitMemoryAllocator allocator,
ICounter counter,
ExceptionCallbackNoArgs interruptCallback = null,
ExceptionCallback breakCallback = null,
+ ExceptionCallbackNoArgs stepCallback = null,
ExceptionCallback supervisorCallback = null,
ExceptionCallback undefinedCallback = null)
{
@@ -105,6 +113,7 @@ namespace ARMeilleure.State
_counter = counter;
_interruptCallback = interruptCallback;
_breakCallback = breakCallback;
+ _stepCallback = stepCallback;
_supervisorCallback = supervisorCallback;
_undefinedCallback = undefinedCallback;
@@ -127,9 +136,9 @@ namespace ARMeilleure.State
internal void CheckInterrupt()
{
- if (_interrupted)
+ if (Interrupted)
{
- _interrupted = false;
+ Interrupted = false;
_interruptCallback?.Invoke(this);
}
@@ -139,16 +148,37 @@ namespace ARMeilleure.State
public void RequestInterrupt()
{
- _interrupted = true;
+ Interrupted = true;
+ }
+
+ public void StepHandler()
+ {
+ _stepCallback?.Invoke(this);
+ }
+
+ public void RequestDebugStep()
+ {
+ Interlocked.Exchange(ref ShouldStep, 1);
+ RequestInterrupt();
}
internal void OnBreak(ulong address, int imm)
{
+ if (Optimizations.EnableDebugging)
+ {
+ DebugPc = Pc;
+ }
+
_breakCallback?.Invoke(this, address, imm);
}
internal void OnSupervisorCall(ulong address, int imm)
{
+ if (Optimizations.EnableDebugging)
+ {
+ DebugPc = Pc;
+ }
+
_supervisorCallback?.Invoke(this, address, imm);
}
diff --git a/src/ARMeilleure/State/NativeContext.cs b/src/ARMeilleure/State/NativeContext.cs
index c90e522a9..a9f1c3dab 100644
--- a/src/ARMeilleure/State/NativeContext.cs
+++ b/src/ARMeilleure/State/NativeContext.cs
@@ -22,6 +22,12 @@ namespace ARMeilleure.State
public ulong ExclusiveValueHigh;
public int Running;
public long Tpidr2El0;
+
+ ///
+ /// Precise PC value used for debugging.
+ /// This will only be set when Optimizations.EnableDebugging is true.
+ ///
+ public ulong DebugPrecisePc;
}
private static NativeCtxStorage _dummyStorage = new();
@@ -39,6 +45,11 @@ namespace ARMeilleure.State
public ulong GetPc()
{
+ if (Optimizations.EnableDebugging)
+ {
+ return GetStorage().DebugPrecisePc;
+ }
+
// TODO: More precise tracking of PC value.
return GetStorage().DispatchAddress;
}
@@ -268,6 +279,11 @@ namespace ARMeilleure.State
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running);
}
+ public static int GetDebugPrecisePcOffset()
+ {
+ return StorageOffset(ref _dummyStorage, ref _dummyStorage.DebugPrecisePc);
+ }
+
private static int StorageOffset(ref NativeCtxStorage storage, ref T target)
{
return (int)Unsafe.ByteOffset(ref Unsafe.As(ref storage), ref target);
diff --git a/src/ARMeilleure/Translation/ArmEmitterContext.cs b/src/ARMeilleure/Translation/ArmEmitterContext.cs
index 196120e92..85c3e6c50 100644
--- a/src/ARMeilleure/Translation/ArmEmitterContext.cs
+++ b/src/ARMeilleure/Translation/ArmEmitterContext.cs
@@ -52,6 +52,7 @@ namespace ARMeilleure.Translation
public bool HighCq { get; }
public bool HasPtc { get; }
public Aarch32Mode Mode { get; }
+ public bool IsSingleStep { get; }
private int _ifThenBlockStateIndex = 0;
private Condition[] _ifThenBlockState = [];
@@ -66,7 +67,8 @@ namespace ARMeilleure.Translation
ulong entryAddress,
bool highCq,
bool hasPtc,
- Aarch32Mode mode)
+ Aarch32Mode mode,
+ bool isSingleStep)
{
Memory = memory;
CountTable = countTable;
@@ -76,6 +78,7 @@ namespace ARMeilleure.Translation
HighCq = highCq;
HasPtc = hasPtc;
Mode = mode;
+ IsSingleStep = isSingleStep;
_labels = new Dictionary();
}
diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs
index f36d4256d..c69ebcadb 100644
--- a/src/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/src/ARMeilleure/Translation/PTC/Ptc.cs
@@ -33,7 +33,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";
- private const uint InternalVersion = 7008; //! To be incremented manually for each change to the ARMeilleure project.
+ private const uint InternalVersion = 7009; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";
@@ -303,6 +303,13 @@ namespace ARMeilleure.Translation.PTC
return false;
}
+ if (outerHeader.DebuggerMode != Optimizations.EnableDebugging)
+ {
+ InvalidateCompressedStream(compressedStream);
+
+ return false;
+ }
+
nint intPtr = nint.Zero;
try
@@ -479,6 +486,7 @@ namespace ARMeilleure.Translation.PTC
MemoryManagerMode = GetMemoryManagerMode(),
OSPlatform = GetOSPlatform(),
Architecture = (uint)RuntimeInformation.ProcessArchitecture,
+ DebuggerMode = Optimizations.EnableDebugging,
UncompressedStreamSize =
(long)Unsafe.SizeOf() +
@@ -1068,7 +1076,7 @@ namespace ARMeilleure.Translation.PTC
return osPlatform;
}
- [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 86*/)]
+ [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 87*/)]
private struct OuterHeader
{
public ulong Magic;
@@ -1080,6 +1088,7 @@ namespace ARMeilleure.Translation.PTC
public byte MemoryManagerMode;
public uint OSPlatform;
public uint Architecture;
+ public bool DebuggerMode;
public long UncompressedStreamSize;
diff --git a/src/ARMeilleure/Translation/Translator.cs b/src/ARMeilleure/Translation/Translator.cs
index d8528cfd6..073b7ffe2 100644
--- a/src/ARMeilleure/Translation/Translator.cs
+++ b/src/ARMeilleure/Translation/Translator.cs
@@ -119,7 +119,25 @@ namespace ARMeilleure.Translation
NativeInterface.RegisterThread(context, Memory, this);
- if (Optimizations.UseUnmanagedDispatchLoop)
+ if (Optimizations.EnableDebugging)
+ {
+ context.DebugPc = address;
+ do
+ {
+ if (Interlocked.CompareExchange(ref context.ShouldStep, 0, 1) == 1)
+ {
+ context.DebugPc = Step(context, context.DebugPc);
+ context.StepHandler();
+ }
+ else
+ {
+ context.DebugPc = ExecuteSingle(context, context.DebugPc);
+ }
+ context.CheckInterrupt();
+ }
+ while (context.Running && context.DebugPc != 0);
+ }
+ else if (Optimizations.UseUnmanagedDispatchLoop)
{
Stubs.DispatchLoop(context.NativeContextPtr, address);
}
@@ -175,7 +193,7 @@ namespace ARMeilleure.Translation
return nextAddr;
}
- public ulong Step(State.ExecutionContext context, ulong address)
+ private ulong Step(State.ExecutionContext context, ulong address)
{
TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true);
@@ -186,6 +204,8 @@ namespace ARMeilleure.Translation
return address;
}
+
+
internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
{
if (!Functions.TryGetValue(address, out TranslatedFunction func))
@@ -229,7 +249,8 @@ namespace ARMeilleure.Translation
address,
highCq,
_ptc.State != PtcState.Disabled,
- mode: Aarch32Mode.User);
+ mode: Aarch32Mode.User,
+ isSingleStep: singleStep);
Logger.StartPass(PassName.Decoding);
@@ -367,9 +388,13 @@ namespace ARMeilleure.Translation
if (block.Exit)
{
- // Left option here as it may be useful if we need to return to managed rather than tail call in
- // future. (eg. for debug)
- bool useReturns = false;
+ // Return to managed rather than tail call.
+ bool useReturns = Optimizations.EnableDebugging;
+
+ if (Optimizations.EnableDebugging)
+ {
+ EmitDebugPrecisePcUpdate(context, block.Address);
+ }
InstEmitFlowHelper.EmitVirtualJump(context, Const(block.Address), isReturn: useReturns);
}
@@ -393,6 +418,11 @@ namespace ARMeilleure.Translation
}
}
+ if (Optimizations.EnableDebugging)
+ {
+ EmitDebugPrecisePcUpdate(context, opCode.Address);
+ }
+
Operand lblPredicateSkip = default;
if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al)
@@ -489,6 +519,14 @@ namespace ARMeilleure.Translation
context.MarkLabel(lblExit);
}
+ internal static void EmitDebugPrecisePcUpdate(EmitterContext context, ulong address)
+ {
+ long debugPrecisePcOffs = NativeContext.GetDebugPrecisePcOffset();
+
+ Operand debugPrecisePcAddr = context.Add(context.LoadArgument(OperandType.I64, 0), Const(debugPrecisePcOffs));
+ context.Store(debugPrecisePcAddr, Const(address));
+ }
+
public void InvalidateJitCacheRegion(ulong address, ulong size)
{
ulong[] overlapAddresses = [];
diff --git a/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs b/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs
index 1a5802a37..8b497fe2a 100644
--- a/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs
+++ b/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs
@@ -81,14 +81,14 @@ namespace Ryujinx.Audio.Renderer.Dsp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static short GetCoefficientAtIndex(ReadOnlySpan coefficients, int index)
{
- if ((uint)index < (uint)coefficients.Length)
+ if ((uint)index >= (uint)coefficients.Length)
{
- return coefficients[index];
+ Logger.Error?.Print(LogClass.AudioRenderer, $"Out of bound read for coefficient at index {index}");
+
+ return 0;
}
- Logger.Error?.Print(LogClass.AudioRenderer, $"Out of bound read for coefficient at index {index}");
-
- return 0;
+ return coefficients[index];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs
index 423cd22c8..18e60687d 100644
--- a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs
+++ b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs
@@ -14,12 +14,13 @@ namespace Ryujinx.Common.Collections
/// Adds a new node into the tree.
///
/// Node to be added
+ /// Node to be added under
/// is null
- public void Add(T node)
+ public void Add(T node, T parent = null)
{
ArgumentNullException.ThrowIfNull(node);
- Insert(node);
+ Insert(node, parent);
}
///
@@ -76,9 +77,11 @@ namespace Ryujinx.Common.Collections
/// Inserts a new node into the tree.
///
/// Node to be inserted
- private void Insert(T node)
+ /// Node to be inserted under
+ private void Insert(T node, T parent = null)
{
- T newNode = BSTInsert(node);
+ T newNode = parent != null ? InsertWithParent(node, parent) : BSTInsert(node);
+
RestoreBalanceAfterInsertion(newNode);
}
@@ -122,10 +125,78 @@ namespace Ryujinx.Common.Collections
else if (newNode.CompareTo(parent) < 0)
{
parent.Left = newNode;
+
+ newNode.Successor = parent;
+
+ if (parent.Predecessor != null)
+ {
+ newNode.Predecessor = parent.Predecessor;
+ parent.Predecessor = newNode;
+ newNode.Predecessor.Successor = newNode;
+ }
+
+ parent.Predecessor = newNode;
}
else
{
parent.Right = newNode;
+
+ newNode.Predecessor = parent;
+
+ if (parent.Successor != null)
+ {
+ newNode.Successor = parent.Successor;
+ newNode.Successor.Predecessor = newNode;
+ }
+
+ parent.Successor = newNode;
+ }
+ Count++;
+ return newNode;
+ }
+
+ ///
+ /// Insertion Mechanism for a Binary Search Tree (BST).
+ ///
+ /// Inserts a new node directly under a parent node
+ /// where all children in the left subtree are less than ,
+ /// and all children in the right subtree are greater than .
+ ///
+ /// Node to be inserted
+ /// Node to be inserted under
+ /// The inserted Node
+ private T InsertWithParent(T newNode, T parent)
+ {
+ newNode.Parent = parent;
+
+ if (newNode.CompareTo(parent) < 0)
+ {
+ parent.Left = newNode;
+
+ newNode.Successor = parent;
+
+ if (parent.Predecessor != null)
+ {
+ newNode.Predecessor = parent.Predecessor;
+ parent.Predecessor = newNode;
+ newNode.Predecessor.Successor = newNode;
+ }
+
+ parent.Predecessor = newNode;
+ }
+ else
+ {
+ parent.Right = newNode;
+
+ newNode.Predecessor = parent;
+
+ if (parent.Successor != null)
+ {
+ newNode.Successor = parent.Successor;
+ newNode.Successor.Predecessor = newNode;
+ }
+
+ parent.Successor = newNode;
}
Count++;
@@ -159,7 +230,7 @@ namespace Ryujinx.Common.Collections
}
else
{
- T element = Minimum(RightOf(nodeToDelete));
+ T element = nodeToDelete.Successor;
child = RightOf(element);
parent = ParentOf(element);
@@ -187,6 +258,9 @@ namespace Ryujinx.Common.Collections
element.Left = old.Left;
element.Right = old.Right;
element.Parent = old.Parent;
+ element.Predecessor = old.Predecessor;
+ if (element.Predecessor != null)
+ element.Predecessor.Successor = element;
if (ParentOf(old) == null)
{
@@ -241,6 +315,11 @@ namespace Ryujinx.Common.Collections
{
RestoreBalanceAfterRemoval(child);
}
+
+ if (old.Successor != null)
+ old.Successor.Predecessor = old.Predecessor;
+ if (old.Predecessor != null)
+ old.Predecessor.Successor = old.Successor;
return old;
}
diff --git a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeNode.cs b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeNode.cs
index 29d2d0c9a..57e0b27c8 100644
--- a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeNode.cs
+++ b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeNode.cs
@@ -9,8 +9,7 @@ namespace Ryujinx.Common.Collections
public T Left;
public T Right;
public T Parent;
-
- public T Predecessor => IntrusiveRedBlackTreeImpl.PredecessorOf((T)this);
- public T Successor => IntrusiveRedBlackTreeImpl.SuccessorOf((T)this);
+ public T Predecessor;
+ public T Successor;
}
}
diff --git a/src/Ryujinx.Common/Collections/TreeDictionary.cs b/src/Ryujinx.Common/Collections/TreeDictionary.cs
index af104d268..453f128d3 100644
--- a/src/Ryujinx.Common/Collections/TreeDictionary.cs
+++ b/src/Ryujinx.Common/Collections/TreeDictionary.cs
@@ -109,7 +109,7 @@ namespace Ryujinx.Common.Collections
Node node = GetNode(key);
if (node != null)
{
- Node successor = SuccessorOf(node);
+ Node successor = node.Successor;
return successor != null ? successor.Key : default;
}
@@ -127,7 +127,7 @@ namespace Ryujinx.Common.Collections
Node node = GetNode(key);
if (node != null)
{
- Node predecessor = PredecessorOf(node);
+ Node predecessor = node.Predecessor;
return predecessor != null ? predecessor.Key : default;
}
@@ -136,11 +136,10 @@ namespace Ryujinx.Common.Collections
}
///
- /// Adds all the nodes in the dictionary as key/value pairs into .
+ /// Adds all the nodes in the dictionary as key/value pairs into a list.
///
/// The key/value pairs will be added in Level Order.
///
- /// List to add the tree pairs into
public List> AsLevelOrderList()
{
List> list = [];
@@ -170,7 +169,7 @@ namespace Ryujinx.Common.Collections
}
///
- /// Adds all the nodes in the dictionary into .
+ /// Adds all the nodes in the dictionary into a list.
///
/// A list of all KeyValuePairs sorted by Key Order
public List> AsList()
@@ -284,7 +283,7 @@ namespace Ryujinx.Common.Collections
}
Node newNode = new(key, value, parent);
- if (newNode.Parent == null)
+ if (parent == null)
{
Root = newNode;
}
diff --git a/src/Ryujinx.Common/Logging/LogClass.cs b/src/Ryujinx.Common/Logging/LogClass.cs
index a4117580e..89f0336dc 100644
--- a/src/Ryujinx.Common/Logging/LogClass.cs
+++ b/src/Ryujinx.Common/Logging/LogClass.cs
@@ -13,6 +13,7 @@ namespace Ryujinx.Common.Logging
Cpu,
Emulation,
FFmpeg,
+ GdbStub,
Font,
Gpu,
Hid,
diff --git a/src/Ryujinx.Cpu/AppleHv/Arm/ExceptionLevel.cs b/src/Ryujinx.Cpu/AppleHv/Arm/ExceptionLevel.cs
new file mode 100644
index 000000000..08114e12a
--- /dev/null
+++ b/src/Ryujinx.Cpu/AppleHv/Arm/ExceptionLevel.cs
@@ -0,0 +1,10 @@
+namespace Ryujinx.Cpu.AppleHv.Arm
+{
+ enum ExceptionLevel : uint
+ {
+ PstateMask = 0xfffffff0,
+ EL1h = 0b0101,
+ El1t = 0b0100,
+ EL0 = 0b0000,
+ }
+}
diff --git a/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs b/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs
index 53cea5385..f13662e44 100644
--- a/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs
+++ b/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs
@@ -11,7 +11,18 @@ namespace Ryujinx.Cpu.AppleHv
class HvExecutionContext : IExecutionContext
{
///
- public ulong Pc => _impl.ElrEl1;
+ public ulong Pc
+ {
+ get
+ {
+ uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
+ if (currentEl == (uint)ExceptionLevel.EL1h)
+ {
+ return _impl.ElrEl1;
+ }
+ return _impl.Pc;
+ }
+ }
///
public long TpidrEl0
@@ -48,6 +59,9 @@ namespace Ryujinx.Cpu.AppleHv
set => _impl.Fpsr = value;
}
+ ///
+ public ulong ThreadUid { get; set; }
+
///
public bool IsAarch32
{
@@ -67,6 +81,7 @@ namespace Ryujinx.Cpu.AppleHv
private readonly ICounter _counter;
private readonly IHvExecutionContext _shadowContext;
private IHvExecutionContext _impl;
+ private int _shouldStep;
private readonly ExceptionCallbacks _exceptionCallbacks;
@@ -103,6 +118,11 @@ namespace Ryujinx.Cpu.AppleHv
_exceptionCallbacks.BreakCallback?.Invoke(this, address, imm);
}
+ private void StepHandler()
+ {
+ _exceptionCallbacks.StepCallback?.Invoke(this);
+ }
+
private void SupervisorCallHandler(ulong address, int imm)
{
_exceptionCallbacks.SupervisorCallback?.Invoke(this, address, imm);
@@ -127,6 +147,30 @@ namespace Ryujinx.Cpu.AppleHv
return Interlocked.Exchange(ref _interruptRequested, 0) != 0;
}
+ ///
+ public void RequestDebugStep()
+ {
+ Interlocked.Exchange(ref _shouldStep, 1);
+ }
+
+ ///
+ public ulong DebugPc
+ {
+ get => Pc;
+ set
+ {
+ uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
+ if (currentEl == (uint)ExceptionLevel.EL1h)
+ {
+ _impl.ElrEl1 = value;
+ }
+ else
+ {
+ _impl.Pc = value;
+ }
+ }
+ }
+
///
public void StopRunning()
{
@@ -142,6 +186,22 @@ namespace Ryujinx.Cpu.AppleHv
while (Running)
{
+ if (Interlocked.CompareExchange(ref _shouldStep, 0, 1) == 1)
+ {
+ uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
+ if (currentEl == (uint)ExceptionLevel.EL1h)
+ {
+ HvApi.hv_vcpu_get_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, out ulong spsr).ThrowOnError();
+ spsr |= (1 << 21);
+ HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, spsr);
+ }
+ else
+ {
+ Pstate |= (1 << 21);
+ }
+ HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.MDSCR_EL1, 1);
+ }
+
HvApi.hv_vcpu_run(vcpu.Handle).ThrowOnError();
HvExitReason reason = vcpu.ExitInfo->Reason;
@@ -209,6 +269,20 @@ namespace Ryujinx.Cpu.AppleHv
SupervisorCallHandler(elr - 4UL, id);
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
break;
+ case ExceptionClass.SoftwareStepLowerEl:
+ HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.SPSR_EL1, out ulong spsr).ThrowOnError();
+ spsr &= ~((ulong)(1 << 21));
+ HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.SPSR_EL1, spsr).ThrowOnError();
+ HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.MDSCR_EL1, 0);
+ ReturnToPool(vcpu);
+ StepHandler();
+ vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
+ break;
+ case ExceptionClass.BrkAarch64:
+ ReturnToPool(vcpu);
+ BreakHandler(elr, (ushort)esr);
+ vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
+ break;
default:
throw new Exception($"Unhandled guest exception {ec}.");
}
@@ -219,10 +293,7 @@ namespace Ryujinx.Cpu.AppleHv
// TODO: Invalidate only the range that was modified?
return HvAddressSpace.KernelRegionTlbiEretAddress;
}
- else
- {
- return HvAddressSpace.KernelRegionEretAddress;
- }
+ return HvAddressSpace.KernelRegionEretAddress;
}
private static void DataAbort(MemoryTracking tracking, ulong vcpu, uint esr)
diff --git a/src/Ryujinx.Cpu/AppleHv/HvExecutionContextShadow.cs b/src/Ryujinx.Cpu/AppleHv/HvExecutionContextShadow.cs
index 6ce8e1800..4ea5f276d 100644
--- a/src/Ryujinx.Cpu/AppleHv/HvExecutionContextShadow.cs
+++ b/src/Ryujinx.Cpu/AppleHv/HvExecutionContextShadow.cs
@@ -18,6 +18,8 @@ namespace Ryujinx.Cpu.AppleHv
public bool IsAarch32 { get; set; }
+ public ulong ThreadUid { get; set; }
+
private readonly ulong[] _x;
private readonly V128[] _v;
@@ -46,5 +48,14 @@ namespace Ryujinx.Cpu.AppleHv
{
_v[index] = value;
}
+
+ public void RequestInterrupt()
+ {
+ }
+
+ public bool GetAndClearInterruptRequested()
+ {
+ return false;
+ }
}
}
diff --git a/src/Ryujinx.Cpu/AppleHv/HvExecutionContextVcpu.cs b/src/Ryujinx.Cpu/AppleHv/HvExecutionContextVcpu.cs
index 1949cabdf..9ef03e61e 100644
--- a/src/Ryujinx.Cpu/AppleHv/HvExecutionContextVcpu.cs
+++ b/src/Ryujinx.Cpu/AppleHv/HvExecutionContextVcpu.cs
@@ -2,6 +2,7 @@ using ARMeilleure.State;
using Ryujinx.Memory;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
+using System.Threading;
namespace Ryujinx.Cpu.AppleHv
{
@@ -13,6 +14,8 @@ namespace Ryujinx.Cpu.AppleHv
private static readonly SetSimdFpReg _setSimdFpReg;
private static readonly nint _setSimdFpRegNativePtr;
+ public ulong ThreadUid { get; set; }
+
static HvExecutionContextVcpu()
{
// .NET does not support passing vectors by value, so we need to pass a pointer and use a native
@@ -135,6 +138,7 @@ namespace Ryujinx.Cpu.AppleHv
}
private readonly ulong _vcpu;
+ private int _interruptRequested;
public HvExecutionContextVcpu(ulong vcpu)
{
@@ -180,8 +184,16 @@ namespace Ryujinx.Cpu.AppleHv
public void RequestInterrupt()
{
- ulong vcpu = _vcpu;
- HvApi.hv_vcpus_exit(ref vcpu, 1);
+ if (Interlocked.Exchange(ref _interruptRequested, 1) == 0)
+ {
+ ulong vcpu = _vcpu;
+ HvApi.hv_vcpus_exit(ref vcpu, 1);
+ }
+ }
+
+ public bool GetAndClearInterruptRequested()
+ {
+ return Interlocked.Exchange(ref _interruptRequested, 0) != 0;
}
}
}
diff --git a/src/Ryujinx.Cpu/AppleHv/IHvExecutionContext.cs b/src/Ryujinx.Cpu/AppleHv/IHvExecutionContext.cs
index 54b73acc6..134405b5c 100644
--- a/src/Ryujinx.Cpu/AppleHv/IHvExecutionContext.cs
+++ b/src/Ryujinx.Cpu/AppleHv/IHvExecutionContext.cs
@@ -15,6 +15,7 @@ namespace Ryujinx.Cpu.AppleHv
uint Fpcr { get; set; }
uint Fpsr { get; set; }
+ ulong ThreadUid { get; set; }
ulong GetX(int index);
void SetX(int index, ulong value);
@@ -39,5 +40,8 @@ namespace Ryujinx.Cpu.AppleHv
SetV(i, context.GetV(i));
}
}
+
+ void RequestInterrupt();
+ bool GetAndClearInterruptRequested();
}
}
diff --git a/src/Ryujinx.Cpu/ExceptionCallbacks.cs b/src/Ryujinx.Cpu/ExceptionCallbacks.cs
index d9293302b..6e50b4d70 100644
--- a/src/Ryujinx.Cpu/ExceptionCallbacks.cs
+++ b/src/Ryujinx.Cpu/ExceptionCallbacks.cs
@@ -29,6 +29,11 @@ namespace Ryujinx.Cpu
///
public readonly ExceptionCallback BreakCallback;
+ ///
+ /// Handler for CPU software interrupts caused by single-stepping.
+ ///
+ public readonly ExceptionCallbackNoArgs StepCallback;
+
///
/// Handler for CPU software interrupts caused by the Arm SVC instruction.
///
@@ -47,16 +52,19 @@ namespace Ryujinx.Cpu
///
/// Handler for CPU interrupts triggered using
/// Handler for CPU software interrupts caused by the Arm BRK instruction
+ /// Handler for CPU software interrupts caused by single-stepping
/// Handler for CPU software interrupts caused by the Arm SVC instruction
/// Handler for CPU software interrupts caused by any undefined Arm instruction
public ExceptionCallbacks(
ExceptionCallbackNoArgs interruptCallback = null,
ExceptionCallback breakCallback = null,
+ ExceptionCallbackNoArgs stepCallback = null,
ExceptionCallback supervisorCallback = null,
ExceptionCallback undefinedCallback = null)
{
InterruptCallback = interruptCallback;
BreakCallback = breakCallback;
+ StepCallback = stepCallback;
SupervisorCallback = supervisorCallback;
UndefinedCallback = undefinedCallback;
}
diff --git a/src/Ryujinx.Cpu/IExecutionContext.cs b/src/Ryujinx.Cpu/IExecutionContext.cs
index c38210800..df0c94278 100644
--- a/src/Ryujinx.Cpu/IExecutionContext.cs
+++ b/src/Ryujinx.Cpu/IExecutionContext.cs
@@ -1,5 +1,6 @@
using ARMeilleure.State;
using System;
+using System.Threading;
namespace Ryujinx.Cpu
{
@@ -46,6 +47,11 @@ namespace Ryujinx.Cpu
///
bool IsAarch32 { get; set; }
+ ///
+ /// Thread UID.
+ ///
+ public ulong ThreadUid { get; set; }
+
///
/// Indicates whenever the CPU is still running code.
///
@@ -108,5 +114,23 @@ namespace Ryujinx.Cpu
/// If you only need to pause the thread temporarily, use instead.
///
void StopRunning();
+
+ ///
+ /// Requests the thread to stop running temporarily and call .
+ ///
+ ///
+ /// The thread might not pause immediately.
+ /// One must not assume that guest code is no longer being executed by the thread after calling this function.
+ /// After single stepping, the thread should call call .
+ ///
+ void RequestDebugStep();
+
+ ///
+ /// Current Program Counter (for debugging).
+ ///
+ ///
+ /// PC register for the debugger. Must not be accessed while the thread isn't stopped for debugging.
+ ///
+ ulong DebugPc { get; set; }
}
}
diff --git a/src/Ryujinx.Cpu/Jit/JitExecutionContext.cs b/src/Ryujinx.Cpu/Jit/JitExecutionContext.cs
index f15486e68..f00acc1d7 100644
--- a/src/Ryujinx.Cpu/Jit/JitExecutionContext.cs
+++ b/src/Ryujinx.Cpu/Jit/JitExecutionContext.cs
@@ -1,5 +1,6 @@
using ARMeilleure.Memory;
using ARMeilleure.State;
+using ExecutionContext = ARMeilleure.State.ExecutionContext;
namespace Ryujinx.Cpu.Jit
{
@@ -53,6 +54,13 @@ namespace Ryujinx.Cpu.Jit
set => _impl.IsAarch32 = value;
}
+ ///
+ public ulong ThreadUid
+ {
+ get => _impl.ThreadUid;
+ set => _impl.ThreadUid = value;
+ }
+
///
public bool Running => _impl.Running;
@@ -65,6 +73,7 @@ namespace Ryujinx.Cpu.Jit
counter,
InterruptHandler,
BreakHandler,
+ StepHandler,
SupervisorCallHandler,
UndefinedHandler);
@@ -93,6 +102,11 @@ namespace Ryujinx.Cpu.Jit
_exceptionCallbacks.BreakCallback?.Invoke(this, address, imm);
}
+ private void StepHandler(ExecutionContext context)
+ {
+ _exceptionCallbacks.StepCallback?.Invoke(this);
+ }
+
private void SupervisorCallHandler(ExecutionContext context, ulong address, int imm)
{
_exceptionCallbacks.SupervisorCallback?.Invoke(this, address, imm);
@@ -109,6 +123,16 @@ namespace Ryujinx.Cpu.Jit
_impl.RequestInterrupt();
}
+ ///
+ public void RequestDebugStep() => _impl.RequestDebugStep();
+
+ ///
+ public ulong DebugPc
+ {
+ get => _impl.DebugPc;
+ set => _impl.DebugPc = value;
+ }
+
///
public void StopRunning()
{
diff --git a/src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs b/src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs
index a366dcca6..a1ba0002e 100644
--- a/src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs
+++ b/src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs
@@ -1,6 +1,8 @@
+using ARMeilleure;
using ARMeilleure.Memory;
using ARMeilleure.State;
using System;
+using System.Threading;
namespace Ryujinx.Cpu.LightningJit.State
{
@@ -51,6 +53,8 @@ namespace Ryujinx.Cpu.LightningJit.State
}
public bool IsAarch32 { get; set; }
+
+ public ulong ThreadUid { get; set; }
internal ExecutionMode ExecutionMode
{
@@ -77,15 +81,20 @@ namespace Ryujinx.Cpu.LightningJit.State
private readonly ExceptionCallbackNoArgs _interruptCallback;
private readonly ExceptionCallback _breakCallback;
+ private readonly ExceptionCallbackNoArgs _stepCallback;
private readonly ExceptionCallback _supervisorCallback;
private readonly ExceptionCallback _undefinedCallback;
+ internal int ShouldStep;
+ public ulong DebugPc { get; set; }
+
public ExecutionContext(IJitMemoryAllocator allocator, ICounter counter, ExceptionCallbacks exceptionCallbacks)
{
_nativeContext = new NativeContext(allocator);
_counter = counter;
_interruptCallback = exceptionCallbacks.InterruptCallback;
_breakCallback = exceptionCallbacks.BreakCallback;
+ _stepCallback = exceptionCallbacks.StepCallback;
_supervisorCallback = exceptionCallbacks.SupervisorCallback;
_undefinedCallback = exceptionCallbacks.UndefinedCallback;
@@ -117,6 +126,17 @@ namespace Ryujinx.Cpu.LightningJit.State
_interrupted = true;
}
+ public void StepHandler()
+ {
+ _stepCallback?.Invoke(this);
+ }
+
+ public void RequestDebugStep()
+ {
+ Interlocked.Exchange(ref ShouldStep, 1);
+ RequestInterrupt();
+ }
+
internal void OnBreak(ulong address, int imm)
{
_breakCallback?.Invoke(this, address, imm);
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs
index a2448d76f..293f7fd2c 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs
@@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
///
/// Buffer, used to store vertex and index data, uniform and storage buffers, and others.
///
- class Buffer : IRange, ISyncActionHandler, IDisposable
+ class Buffer : INonOverlappingRange, ISyncActionHandler, IDisposable
{
private const ulong GranularBufferThreshold = 4096;
@@ -35,7 +35,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
///
/// Size of the buffer in bytes.
///
- public ulong Size { get; }
+ public ulong Size { get; private set; }
///
/// End address of the buffer in guest memory.
@@ -60,13 +60,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
///
/// This is null until at least one modification occurs.
///
- private BufferModifiedRangeList _modifiedRanges = null;
+ private BufferModifiedRangeList _modifiedRanges;
///
/// A structure that is used to flush buffer data back to a host mapped buffer for cached readback.
/// Only used if the buffer data is explicitly owned by device local memory.
///
- private BufferPreFlush _preFlush = null;
+ private BufferPreFlush _preFlush;
///
/// Usage tracking state that determines what type of backing the buffer should use.
@@ -110,7 +110,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
ulong size,
BufferStage stage,
bool sparseCompatible,
- IEnumerable baseBuffers = null)
+ List baseBuffers)
{
_context = context;
_physicalMemory = physicalMemory;
@@ -126,21 +126,22 @@ namespace Ryujinx.Graphics.Gpu.Memory
_useGranular = size > GranularBufferThreshold;
- IEnumerable baseHandles = null;
+ List baseHandles = null;
- if (baseBuffers != null)
+ if (baseBuffers.Count != 0)
{
- baseHandles = baseBuffers.SelectMany(buffer =>
+ baseHandles = new List();
+ foreach (Buffer buffer in baseBuffers)
{
if (buffer._useGranular)
{
- return buffer._memoryTrackingGranular.GetHandles();
+ baseHandles.AddRange((buffer._memoryTrackingGranular.GetHandles()));
}
else
{
- return Enumerable.Repeat(buffer._memoryTracking, 1);
+ baseHandles.Add(buffer._memoryTracking);
}
- });
+ }
}
if (_useGranular)
@@ -171,9 +172,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
_memoryTracking.RegisterPreciseAction(PreciseAction);
}
- _externalFlushDelegate = new RegionSignal(ExternalFlush);
- _loadDelegate = new Action(LoadRegion);
- _modifiedDelegate = new Action(RegionModified);
+ _externalFlushDelegate = ExternalFlush;
+ _loadDelegate = LoadRegion;
+ _modifiedDelegate = RegionModified;
_virtualDependenciesLock = new ReaderWriterLockSlim();
}
@@ -247,6 +248,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
return Address < address + size && address < EndAddress;
}
+ public INonOverlappingRange Split(ulong splitAddress)
+ {
+ throw new NotImplementedException();
+ }
+
///
/// Checks if a given range is fully contained in the buffer.
///
@@ -435,7 +441,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// The buffer to inherit from
public void InheritModifiedRanges(Buffer from)
{
- if (from._modifiedRanges != null && from._modifiedRanges.HasRanges)
+ if (from._modifiedRanges is { HasRanges: true })
{
if (from._syncActionRegistered && !_syncActionRegistered)
{
@@ -443,7 +449,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
_syncActionRegistered = true;
}
- void registerRangeAction(ulong address, ulong size)
+ void RegisterRangeAction(ulong address, ulong size)
{
if (_useGranular)
{
@@ -457,7 +463,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
EnsureRangeList();
- _modifiedRanges.InheritRanges(from._modifiedRanges, registerRangeAction);
+ _modifiedRanges.InheritRanges(from._modifiedRanges, RegisterRangeAction);
}
if (from._dirtyStart != ulong.MaxValue)
@@ -499,14 +505,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
// Cut off the start.
- if (end < _dirtyEnd)
- {
- _dirtyStart = end;
- }
- else
- {
- _dirtyStart = ulong.MaxValue;
- }
+ _dirtyStart = end < _dirtyEnd ? end : ulong.MaxValue;
}
else if (end >= _dirtyEnd)
{
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs
index a9b1f50e2..df130bb1d 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs
@@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Parent buffer
/// Initial buffer stage
/// Buffers to inherit state from
- public BufferBackingState(GpuContext context, Buffer parent, BufferStage stage, IEnumerable baseBuffers = null)
+ public BufferBackingState(GpuContext context, Buffer parent, BufferStage stage, List baseBuffers)
{
_size = (int)parent.Size;
_systemMemoryType = context.Capabilities.MemoryType;
@@ -72,7 +72,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
BufferStage storageFlags = stage & BufferStage.StorageMask;
- if (parent.Size > DeviceLocalSizeThreshold && baseBuffers == null)
+ if (parent.Size > DeviceLocalSizeThreshold && baseBuffers.Count == 0)
{
_desiredType = BufferBackingType.DeviceMemory;
}
@@ -100,7 +100,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
// TODO: Might be nice to force atomic access to be device local for any stage.
}
- if (baseBuffers != null)
+ if (baseBuffers.Count != 0)
{
foreach (Buffer buffer in baseBuffers)
{
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs
index d02efcb29..8d0bf9833 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs
@@ -2,7 +2,6 @@ using Ryujinx.Graphics.GAL;
using Ryujinx.Memory.Range;
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Runtime.CompilerServices;
namespace Ryujinx.Graphics.Gpu.Memory
@@ -39,11 +38,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Only modified from the GPU thread. Must lock for add/remove.
/// Must lock for any access from other threads.
///
- private readonly RangeList _buffers;
+ private readonly NonOverlappingRangeList _buffers;
private readonly MultiRangeList _multiRangeBuffers;
- private Buffer[] _bufferOverlaps;
-
private readonly Dictionary _dirtyCache;
private readonly Dictionary _modifiedCache;
private bool _pruneCaches;
@@ -64,8 +61,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
_buffers = [];
_multiRangeBuffers = [];
- _bufferOverlaps = new Buffer[OverlapsBufferInitialCapacity];
-
_dirtyCache = new Dictionary();
// There are a lot more entries on the modified cache, so it is separate from the one for ForceDirty.
@@ -79,24 +74,23 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Event arguments
public void MemoryUnmappedHandler(object sender, UnmapEventArgs e)
{
- Buffer[] overlaps = new Buffer[10];
- int overlapCount;
-
MultiRange range = ((MemoryManager)sender).GetPhysicalRegions(e.Address, e.Size);
for (int index = 0; index < range.Count; index++)
{
MemoryRange subRange = range.GetSubRange(index);
+
+ _buffers.Lock.EnterReadLock();
+ (RangeItem first, RangeItem last) = _buffers.FindOverlaps(subRange.Address, subRange.Size);
- lock (_buffers)
+ RangeItem current = first;
+ while (last != null && current != last.Next)
{
- overlapCount = _buffers.FindOverlaps(subRange.Address, subRange.Size, ref overlaps);
+ current.Value.Unmapped(subRange.Address, subRange.Size);
+ current = current.Next;
}
- for (int i = 0; i < overlapCount; i++)
- {
- overlaps[i].Unmapped(subRange.Address, subRange.Size);
- }
+ _buffers.Lock.ExitReadLock();
}
}
@@ -137,7 +131,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Physical ranges of the buffer, after address translation
public MultiRange TranslateAndCreateMultiBuffers(MemoryManager memoryManager, ulong gpuVa, ulong size, BufferStage stage)
{
- if (gpuVa == 0)
+ if (gpuVa == 0 || size == 0)
{
return new MultiRange(MemoryManager.PteUnmapped, size);
}
@@ -336,7 +330,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
ulong alignedEndAddress = (endAddress + alignmentMask) & ~alignmentMask;
ulong alignedSize = alignedEndAddress - alignedAddress;
- Buffer buffer = _buffers.FindFirstOverlap(alignedAddress, alignedSize);
+ Buffer buffer = _buffers.FindOverlap(alignedAddress, alignedSize).Value;
BufferRange bufferRange = buffer.GetRange(alignedAddress, alignedSize, false);
alignedSubRanges[i] = new MemoryRange(alignedAddress, alignedSize);
@@ -403,7 +397,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (subRange.Address != MemoryManager.PteUnmapped)
{
- Buffer buffer = _buffers.FindFirstOverlap(subRange.Address, subRange.Size);
+ Buffer buffer = _buffers.FindOverlap(subRange.Address, subRange.Size).Value;
virtualBuffer.AddPhysicalDependency(buffer, subRange.Address, dstOffset, subRange.Size);
physicalBuffers.Add(buffer);
@@ -495,10 +489,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// The type of usage that created the buffer
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage)
{
- Buffer[] overlaps = _bufferOverlaps;
- int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
+ _buffers.Lock.EnterWriteLock();
+ (RangeItem first, RangeItem last) = _buffers.FindOverlaps(address, size);
- if (overlapsCount != 0)
+ if (first is not null)
{
// The buffer already exists. We can just return the existing buffer
// if the buffer we need is fully contained inside the overlapping buffer.
@@ -507,9 +501,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
// old buffer(s) to the new buffer.
ulong endAddress = address + size;
- Buffer overlap0 = overlaps[0];
- if (overlap0.Address > address || overlap0.EndAddress < endAddress)
+ if (first.Address > address || first.EndAddress < endAddress)
{
bool anySparseCompatible = false;
@@ -522,53 +515,52 @@ namespace Ryujinx.Graphics.Gpu.Memory
// sequential memory.
// Allowing for 2 pages (rather than just one) is necessary to catch cases where the
// range crosses a page, and after alignment, ends having a size of 2 pages.
- if (overlapsCount == 1 &&
- address >= overlap0.Address &&
- endAddress - overlap0.EndAddress <= BufferAlignmentSize * 2)
+ if (first == last &&
+ address >= first.Address &&
+ endAddress - first.EndAddress <= BufferAlignmentSize * 2)
{
// Try to grow the buffer by 1.5x of its current size.
// This improves performance in the cases where the buffer is resized often by small amounts.
- ulong existingSize = overlap0.Size;
+ ulong existingSize = first.Value.Size;
ulong growthSize = (existingSize + Math.Min(existingSize >> 1, MaxDynamicGrowthSize)) & ~BufferAlignmentMask;
size = Math.Max(size, growthSize);
endAddress = address + size;
- overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
+ (first, last) = _buffers.FindOverlaps(address, size);
}
+
+ address = Math.Min(address, first.Address);
+ endAddress = Math.Max(endAddress, last.EndAddress);
- for (int index = 0; index < overlapsCount; index++)
+ List overlaps = [];
+
+ RangeItem current = first;
+ while (current != last.Next)
{
- Buffer buffer = overlaps[index];
-
- anySparseCompatible |= buffer.SparseCompatible;
-
- address = Math.Min(address, buffer.Address);
- endAddress = Math.Max(endAddress, buffer.EndAddress);
-
- lock (_buffers)
- {
- _buffers.Remove(buffer);
- }
+ anySparseCompatible |= current.Value.SparseCompatible;
+ overlaps.Add(current.Value);
+ _buffers.Remove(current.Value);
+
+ current = current.Next;
}
-
+
ulong newSize = endAddress - address;
- CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlaps, overlapsCount);
+ Buffer newBuffer = CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlaps);
+
+ _buffers.Add(newBuffer);
}
}
else
{
// No overlap, just create a new buffer.
- Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible: false);
+ Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible: false, []);
- lock (_buffers)
- {
- _buffers.Add(buffer);
- }
+ _buffers.Add(buffer);
}
-
- ShrinkOverlapsBufferIfNeeded();
+
+ _buffers.Lock.ExitWriteLock();
}
///
@@ -582,72 +574,68 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Alignment of the start address of the buffer
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, ulong alignment)
{
- Buffer[] overlaps = _bufferOverlaps;
- int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
bool sparseAligned = alignment >= SparseBufferAlignmentSize;
+
+ _buffers.Lock.EnterWriteLock();
+ (RangeItem first, RangeItem last) = _buffers.FindOverlaps(address, size);
- if (overlapsCount != 0)
+ if (first is not null)
{
// If the buffer already exists, make sure if covers the entire range,
// and make sure it is properly aligned, otherwise sparse mapping may fail.
ulong endAddress = address + size;
- Buffer overlap0 = overlaps[0];
- if (overlap0.Address > address ||
- overlap0.EndAddress < endAddress ||
- (overlap0.Address & (alignment - 1)) != 0 ||
- (!overlap0.SparseCompatible && sparseAligned))
+ if (first.Address > address ||
+ first.EndAddress < endAddress ||
+ (first.Address & (alignment - 1)) != 0 ||
+ (!first.Value.SparseCompatible && sparseAligned))
{
// We need to make sure the new buffer is properly aligned.
// However, after the range is aligned, it is possible that it
// overlaps more buffers, so try again after each extension
// and ensure we cover all overlaps.
- int oldOverlapsCount;
+ RangeItem oldFirst;
+ endAddress = Math.Max(endAddress, last.EndAddress);
do
{
- for (int index = 0; index < overlapsCount; index++)
- {
- Buffer buffer = overlaps[index];
-
- address = Math.Min(address, buffer.Address);
- endAddress = Math.Max(endAddress, buffer.EndAddress);
- }
+ address = Math.Min(address, first.Address);
address &= ~(alignment - 1);
- oldOverlapsCount = overlapsCount;
- overlapsCount = _buffers.FindOverlapsNonOverlapping(address, endAddress - address, ref overlaps);
- }
- while (oldOverlapsCount != overlapsCount);
-
- lock (_buffers)
- {
- for (int index = 0; index < overlapsCount; index++)
- {
- _buffers.Remove(overlaps[index]);
- }
+ oldFirst = first;
+ (first, last) = _buffers.FindOverlaps(address, endAddress - address);
}
+ while (oldFirst != first);
ulong newSize = endAddress - address;
-
- CreateBufferAligned(address, newSize, stage, sparseAligned, overlaps, overlapsCount);
+
+ List overlaps = [];
+
+ RangeItem current = first;
+ while (current != last.Next)
+ {
+ overlaps.Add(current.Value);
+ _buffers.Remove(current.Value);
+
+ current = current.Next;
+ }
+
+ Buffer newBuffer = CreateBufferAligned(address, newSize, stage, sparseAligned, overlaps);
+
+ _buffers.Add(newBuffer);
}
}
else
{
// No overlap, just create a new buffer.
- Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseAligned);
+ Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseAligned, []);
- lock (_buffers)
- {
- _buffers.Add(buffer);
- }
+ _buffers.Add(buffer);
}
-
- ShrinkOverlapsBufferIfNeeded();
+ _buffers.Lock.ExitWriteLock();
}
///
@@ -660,17 +648,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// The type of usage that created the buffer
/// Indicates if the buffer can be used in a sparse buffer mapping
/// Buffers overlapping the range
- /// Total of overlaps
- private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, bool sparseCompatible, Buffer[] overlaps, int overlapsCount)
+ private Buffer CreateBufferAligned(ulong address, ulong size, BufferStage stage, bool sparseCompatible, List overlaps)
{
- Buffer newBuffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible, overlaps.Take(overlapsCount));
+ Buffer newBuffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible, overlaps);
- lock (_buffers)
- {
- _buffers.Add(newBuffer);
- }
-
- for (int index = 0; index < overlapsCount; index++)
+ for (int index = 0; index < overlaps.Count; index++)
{
Buffer buffer = overlaps[index];
@@ -688,6 +670,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
NotifyBuffersModified?.Invoke();
RecreateMultiRangeBuffers(address, size);
+
+ return newBuffer;
}
///
@@ -718,17 +702,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
}
- ///
- /// Resizes the temporary buffer used for range list intersection results, if it has grown too much.
- ///
- private void ShrinkOverlapsBufferIfNeeded()
- {
- if (_bufferOverlaps.Length > OverlapsBufferMaxCapacity)
- {
- Array.Resize(ref _bufferOverlaps, OverlapsBufferMaxCapacity);
- }
- }
-
///
/// Copy a buffer data from a given address to another.
///
@@ -909,7 +882,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
MemoryRange subRange = range.GetSubRange(i);
- Buffer subBuffer = _buffers.FindFirstOverlap(subRange.Address, subRange.Size);
+ Buffer subBuffer = _buffers.FindOverlapFast(subRange.Address, subRange.Size).Value;
subBuffer.SynchronizeMemory(subRange.Address, subRange.Size);
@@ -957,7 +930,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (size != 0)
{
- buffer = _buffers.FindFirstOverlap(address, size);
+ buffer = _buffers.FindOverlapFast(address, size).Value;
buffer.CopyFromDependantVirtualBuffers();
buffer.SynchronizeMemory(address, size);
@@ -969,7 +942,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
else
{
- buffer = _buffers.FindFirstOverlap(address, 1);
+ buffer = _buffers.FindOverlapFast(address, 1).Value;
}
return buffer;
@@ -1007,7 +980,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
if (size != 0)
{
- Buffer buffer = _buffers.FindFirstOverlap(address, size);
+ Buffer buffer = _buffers.FindOverlapFast(address, size).Value;
if (copyBackVirtual)
{
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
index cb99b455b..73647bef5 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
@@ -258,7 +258,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
RecordStorageAlignment(_cpStorageBuffers, index, gpuVa);
- gpuVa = BitUtils.AlignDown(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
+ gpuVa = BitUtils.AlignDown(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size, BufferStageUtils.ComputeStorage(flags));
@@ -282,7 +282,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
RecordStorageAlignment(buffers, index, gpuVa);
- gpuVa = BitUtils.AlignDown(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
+ gpuVa = BitUtils.AlignDown(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size, BufferStageUtils.GraphicsStorage(stage, flags));
@@ -761,7 +761,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (!bounds.IsUnmapped)
{
- bool isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
+ bool isWrite = (bounds.Flags & BufferUsageFlags.Write) == BufferUsageFlags.Write;
BufferRange range = isStorage
? bufferCache.GetBufferRangeAligned(bounds.Range, bufferStage | BufferStageUtils.FromUsage(bounds.Flags), isWrite)
: bufferCache.GetBufferRange(bounds.Range, bufferStage);
@@ -798,7 +798,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (!bounds.IsUnmapped)
{
- bool isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
+ bool isWrite = (bounds.Flags & BufferUsageFlags.Write) == BufferUsageFlags.Write;
BufferRange range = isStorage
? bufferCache.GetBufferRangeAligned(bounds.Range, BufferStageUtils.ComputeStorage(bounds.Flags), isWrite)
: bufferCache.GetBufferRange(bounds.Range, BufferStage.Compute);
@@ -817,7 +817,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Bind respective buffer bindings on the host API.
///
/// Host buffers to bind, with their offsets and sizes
- /// First binding point
/// Number of bindings
/// Indicates if the buffers are storage or uniform buffers
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -866,7 +865,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Buffer texture
/// Physical ranges of memory where the buffer texture data is located
/// Binding info for the buffer texture
- /// Format of the buffer texture
/// Whether the binding is for an image or a sampler
public void SetBufferTextureStorage(
ShaderStage stage,
@@ -889,7 +887,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Physical ranges of memory where the buffer texture data is located
/// Binding info for the buffer texture
/// Index of the binding on the array
- /// Format of the buffer texture
public void SetBufferTextureStorage(
ShaderStage stage,
ITextureArray array,
@@ -912,7 +909,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Physical ranges of memory where the buffer texture data is located
/// Binding info for the buffer texture
/// Index of the binding on the array
- /// Format of the buffer texture
public void SetBufferTextureStorage(
ShaderStage stage,
IImageArray array,
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs
index bccbdfd31..8c1132d9b 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs
@@ -1,25 +1,24 @@
-using Ryujinx.Common.Pools;
using Ryujinx.Memory.Range;
using System;
+using System.Collections.Generic;
using System.Linq;
-using System.Threading;
namespace Ryujinx.Graphics.Gpu.Memory
{
///
/// A range within a buffer that has been modified by the GPU.
///
- class BufferModifiedRange : IRange
+ class BufferModifiedRange : INonOverlappingRange
{
///
/// Start address of the range in guest memory.
///
- public ulong Address { get; }
+ public ulong Address { get; internal set; }
///
/// Size of the range in bytes.
///
- public ulong Size { get; }
+ public ulong Size { get; internal set; }
///
/// End address of the range in guest memory.
@@ -61,14 +60,19 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
return Address < address + size && address < EndAddress;
}
+
+ public INonOverlappingRange Split(ulong splitAddress)
+ {
+ throw new NotImplementedException();
+ }
}
///
/// A structure used to track GPU modified ranges within a buffer.
///
- class BufferModifiedRangeList : RangeList
+ class BufferModifiedRangeList : NonOverlappingRangeList
{
- private const int BackingInitialSize = 8;
+ private new const int BackingInitialSize = 8;
private readonly GpuContext _context;
private readonly Buffer _parent;
@@ -77,8 +81,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
private BufferMigration _source;
private BufferModifiedRangeList _migrationTarget;
- private readonly Lock _lock = new();
-
///
/// Whether the modified range list has any entries or not.
///
@@ -86,10 +88,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
get
{
- lock (_lock)
- {
- return Count > 0;
- }
+ Lock.EnterReadLock();
+ bool result = Count > 0;
+ Lock.ExitReadLock();
+ return result;
}
}
@@ -114,33 +116,41 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Action to perform for each remaining sub-range of the input range
public void ExcludeModifiedRegions(ulong address, ulong size, Action action)
{
- lock (_lock)
+ // Slices a given region using the modified regions in the list. Calls the action for the new slices.
+ bool lockOwner = Lock.IsReadLockHeld;
+ if (!lockOwner)
{
- // Slices a given region using the modified regions in the list. Calls the action for the new slices.
- ref BufferModifiedRange[] overlaps = ref ThreadStaticArray.Get();
+ Lock.EnterReadLock();
+ }
- int count = FindOverlapsNonOverlapping(address, size, ref overlaps);
+ (RangeItem first, RangeItem last) = FindOverlaps(address, size);
- for (int i = 0; i < count; i++)
+ RangeItem current = first;
+ while (last != null && current != last.Next)
+ {
+ BufferModifiedRange overlap = current.Value;
+
+ if (overlap.Address > address)
{
- BufferModifiedRange overlap = overlaps[i];
-
- if (overlap.Address > address)
- {
- // The start of the remaining region is uncovered by this overlap. Call the action for it.
- action(address, overlap.Address - address);
- }
-
- // Remaining region is after this overlap.
- size -= overlap.EndAddress - address;
- address = overlap.EndAddress;
+ // The start of the remaining region is uncovered by this overlap. Call the action for it.
+ action(address, overlap.Address - address);
}
- if ((long)size > 0)
- {
- // If there is any region left after removing the overlaps, signal it.
- action(address, size);
- }
+ // Remaining region is after this overlap.
+ size -= overlap.EndAddress - address;
+ address = overlap.EndAddress;
+ current = current.Next;
+ }
+
+ if (!lockOwner)
+ {
+ Lock.ExitReadLock();
+ }
+
+ if ((long)size > 0)
+ {
+ // If there is any region left after removing the overlaps, signal it.
+ action(address, size);
}
}
@@ -152,51 +162,101 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Size of the modified region in bytes
public void SignalModified(ulong address, ulong size)
{
- // Must lock, as this can affect flushes from the background thread.
- lock (_lock)
+ // We may overlap with some existing modified regions. They must be cut into by the new entry.
+ Lock.EnterWriteLock();
+ (RangeItem first, RangeItem last) = FindOverlaps(address, size);
+
+ ulong endAddress = address + size;
+ ulong syncNumber = _context.SyncNumber;
+
+ if (first is null)
{
- // We may overlap with some existing modified regions. They must be cut into by the new entry.
- ref BufferModifiedRange[] overlaps = ref ThreadStaticArray.Get();
+ Add(new BufferModifiedRange(address, size, syncNumber, this));
+ Lock.ExitWriteLock();
+ return;
+ }
- int count = FindOverlapsNonOverlapping(address, size, ref overlaps);
+ BufferModifiedRange buffPost = null;
+ bool extendsPost = false;
+ bool extendsPre = false;
- ulong endAddress = address + size;
- ulong syncNumber = _context.SyncNumber;
-
- for (int i = 0; i < count; i++)
+ if (first == last)
+ {
+ if (first.Address == address && first.EndAddress == endAddress)
{
- // The overlaps must be removed or split.
+ first.Value.SyncNumber = syncNumber;
+ first.Value.Parent = this;
+ Lock.ExitWriteLock();
+ return;
+ }
- BufferModifiedRange overlap = overlaps[i];
+ if (first.Address < address)
+ {
+ first.Value.Size = address - first.Address;
- if (overlap.Address == address && overlap.Size == size)
+ extendsPre = true;
+
+ if (first.EndAddress > endAddress)
{
- // Region already exists. Just update the existing sync number.
- overlap.SyncNumber = syncNumber;
- overlap.Parent = this;
-
- return;
+ buffPost = new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
+ first.Value.SyncNumber, first.Value.Parent);
+ extendsPost = true;
}
-
- Remove(overlap);
-
- if (overlap.Address < address && overlap.EndAddress > address)
+ }
+ else
+ {
+ if (first.EndAddress > endAddress)
{
- // A split item must be created behind this overlap.
-
- Add(new BufferModifiedRange(overlap.Address, address - overlap.Address, overlap.SyncNumber, overlap.Parent));
+ first.Value.Size = first.EndAddress - endAddress;
+ first.Value.Address = endAddress;
}
-
- if (overlap.Address < endAddress && overlap.EndAddress > endAddress)
+ else
{
- // A split item must be created after this overlap.
-
- Add(new BufferModifiedRange(endAddress, overlap.EndAddress - endAddress, overlap.SyncNumber, overlap.Parent));
+ Remove(first.Value);
}
}
+ if (extendsPre && extendsPost)
+ {
+ Add(buffPost);
+ }
+
Add(new BufferModifiedRange(address, size, syncNumber, this));
+ Lock.ExitWriteLock();
+
+ return;
}
+
+ BufferModifiedRange buffPre = null;
+
+ if (first.Address < address)
+ {
+ buffPre = new BufferModifiedRange(first.Address, address - first.Address,
+ first.Value.SyncNumber, first.Value.Parent);
+ extendsPre = true;
+ }
+
+ if (last.EndAddress > endAddress)
+ {
+ buffPost = new BufferModifiedRange(endAddress, last.EndAddress - endAddress,
+ last.Value.SyncNumber, last.Value.Parent);
+ extendsPost = true;
+ }
+
+ RemoveRange(first, last);
+
+ if (extendsPre)
+ {
+ Add(buffPre);
+ }
+
+ if (extendsPost)
+ {
+ Add(buffPost);
+ }
+
+ Add(new BufferModifiedRange(address, size, syncNumber, this));
+ Lock.ExitWriteLock();
}
///
@@ -208,25 +268,23 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// The action to call for each modified range
public void GetRangesAtSync(ulong address, ulong size, ulong syncNumber, Action rangeAction)
{
- int count = 0;
+ Lock.EnterReadLock();
+ (RangeItem first, RangeItem last) = FindOverlaps(address, size);
- ref BufferModifiedRange[] overlaps = ref ThreadStaticArray.Get();
-
- // Range list must be consistent for this operation.
- lock (_lock)
+ RangeItem current = first;
+ while (last != null && current != last.Next)
{
- count = FindOverlapsNonOverlapping(address, size, ref overlaps);
- }
-
- for (int i = 0; i < count; i++)
- {
- BufferModifiedRange overlap = overlaps[i];
+ BufferModifiedRange overlap = current.Value;
if (overlap.SyncNumber == syncNumber)
{
rangeAction(overlap.Address, overlap.Size);
}
+
+ current = current.Next;
}
+
+ Lock.ExitReadLock();
}
///
@@ -237,19 +295,23 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// The action to call for each modified range
public void GetRanges(ulong address, ulong size, Action rangeAction)
{
- int count = 0;
-
- ref BufferModifiedRange[] overlaps = ref ThreadStaticArray.Get();
-
- // Range list must be consistent for this operation.
- lock (_lock)
+ List> overlaps = [];
+
+ // We use the non-span method here because keeping the lock will cause a deadlock.
+ Lock.EnterReadLock();
+ (RangeItem first, RangeItem last) = FindOverlaps(address, size);
+
+ RangeItem current = first;
+ while (last != null && current != last.Next)
{
- count = FindOverlapsNonOverlapping(address, size, ref overlaps);
+ overlaps.Add(current);
+ current = current.Next;
}
+ Lock.ExitReadLock();
- for (int i = 0; i < count; i++)
+ for (int i = 0; i < overlaps.Count; i++)
{
- BufferModifiedRange overlap = overlaps[i];
+ BufferModifiedRange overlap = overlaps[i].Value;
rangeAction(overlap.Address, overlap.Size);
}
}
@@ -262,11 +324,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// True if a range exists in the specified region, false otherwise
public bool HasRange(ulong address, ulong size)
{
- // Range list must be consistent for this operation.
- lock (_lock)
- {
- return FindOverlapsNonOverlapping(address, size, ref ThreadStaticArray.Get()) > 0;
- }
+ Lock.EnterReadLock();
+ (RangeItem first, RangeItem _) = FindOverlaps(address, size);
+ bool result = first is not null;
+ Lock.ExitReadLock();
+ return result;
}
///
@@ -298,38 +360,37 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// The start address of the flush range
/// The end address of the flush range
private void RemoveRangesAndFlush(
- BufferModifiedRange[] overlaps,
+ RangeItem[] overlaps,
int rangeCount,
long highestDiff,
ulong currentSync,
ulong address,
ulong endAddress)
{
- lock (_lock)
+ if (_migrationTarget == null)
{
- if (_migrationTarget == null)
+ ulong waitSync = currentSync + (ulong)highestDiff;
+
+ for (int i = 0; i < rangeCount; i++)
{
- ulong waitSync = currentSync + (ulong)highestDiff;
+ BufferModifiedRange overlap = overlaps[i].Value;
- for (int i = 0; i < rangeCount; i++)
+ long diff = (long)(overlap.SyncNumber - currentSync);
+
+ if (diff <= highestDiff)
{
- BufferModifiedRange overlap = overlaps[i];
+ ulong clampAddress = Math.Max(address, overlap.Address);
+ ulong clampEnd = Math.Min(endAddress, overlap.EndAddress);
- long diff = (long)(overlap.SyncNumber - currentSync);
+ Lock.EnterWriteLock();
+ ClearPart(overlap, clampAddress, clampEnd);
+ Lock.ExitWriteLock();
- if (diff <= highestDiff)
- {
- ulong clampAddress = Math.Max(address, overlap.Address);
- ulong clampEnd = Math.Min(endAddress, overlap.EndAddress);
-
- ClearPart(overlap, clampAddress, clampEnd);
-
- RangeActionWithMigration(clampAddress, clampEnd - clampAddress, waitSync, _flushAction);
- }
+ RangeActionWithMigration(clampAddress, clampEnd - clampAddress, waitSync, _flushAction);
}
-
- return;
}
+
+ return;
}
// There is a migration target to call instead. This can't be changed after set so accessing it outside the lock is fine.
@@ -355,28 +416,37 @@ namespace Ryujinx.Graphics.Gpu.Memory
int rangeCount = 0;
- ref BufferModifiedRange[] overlaps = ref ThreadStaticArray.Get();
+ List> overlaps = [];
// Range list must be consistent for this operation
- lock (_lock)
+ Lock.EnterReadLock();
+ if (_migrationTarget != null)
{
- if (_migrationTarget != null)
+ rangeCount = -1;
+ }
+ else
+ {
+ // We use the non-span method here because the array is partially modified by the code, which would invalidate a span.
+ (RangeItem first, RangeItem last) = FindOverlaps(address, size);
+
+ RangeItem current = first;
+ while (last != null && current != last.Next)
{
- rangeCount = -1;
- }
- else
- {
- rangeCount = FindOverlapsNonOverlapping(address, size, ref overlaps);
+ rangeCount++;
+ overlaps.Add(current);
+ current = current.Next;
}
}
+ Lock.ExitReadLock();
if (rangeCount == -1)
{
- _migrationTarget.WaitForAndFlushRanges(address, size);
+ _migrationTarget!.WaitForAndFlushRanges(address, size);
return;
}
- else if (rangeCount == 0)
+
+ if (rangeCount == 0)
{
return;
}
@@ -388,7 +458,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
for (int i = 0; i < rangeCount; i++)
{
- BufferModifiedRange overlap = overlaps[i];
+ BufferModifiedRange overlap = overlaps[i].Value;
long diff = (long)(overlap.SyncNumber - currentSync);
@@ -406,7 +476,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
// Wait for the syncpoint.
_context.Renderer.WaitSync(currentSync + (ulong)highestDiff);
- RemoveRangesAndFlush(overlaps, rangeCount, highestDiff, currentSync, address, endAddress);
+ RemoveRangesAndFlush(overlaps.ToArray(), rangeCount, highestDiff, currentSync, address, endAddress);
}
///
@@ -419,42 +489,39 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// The action to call for each modified range
public void InheritRanges(BufferModifiedRangeList ranges, Action registerRangeAction)
{
- BufferModifiedRange[] inheritRanges;
+ ranges.Lock.EnterReadLock();
+ BufferModifiedRange[] inheritRanges = ranges.ToArray();
+ ranges.Lock.ExitReadLock();
- lock (ranges._lock)
+ // Copy over the migration from the previous range list
+
+ BufferMigration oldMigration = ranges._source;
+
+ BufferMigrationSpan span = new(ranges._parent, ranges._flushAction, oldMigration);
+ ranges._parent.IncrementReferenceCount();
+
+ if (_source == null)
{
- inheritRanges = ranges.ToArray();
+ // Create a new migration.
+ _source = new BufferMigration([span], this, _context.SyncNumber);
- lock (_lock)
- {
- // Copy over the migration from the previous range list
-
- BufferMigration oldMigration = ranges._source;
-
- BufferMigrationSpan span = new(ranges._parent, ranges._flushAction, oldMigration);
- ranges._parent.IncrementReferenceCount();
-
- if (_source == null)
- {
- // Create a new migration.
- _source = new BufferMigration([span], this, _context.SyncNumber);
-
- _context.RegisterBufferMigration(_source);
- }
- else
- {
- // Extend the migration
- _source.AddSpanToEnd(span);
- }
-
- ranges._migrationTarget = this;
-
- foreach (BufferModifiedRange range in inheritRanges)
- {
- Add(range);
- }
- }
+ _context.RegisterBufferMigration(_source);
}
+ else
+ {
+ // Extend the migration
+ _source.AddSpanToEnd(span);
+ }
+
+ ranges._migrationTarget = this;
+
+ Lock.EnterWriteLock();
+ foreach (BufferModifiedRange range in inheritRanges)
+ {
+ Add(range);
+ }
+
+ Lock.ExitWriteLock();
ulong currentSync = _context.SyncNumber;
foreach (BufferModifiedRange range in inheritRanges)
@@ -473,18 +540,18 @@ namespace Ryujinx.Graphics.Gpu.Memory
///
public void SelfMigration()
{
- lock (_lock)
- {
- BufferMigrationSpan span = new(_parent, _parent.GetSnapshotDisposeAction(), _parent.GetSnapshotFlushAction(), _source);
- BufferMigration migration = new([span], this, _context.SyncNumber);
+ BufferMigrationSpan span = new(_parent, _parent.GetSnapshotDisposeAction(),
+ _parent.GetSnapshotFlushAction(), _source);
+ BufferMigration migration = new([span], this, _context.SyncNumber);
- // Migration target is used to redirect flush actions to the latest range list,
- // so we don't need to set it here. (this range list is still the latest)
+ // Migration target is used to redirect flush actions to the latest range list,
+ // so we don't need to set it here. (this range list is still the latest)
- _context.RegisterBufferMigration(migration);
+ _context.RegisterBufferMigration(migration);
- _source = migration;
- }
+ Lock.EnterWriteLock();
+ _source = migration;
+ Lock.ExitWriteLock();
}
///
@@ -493,13 +560,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// The migration to remove
public void RemoveMigration(BufferMigration migration)
{
- lock (_lock)
+ Lock.EnterWriteLock();
+ if (_source == migration)
{
- if (_source == migration)
- {
- _source = null;
- }
+ _source = null;
}
+
+ Lock.ExitWriteLock();
}
private void ClearPart(BufferModifiedRange overlap, ulong address, ulong endAddress)
@@ -526,33 +593,85 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Size to clear
public void Clear(ulong address, ulong size)
{
- lock (_lock)
+ ulong endAddress = address + size;
+ Lock.EnterWriteLock();
+ (RangeItem first, RangeItem last) = FindOverlaps(address, size);
+
+ if (first is null)
{
- // This function can be called from any thread, so it cannot use the arrays for background or foreground.
- BufferModifiedRange[] toClear = new BufferModifiedRange[1];
+ Lock.ExitWriteLock();
+ return;
+ }
- int rangeCount = FindOverlapsNonOverlapping(address, size, ref toClear);
+ BufferModifiedRange buffPost = null;
+ bool extendsPost = false;
+ bool extendsPre = false;
- ulong endAddress = address + size;
-
- for (int i = 0; i < rangeCount; i++)
+ if (first == last)
+ {
+ if (first.Address < address)
{
- BufferModifiedRange overlap = toClear[i];
+ first.Value.Size = address - first.Address;
+ extendsPre = true;
- ClearPart(overlap, address, endAddress);
+ if (first.EndAddress > endAddress)
+ {
+ buffPost = new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
+ first.Value.SyncNumber, first.Value.Parent);
+ extendsPost = true;
+ }
+ }
+ else
+ {
+ if (first.EndAddress > endAddress)
+ {
+ first.Value.Size = first.EndAddress - endAddress;
+ first.Value.Address = endAddress;
+ }
+ else
+ {
+ Remove(first.Value);
+ }
}
- }
- }
- ///
- /// Clear all modified ranges.
- ///
- public void Clear()
- {
- lock (_lock)
- {
- Count = 0;
+ if (extendsPre && extendsPost)
+ {
+ Add(buffPost);
+ }
+
+ Lock.ExitWriteLock();
+ return;
}
+
+ BufferModifiedRange buffPre = null;
+
+ if (first.Address < address)
+ {
+ buffPre = new BufferModifiedRange(first.Address, address - first.Address,
+ first.Value.SyncNumber, first.Value.Parent);
+ extendsPre = true;
+ }
+
+ if (last.EndAddress > endAddress)
+ {
+ buffPost = new BufferModifiedRange(endAddress, last.EndAddress - endAddress,
+ last.Value.SyncNumber, last.Value.Parent);
+ extendsPost = true;
+ }
+
+ RemoveRange(first, last);
+
+ if (extendsPre)
+ {
+ Add(buffPre);
+ }
+
+ if (extendsPost)
+ {
+ Add(buffPost);
+ }
+
+ Lock.ExitWriteLock();
}
}
}
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs
index 8a9f37658..c299731f8 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs
@@ -1,4 +1,5 @@
using Ryujinx.Graphics.Shader;
+using System;
using System.Runtime.CompilerServices;
namespace Ryujinx.Graphics.Gpu.Memory
@@ -7,6 +8,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// Pipeline stages that can modify buffer data, as well as flags indicating storage usage.
/// Must match ShaderStage for the shader stages, though anything after that can be in any order.
///
+ [Flags]
internal enum BufferStage : byte
{
Compute,
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs b/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
index 6efb7f334..95e43e341 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
@@ -690,11 +690,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (_pageTable[l0] == null)
{
_pageTable[l0] = new ulong[PtLvl1Size];
-
- for (ulong index = 0; index < PtLvl1Size; index++)
- {
- _pageTable[l0][index] = PteUnmapped;
- }
+
+ Array.Fill(_pageTable[l0], PteUnmapped);
}
_pageTable[l0][l1] = pte;
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/VirtualRangeCache.cs b/src/Ryujinx.Graphics.Gpu/Memory/VirtualRangeCache.cs
index ac25b3e5d..06253cb30 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/VirtualRangeCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/VirtualRangeCache.cs
@@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
///
/// Represents a GPU virtual memory range.
///
- private readonly struct VirtualRange : IRange
+ private class VirtualRange : INonOverlappingRange
{
///
/// GPU virtual address where the range starts.
@@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
///
/// Size of the range in bytes.
///
- public ulong Size { get; }
+ public ulong Size { get; private set; }
///
/// GPU virtual address where the range ends.
@@ -35,7 +35,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
///
/// Physical regions where the GPU virtual region is mapped.
///
- public MultiRange Range { get; }
+ public MultiRange Range { get; private set; }
///
/// Creates a new virtual memory range.
@@ -60,10 +60,14 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
return Address < address + size && address < EndAddress;
}
+
+ public INonOverlappingRange Split(ulong splitAddress)
+ {
+ throw new NotImplementedException();
+ }
}
- private readonly RangeList _virtualRanges;
- private VirtualRange[] _virtualRangeOverlaps;
+ private readonly NonOverlappingRangeList _virtualRanges;
private readonly ConcurrentQueue _deferredUnmaps;
private int _hasDeferredUnmaps;
@@ -75,7 +79,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
_memoryManager = memoryManager;
_virtualRanges = [];
- _virtualRangeOverlaps = new VirtualRange[BufferCache.OverlapsBufferInitialCapacity];
_deferredUnmaps = new ConcurrentQueue();
}
@@ -106,19 +109,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// True if the range already existed, false if a new one was created and added
public bool TryGetOrAddRange(ulong gpuVa, ulong size, out MultiRange range)
{
- VirtualRange[] overlaps = _virtualRangeOverlaps;
- int overlapsCount;
-
if (Interlocked.Exchange(ref _hasDeferredUnmaps, 0) != 0)
{
while (_deferredUnmaps.TryDequeue(out VirtualRange unmappedRange))
{
- overlapsCount = _virtualRanges.FindOverlapsNonOverlapping(unmappedRange.Address, unmappedRange.Size, ref overlaps);
-
- for (int index = 0; index < overlapsCount; index++)
- {
- _virtualRanges.Remove(overlaps[index]);
- }
+ _virtualRanges.RemoveRange(unmappedRange.Address, unmappedRange.Size);
}
}
@@ -126,27 +121,22 @@ namespace Ryujinx.Graphics.Gpu.Memory
ulong originalVa = gpuVa;
- overlapsCount = _virtualRanges.FindOverlapsNonOverlapping(gpuVa, size, ref overlaps);
-
- if (overlapsCount != 0)
+ _virtualRanges.Lock.EnterWriteLock();
+ (RangeItem first, RangeItem last) = _virtualRanges.FindOverlaps(gpuVa, size);
+
+ if (first is not null)
{
// The virtual range already exists. We just need to check if our range fits inside
// the existing one, and if not, we must extend the existing one.
ulong endAddress = gpuVa + size;
- VirtualRange overlap0 = overlaps[0];
- if (overlap0.Address > gpuVa || overlap0.EndAddress < endAddress)
+ if (first.Address > gpuVa || first.EndAddress < endAddress)
{
- for (int index = 0; index < overlapsCount; index++)
- {
- VirtualRange virtualRange = overlaps[index];
-
- gpuVa = Math.Min(gpuVa, virtualRange.Address);
- endAddress = Math.Max(endAddress, virtualRange.EndAddress);
-
- _virtualRanges.Remove(virtualRange);
- }
+ gpuVa = Math.Min(gpuVa, first.Address);
+ endAddress = Math.Max(endAddress, last.EndAddress);
+
+ _virtualRanges.RemoveRange(first, last);
ulong newSize = endAddress - gpuVa;
MultiRange newRange = _memoryManager.GetPhysicalRegions(gpuVa, newSize);
@@ -157,8 +147,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
else
{
- found = overlap0.Range.Count == 1 || IsSparseAligned(overlap0.Range);
- range = overlap0.Range.Slice(gpuVa - overlap0.Address, size);
+ found = first.Value.Range.Count == 1 || IsSparseAligned(first.Value.Range);
+ range = first.Value.Range.Slice(gpuVa - first.Address, size);
}
}
else
@@ -170,8 +160,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
_virtualRanges.Add(virtualRange);
}
-
- ShrinkOverlapsBufferIfNeeded();
+ _virtualRanges.Lock.ExitWriteLock();
// If the range is not properly aligned for sparse mapping,
// let's just force it to a single range.
@@ -221,16 +210,5 @@ namespace Ryujinx.Graphics.Gpu.Memory
return true;
}
-
- ///
- /// Resizes the temporary buffer used for range list intersection results, if it has grown too much.
- ///
- private void ShrinkOverlapsBufferIfNeeded()
- {
- if (_virtualRangeOverlaps.Length > BufferCache.OverlapsBufferMaxCapacity)
- {
- Array.Resize(ref _virtualRangeOverlaps, BufferCache.OverlapsBufferMaxCapacity);
- }
- }
}
}
diff --git a/src/Ryujinx.HLE/Debugger/BreakpointManager.cs b/src/Ryujinx.HLE/Debugger/BreakpointManager.cs
new file mode 100644
index 000000000..bf462a781
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/BreakpointManager.cs
@@ -0,0 +1,203 @@
+using Ryujinx.Common;
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.Memory;
+using System.Collections.Concurrent;
+using System.Linq;
+
+namespace Ryujinx.HLE.Debugger
+{
+ internal class Breakpoint
+ {
+ public byte[] OriginalData { get; }
+
+ public bool IsStep { get; }
+
+ public Breakpoint(byte[] originalData, bool isStep)
+ {
+ OriginalData = originalData;
+ IsStep = isStep;
+ }
+ }
+
+ ///
+ /// Manages software breakpoints for the debugger.
+ ///
+ public class BreakpointManager
+ {
+ private readonly Debugger _debugger;
+ private readonly ConcurrentDictionary _breakpoints = new();
+
+ private static readonly byte[] _aarch64BreakInstruction = { 0x00, 0x00, 0x20, 0xD4 }; // BRK #0
+ private static readonly byte[] _aarch32BreakInstruction = { 0xFE, 0xDE, 0xFF, 0xE7 }; // TRAP
+ private static readonly byte[] _aarch32ThumbBreakInstruction = { 0x80, 0xB6 };
+
+ public BreakpointManager(Debugger debugger)
+ {
+ _debugger = debugger;
+ }
+
+ ///
+ /// Sets a software breakpoint at a specified address.
+ ///
+ /// The memory address to set the breakpoint at.
+ /// The length of the instruction to replace.
+ /// Indicates if this is a single-step breakpoint.
+ /// True if the breakpoint was set successfully; otherwise, false.
+ public bool SetBreakPoint(ulong address, ulong length, bool isStep = false)
+ {
+ if (_breakpoints.ContainsKey(address))
+ {
+ return false;
+ }
+
+ byte[] breakInstruction = GetBreakInstruction(length);
+ if (breakInstruction == null)
+ {
+ Logger.Error?.Print(LogClass.GdbStub, $"Unsupported instruction length for breakpoint: {length}");
+ return false;
+ }
+
+ var originalInstruction = new byte[length];
+ if (!ReadMemory(address, originalInstruction))
+ {
+ Logger.Error?.Print(LogClass.GdbStub, $"Failed to read memory at 0x{address:X16} to set breakpoint.");
+ return false;
+ }
+
+ if (!WriteMemory(address, breakInstruction))
+ {
+ Logger.Error?.Print(LogClass.GdbStub, $"Failed to write breakpoint at 0x{address:X16}.");
+ return false;
+ }
+
+ var breakpoint = new Breakpoint(originalInstruction, isStep);
+ if (_breakpoints.TryAdd(address, breakpoint))
+ {
+ Logger.Debug?.Print(LogClass.GdbStub, $"Breakpoint set at 0x{address:X16}");
+ return true;
+ }
+
+ Logger.Error?.Print(LogClass.GdbStub, $"Failed to add breakpoint at 0x{address:X16}.");
+ return false;
+ }
+
+ ///
+ /// Clears a software breakpoint at a specified address.
+ ///
+ /// The memory address of the breakpoint to clear.
+ /// The length of the instruction (unused).
+ /// True if the breakpoint was cleared successfully; otherwise, false.
+ public bool ClearBreakPoint(ulong address, ulong length)
+ {
+ if (_breakpoints.TryGetValue(address, out Breakpoint breakpoint))
+ {
+ if (!WriteMemory(address, breakpoint.OriginalData))
+ {
+ Logger.Error?.Print(LogClass.GdbStub, $"Failed to restore original instruction at 0x{address:X16} to clear breakpoint.");
+ return false;
+ }
+
+ _breakpoints.TryRemove(address, out _);
+ Logger.Debug?.Print(LogClass.GdbStub, $"Breakpoint cleared at 0x{address:X16}");
+ return true;
+ }
+
+ Logger.Warning?.Print(LogClass.GdbStub, $"No breakpoint found at address 0x{address:X16}");
+ return false;
+ }
+
+ ///
+ /// Clears all currently set software breakpoints.
+ ///
+ public void ClearAll()
+ {
+ foreach (var bp in _breakpoints)
+ {
+ if (!WriteMemory(bp.Key, bp.Value.OriginalData))
+ {
+ Logger.Error?.Print(LogClass.GdbStub, $"Failed to restore original instruction at 0x{bp.Key:X16} while clearing all breakpoints.");
+ }
+
+ }
+ _breakpoints.Clear();
+ Logger.Debug?.Print(LogClass.GdbStub, "All breakpoints cleared.");
+ }
+
+ ///
+ /// Clears all currently set single-step software breakpoints.
+ ///
+ public void ClearAllStepBreakpoints()
+ {
+ var stepBreakpoints = _breakpoints.Where(p => p.Value.IsStep).ToList();
+
+ if (stepBreakpoints.Count == 0)
+ {
+ return;
+ }
+
+ foreach (var bp in stepBreakpoints)
+ {
+ if (_breakpoints.TryRemove(bp.Key, out Breakpoint removedBreakpoint))
+ {
+ WriteMemory(bp.Key, removedBreakpoint.OriginalData);
+ }
+ }
+
+ Logger.Debug?.Print(LogClass.GdbStub, "All step breakpoints cleared.");
+ }
+
+
+ private byte[] GetBreakInstruction(ulong length)
+ {
+ if (_debugger.IsProcessAarch32)
+ {
+ if (length == 2)
+ {
+ return _aarch32ThumbBreakInstruction;
+ }
+
+ if (length == 4)
+ {
+ return _aarch32BreakInstruction;
+ }
+ }
+ else
+ {
+ if (length == 4)
+ {
+ return _aarch64BreakInstruction;
+ }
+ }
+
+ return null;
+ }
+
+ private bool ReadMemory(ulong address, byte[] data)
+ {
+ try
+ {
+ _debugger.DebugProcess.CpuMemory.Read(address, data);
+ return true;
+ }
+ catch (InvalidMemoryRegionException)
+ {
+ return false;
+ }
+ }
+
+ private bool WriteMemory(ulong address, byte[] data)
+ {
+ try
+ {
+ _debugger.DebugProcess.CpuMemory.Write(address, data);
+ _debugger.DebugProcess.InvalidateCacheRegion(address, (ulong)data.Length);
+ return true;
+ }
+ catch (InvalidMemoryRegionException)
+ {
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/DebugState.cs b/src/Ryujinx.HLE/Debugger/DebugState.cs
new file mode 100644
index 000000000..d2efa2bff
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/DebugState.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.HLE.Debugger
+{
+ public enum DebugState
+ {
+ Running,
+ Stopping,
+ Stopped,
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/Debugger.cs b/src/Ryujinx.HLE/Debugger/Debugger.cs
new file mode 100644
index 000000000..7a626b840
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/Debugger.cs
@@ -0,0 +1,1327 @@
+using ARMeilleure.State;
+using Ryujinx.Common;
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Kernel;
+using Ryujinx.HLE.HOS.Kernel.Process;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.Memory;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using IExecutionContext = Ryujinx.Cpu.IExecutionContext;
+
+namespace Ryujinx.HLE.Debugger
+{
+ public class Debugger : IDisposable
+ {
+ internal Switch Device { get; private set; }
+
+ public ushort GdbStubPort { get; private set; }
+
+ private TcpListener ListenerSocket;
+ private Socket ClientSocket = null;
+ private NetworkStream ReadStream = null;
+ private NetworkStream WriteStream = null;
+ private BlockingCollection Messages = new BlockingCollection(1);
+ private Thread DebuggerThread;
+ private Thread MessageHandlerThread;
+ private bool _shuttingDown = false;
+ private ManualResetEventSlim _breakHandlerEvent = new ManualResetEventSlim(false);
+
+ private ulong? cThread;
+ private ulong? gThread;
+
+ private BreakpointManager BreakpointManager;
+
+ private string previousThreadListXml = "";
+
+ public Debugger(Switch device, ushort port)
+ {
+ Device = device;
+ GdbStubPort = port;
+
+ ARMeilleure.Optimizations.EnableDebugging = true;
+
+ DebuggerThread = new Thread(DebuggerThreadMain);
+ DebuggerThread.Start();
+ MessageHandlerThread = new Thread(MessageHandlerMain);
+ MessageHandlerThread.Start();
+ BreakpointManager = new BreakpointManager(this);
+ }
+
+ internal KProcess Process => Device.System?.DebugGetApplicationProcess();
+ internal IDebuggableProcess DebugProcess => Device.System?.DebugGetApplicationProcessDebugInterface();
+ private KThread[] GetThreads() => DebugProcess.GetThreadUids().Select(x => DebugProcess.GetThread(x)).ToArray();
+ internal bool IsProcessAarch32 => DebugProcess.GetThread(gThread.Value).Context.IsAarch32;
+ private KernelContext KernelContext => Device.System.KernelContext;
+
+ const int GdbRegisterCount64 = 68;
+ const int GdbRegisterCount32 = 66;
+ /* FPCR = FPSR & ~FpcrMask
+ All of FPCR's bits are reserved in FPCR and vice versa,
+ see ARM's documentation. */
+ private const uint FpcrMask = 0xfc1fffff;
+
+ private string GdbReadRegister64(IExecutionContext state, int gdbRegId)
+ {
+ switch (gdbRegId)
+ {
+ case >= 0 and <= 31:
+ return ToHex(BitConverter.GetBytes(state.GetX(gdbRegId)));
+ case 32:
+ return ToHex(BitConverter.GetBytes(state.DebugPc));
+ case 33:
+ return ToHex(BitConverter.GetBytes(state.Pstate));
+ case >= 34 and <= 65:
+ return ToHex(state.GetV(gdbRegId - 34).ToArray());
+ case 66:
+ return ToHex(BitConverter.GetBytes((uint)state.Fpsr));
+ case 67:
+ return ToHex(BitConverter.GetBytes((uint)state.Fpcr));
+ default:
+ return null;
+ }
+ }
+
+ private bool GdbWriteRegister64(IExecutionContext state, int gdbRegId, StringStream ss)
+ {
+ switch (gdbRegId)
+ {
+ case >= 0 and <= 31:
+ {
+ ulong value = ss.ReadLengthAsLEHex(16);
+ state.SetX(gdbRegId, value);
+ return true;
+ }
+ case 32:
+ {
+ ulong value = ss.ReadLengthAsLEHex(16);
+ state.DebugPc = value;
+ return true;
+ }
+ case 33:
+ {
+ ulong value = ss.ReadLengthAsLEHex(8);
+ state.Pstate = (uint)value;
+ return true;
+ }
+ case >= 34 and <= 65:
+ {
+ ulong value0 = ss.ReadLengthAsLEHex(16);
+ ulong value1 = ss.ReadLengthAsLEHex(16);
+ state.SetV(gdbRegId - 34, new V128(value0, value1));
+ return true;
+ }
+ case 66:
+ {
+ ulong value = ss.ReadLengthAsLEHex(8);
+ state.Fpsr = (uint)value;
+ return true;
+ }
+ case 67:
+ {
+ ulong value = ss.ReadLengthAsLEHex(8);
+ state.Fpcr = (uint)value;
+ return true;
+ }
+ default:
+ return false;
+ }
+ }
+
+ private string GdbReadRegister32(IExecutionContext state, int gdbRegId)
+ {
+ switch (gdbRegId)
+ {
+ case >= 0 and <= 14:
+ return ToHex(BitConverter.GetBytes((uint)state.GetX(gdbRegId)));
+ case 15:
+ return ToHex(BitConverter.GetBytes((uint)state.DebugPc));
+ case 16:
+ return ToHex(BitConverter.GetBytes((uint)state.Pstate));
+ case >= 17 and <= 32:
+ return ToHex(state.GetV(gdbRegId - 17).ToArray());
+ case >= 33 and <= 64:
+ int reg = (gdbRegId - 33);
+ int n = reg / 2;
+ int shift = reg % 2;
+ ulong value = state.GetV(n).Extract(shift);
+ return ToHex(BitConverter.GetBytes(value));
+ case 65:
+ uint fpscr = (uint)state.Fpsr | (uint)state.Fpcr;
+ return ToHex(BitConverter.GetBytes(fpscr));
+ default:
+ return null;
+ }
+ }
+
+ private bool GdbWriteRegister32(IExecutionContext state, int gdbRegId, StringStream ss)
+ {
+ switch (gdbRegId)
+ {
+ case >= 0 and <= 14:
+ {
+ ulong value = ss.ReadLengthAsLEHex(8);
+ state.SetX(gdbRegId, value);
+ return true;
+ }
+ case 15:
+ {
+ ulong value = ss.ReadLengthAsLEHex(8);
+ state.DebugPc = value;
+ return true;
+ }
+ case 16:
+ {
+ ulong value = ss.ReadLengthAsLEHex(8);
+ state.Pstate = (uint)value;
+ return true;
+ }
+ case >= 17 and <= 32:
+ {
+ ulong value0 = ss.ReadLengthAsLEHex(16);
+ ulong value1 = ss.ReadLengthAsLEHex(16);
+ state.SetV(gdbRegId - 17, new V128(value0, value1));
+ return true;
+ }
+ case >= 33 and <= 64:
+ {
+ ulong value = ss.ReadLengthAsLEHex(16);
+ int regId = (gdbRegId - 33);
+ int regNum = regId / 2;
+ int shift = regId % 2;
+ V128 reg = state.GetV(regNum);
+ reg.Insert(shift, value);
+ return true;
+ }
+ case 65:
+ {
+ ulong value = ss.ReadLengthAsLEHex(8);
+ state.Fpsr = (uint)value & FpcrMask;
+ state.Fpcr = (uint)value & ~FpcrMask;
+ return true;
+ }
+ default:
+ return false;
+ }
+ }
+
+ private void MessageHandlerMain()
+ {
+ while (!_shuttingDown)
+ {
+ IMessage msg = Messages.Take();
+ try {
+ switch (msg)
+ {
+ case BreakInMessage:
+ Logger.Notice.Print(LogClass.GdbStub, "Break-in requested");
+ CommandInterrupt();
+ break;
+
+ case SendNackMessage:
+ WriteStream.WriteByte((byte)'-');
+ break;
+
+ case CommandMessage { Command: var cmd }:
+ Logger.Debug?.Print(LogClass.GdbStub, $"Received Command: {cmd}");
+ WriteStream.WriteByte((byte)'+');
+ ProcessCommand(cmd);
+ break;
+
+ case ThreadBreakMessage { Context: var ctx }:
+ DebugProcess.DebugStop();
+ gThread = cThread = ctx.ThreadUid;
+ _breakHandlerEvent.Set();
+ Reply($"T05thread:{ctx.ThreadUid:x};");
+ break;
+
+ case KillMessage:
+ return;
+ }
+ }
+ catch (IOException e)
+ {
+ Logger.Error?.Print(LogClass.GdbStub, "Error while processing GDB messages", e);
+ }
+ catch (NullReferenceException e)
+ {
+ Logger.Error?.Print(LogClass.GdbStub, "Error while processing GDB messages", e);
+ }
+ }
+ }
+
+ private void ProcessCommand(string cmd)
+ {
+ StringStream ss = new StringStream(cmd);
+
+ switch (ss.ReadChar())
+ {
+ case '!':
+ if (!ss.IsEmpty())
+ {
+ goto unknownCommand;
+ }
+
+ // Enable extended mode
+ ReplyOK();
+ break;
+ case '?':
+ if (!ss.IsEmpty())
+ {
+ goto unknownCommand;
+ }
+
+ CommandQuery();
+ break;
+ case 'c':
+ CommandContinue(ss.IsEmpty() ? null : ss.ReadRemainingAsHex());
+ break;
+ case 'D':
+ if (!ss.IsEmpty())
+ {
+ goto unknownCommand;
+ }
+
+ CommandDetach();
+ break;
+ case 'g':
+ if (!ss.IsEmpty())
+ {
+ goto unknownCommand;
+ }
+
+ CommandReadRegisters();
+ break;
+ case 'G':
+ CommandWriteRegisters(ss);
+ break;
+ case 'H':
+ {
+ char op = ss.ReadChar();
+ ulong? threadId = ss.ReadRemainingAsThreadUid();
+ CommandSetThread(op, threadId);
+ break;
+ }
+ case 'k':
+ Logger.Notice.Print(LogClass.GdbStub, "Kill request received, detach instead");
+ Reply("");
+ CommandDetach();
+ break;
+ case 'm':
+ {
+ ulong addr = ss.ReadUntilAsHex(',');
+ ulong len = ss.ReadRemainingAsHex();
+ CommandReadMemory(addr, len);
+ break;
+ }
+ case 'M':
+ {
+ ulong addr = ss.ReadUntilAsHex(',');
+ ulong len = ss.ReadUntilAsHex(':');
+ CommandWriteMemory(addr, len, ss);
+ break;
+ }
+ case 'p':
+ {
+ ulong gdbRegId = ss.ReadRemainingAsHex();
+ CommandReadRegister((int)gdbRegId);
+ break;
+ }
+ case 'P':
+ {
+ ulong gdbRegId = ss.ReadUntilAsHex('=');
+ CommandWriteRegister((int)gdbRegId, ss);
+ break;
+ }
+ case 'q':
+ if (ss.ConsumeRemaining("GDBServerVersion"))
+ {
+ Reply($"name:Ryujinx;version:{ReleaseInformation.Version};");
+ break;
+ }
+
+ if (ss.ConsumeRemaining("HostInfo"))
+ {
+ if (IsProcessAarch32)
+ {
+ Reply(
+ $"triple:{ToHex("arm-unknown-linux-android")};endian:little;ptrsize:4;hostname:{ToHex("Ryujinx")};");
+ }
+ else
+ {
+ Reply(
+ $"triple:{ToHex("aarch64-unknown-linux-android")};endian:little;ptrsize:8;hostname:{ToHex("Ryujinx")};");
+ }
+ break;
+ }
+
+ if (ss.ConsumeRemaining("ProcessInfo"))
+ {
+ if (IsProcessAarch32)
+ {
+ Reply(
+ $"pid:1;cputype:12;cpusubtype:0;triple:{ToHex("arm-unknown-linux-android")};ostype:unknown;vendor:none;endian:little;ptrsize:4;");
+ }
+ else
+ {
+ Reply(
+ $"pid:1;cputype:100000c;cpusubtype:0;triple:{ToHex("aarch64-unknown-linux-android")};ostype:unknown;vendor:none;endian:little;ptrsize:8;");
+ }
+ break;
+ }
+
+ if (ss.ConsumePrefix("Supported:") || ss.ConsumeRemaining("Supported"))
+ {
+ Reply("PacketSize=10000;qXfer:features:read+;qXfer:threads:read+;vContSupported+");
+ break;
+ }
+
+ if (ss.ConsumePrefix("Rcmd,"))
+ {
+ string hexCommand = ss.ReadRemaining();
+ HandleQRcmdCommand(hexCommand);
+ break;
+ }
+
+ if (ss.ConsumeRemaining("fThreadInfo"))
+ {
+ Reply($"m{string.Join(",", DebugProcess.GetThreadUids().Select(x => $"{x:x}"))}");
+ break;
+ }
+
+ if (ss.ConsumeRemaining("sThreadInfo"))
+ {
+ Reply("l");
+ break;
+ }
+
+ if (ss.ConsumePrefix("ThreadExtraInfo,"))
+ {
+ ulong? threadId = ss.ReadRemainingAsThreadUid();
+ if (threadId == null)
+ {
+ ReplyError();
+ break;
+ }
+
+ if (DebugProcess.IsThreadPaused(DebugProcess.GetThread(threadId.Value)))
+ {
+ Reply(ToHex("Paused"));
+ }
+ else
+ {
+ Reply(ToHex("Running"));
+ }
+ break;
+ }
+
+ if (ss.ConsumePrefix("Xfer:threads:read:"))
+ {
+ ss.ReadUntil(':');
+ ulong offset = ss.ReadUntilAsHex(',');
+ ulong len = ss.ReadRemainingAsHex();
+
+ var data = "";
+ if (offset > 0)
+ {
+ data = previousThreadListXml;
+ } else
+ {
+ previousThreadListXml = data = GetThreadListXml();
+ }
+
+ if (offset >= (ulong)data.Length)
+ {
+ Reply("l");
+ break;
+ }
+
+ if (len >= (ulong)data.Length - offset)
+ {
+ Reply("l" + ToBinaryFormat(data.Substring((int)offset)));
+ break;
+ }
+ else
+ {
+ Reply("m" + ToBinaryFormat(data.Substring((int)offset, (int)len)));
+ break;
+ }
+ }
+
+ if (ss.ConsumePrefix("Xfer:features:read:"))
+ {
+ string feature = ss.ReadUntil(':');
+ ulong offset = ss.ReadUntilAsHex(',');
+ ulong len = ss.ReadRemainingAsHex();
+
+ if (feature == "target.xml")
+ {
+ feature = IsProcessAarch32 ? "target32.xml" : "target64.xml";
+ }
+
+ string data;
+ if (RegisterInformation.Features.TryGetValue(feature, out data))
+ {
+ if (offset >= (ulong)data.Length)
+ {
+ Reply("l");
+ break;
+ }
+
+ if (len >= (ulong)data.Length - offset)
+ {
+ Reply("l" + ToBinaryFormat(data.Substring((int)offset)));
+ break;
+ }
+ else
+ {
+ Reply("m" + ToBinaryFormat(data.Substring((int)offset, (int)len)));
+ break;
+ }
+ }
+ else
+ {
+ Reply("E00"); // Invalid annex
+ break;
+ }
+ }
+
+ goto unknownCommand;
+ case 'Q':
+ goto unknownCommand;
+ case 's':
+ CommandStep(ss.IsEmpty() ? null : ss.ReadRemainingAsHex());
+ break;
+ case 'T':
+ {
+ ulong? threadId = ss.ReadRemainingAsThreadUid();
+ CommandIsAlive(threadId);
+ break;
+ }
+ case 'v':
+ if (ss.ConsumePrefix("Cont"))
+ {
+ if (ss.ConsumeRemaining("?"))
+ {
+ Reply("vCont;c;C;s;S");
+ break;
+ }
+
+ if (ss.ConsumePrefix(";"))
+ {
+ HandleVContCommand(ss);
+ break;
+ }
+
+ goto unknownCommand;
+ }
+ if (ss.ConsumeRemaining("MustReplyEmpty"))
+ {
+ Reply("");
+ break;
+ }
+ goto unknownCommand;
+ case 'Z':
+ {
+ string type = ss.ReadUntil(',');
+ ulong addr = ss.ReadUntilAsHex(',');
+ ulong len = ss.ReadLengthAsHex(1);
+ string extra = ss.ReadRemaining();
+
+ if (extra.Length > 0)
+ {
+ Logger.Notice.Print(LogClass.GdbStub, $"Unsupported Z command extra data: {extra}");
+ ReplyError();
+ return;
+ }
+
+ switch (type)
+ {
+ case "0": // Software breakpoint
+ if (!BreakpointManager.SetBreakPoint(addr, len, false))
+ {
+ ReplyError();
+ return;
+ }
+ ReplyOK();
+ return;
+ case "1": // Hardware breakpoint
+ case "2": // Write watchpoint
+ case "3": // Read watchpoint
+ case "4": // Access watchpoint
+ ReplyError();
+ return;
+ default:
+ ReplyError();
+ return;
+ }
+ }
+ case 'z':
+ {
+ string type = ss.ReadUntil(',');
+ ss.ConsumePrefix(",");
+ ulong addr = ss.ReadUntilAsHex(',');
+ ulong len = ss.ReadLengthAsHex(1);
+ string extra = ss.ReadRemaining();
+
+ if (extra.Length > 0)
+ {
+ Logger.Notice.Print(LogClass.GdbStub, $"Unsupported z command extra data: {extra}");
+ ReplyError();
+ return;
+ }
+
+ switch (type)
+ {
+ case "0": // Software breakpoint
+ if (!BreakpointManager.ClearBreakPoint(addr, len))
+ {
+ ReplyError();
+ return;
+ }
+ ReplyOK();
+ return;
+ case "1": // Hardware breakpoint
+ case "2": // Write watchpoint
+ case "3": // Read watchpoint
+ case "4": // Access watchpoint
+ ReplyError();
+ return;
+ default:
+ ReplyError();
+ return;
+ }
+ }
+ default:
+ unknownCommand:
+ Logger.Notice.Print(LogClass.GdbStub, $"Unknown command: {cmd}");
+ Reply("");
+ break;
+ }
+ }
+
+ enum VContAction
+ {
+ None,
+ Continue,
+ Stop,
+ Step
+ }
+
+ record VContPendingAction(VContAction Action, ushort? Signal = null);
+
+ private void HandleVContCommand(StringStream ss)
+ {
+ string[] rawActions = ss.ReadRemaining().Split(';', StringSplitOptions.RemoveEmptyEntries);
+
+ var threadActionMap = new Dictionary();
+ foreach (var thread in GetThreads())
+ {
+ threadActionMap[thread.ThreadUid] = new VContPendingAction(VContAction.None);
+ }
+
+ VContAction defaultAction = VContAction.None;
+
+ // For each inferior thread, the *leftmost* action with a matching thread-id is applied.
+ for (int i = rawActions.Length - 1; i >= 0; i--)
+ {
+ var rawAction = rawActions[i];
+ var stream = new StringStream(rawAction);
+
+ char cmd = stream.ReadChar();
+ VContAction action = cmd switch
+ {
+ 'c' => VContAction.Continue,
+ 'C' => VContAction.Continue,
+ 's' => VContAction.Step,
+ 'S' => VContAction.Step,
+ 't' => VContAction.Stop,
+ _ => VContAction.None
+ };
+
+ // Note: We don't support signals yet.
+ ushort? signal = null;
+ if (cmd == 'C' || cmd == 'S')
+ {
+ signal = (ushort)stream.ReadLengthAsHex(2);
+ }
+
+ ulong? threadId = null;
+ if (stream.ConsumePrefix(":"))
+ {
+ threadId = stream.ReadRemainingAsThreadUid();
+ }
+
+ if (threadId.HasValue)
+ {
+ if (threadActionMap.ContainsKey(threadId.Value)) {
+ threadActionMap[threadId.Value] = new VContPendingAction(action, signal);
+ }
+ }
+ else
+ {
+ foreach (var row in threadActionMap.ToList())
+ {
+ threadActionMap[row.Key] = new VContPendingAction(action, signal);
+ }
+
+ if (action == VContAction.Continue) {
+ defaultAction = action;
+ } else {
+ Logger.Warning?.Print(LogClass.GdbStub, $"Received vCont command with unsupported default action: {rawAction}");
+ }
+ }
+ }
+
+ bool hasError = false;
+
+ foreach (var (threadUid, action) in threadActionMap)
+ {
+ if (action.Action == VContAction.Step)
+ {
+ var thread = DebugProcess.GetThread(threadUid);
+ if (!DebugProcess.DebugStep(thread)) {
+ hasError = true;
+ }
+ }
+ }
+
+ // If we receive "vCont;c", just continue the process.
+ // If we receive something like "vCont;c:2e;c:2f" (IDA Pro will send commands like this), continue these threads.
+ // For "vCont;s:2f;c", `DebugProcess.DebugStep()` will continue and suspend other threads if needed, so we don't do anything here.
+ if (threadActionMap.Values.All(a => a.Action == VContAction.Continue))
+ {
+ DebugProcess.DebugContinue();
+ } else if (defaultAction == VContAction.None) {
+ foreach (var (threadUid, action) in threadActionMap)
+ {
+ if (action.Action == VContAction.Continue)
+ {
+ DebugProcess.DebugContinue(DebugProcess.GetThread(threadUid));
+ }
+ }
+ }
+
+ if (hasError)
+ {
+ ReplyError();
+ }
+ else
+ {
+ ReplyOK();
+ }
+
+ foreach (var (threadUid, action) in threadActionMap)
+ {
+ if (action.Action == VContAction.Step)
+ {
+ gThread = cThread = threadUid;
+ Reply($"T05thread:{threadUid:x};");
+ }
+ }
+ }
+
+ private string GetThreadListXml()
+ {
+ var sb = new StringBuilder();
+ sb.Append("\n");
+
+ foreach (var thread in GetThreads())
+ {
+ string threadName = System.Security.SecurityElement.Escape(thread.GetThreadName());
+ sb.Append($"{(DebugProcess.IsThreadPaused(thread) ? "Paused" : "Running")}\n");
+ }
+
+ sb.Append("");
+ return sb.ToString();
+ }
+
+ void CommandQuery()
+ {
+ // GDB is performing initial contact. Stop everything.
+ DebugProcess.DebugStop();
+ gThread = cThread = DebugProcess.GetThreadUids().First();
+ Reply($"T05thread:{cThread:x};");
+ }
+
+ void CommandInterrupt()
+ {
+ // GDB is requesting an interrupt. Stop everything.
+ DebugProcess.DebugStop();
+ if (gThread == null || !GetThreads().Any(x => x.ThreadUid == gThread.Value))
+ {
+ gThread = cThread = DebugProcess.GetThreadUids().First();
+ }
+
+ Reply($"T02thread:{gThread:x};");
+ }
+
+ void CommandContinue(ulong? newPc)
+ {
+ if (newPc.HasValue)
+ {
+ if (cThread == null)
+ {
+ ReplyError();
+ return;
+ }
+
+ DebugProcess.GetThread(cThread.Value).Context.DebugPc = newPc.Value;
+ }
+
+ DebugProcess.DebugContinue();
+ }
+
+ void CommandDetach()
+ {
+ BreakpointManager.ClearAll();
+ CommandContinue(null);
+ }
+
+ void CommandReadRegisters()
+ {
+ if (gThread == null)
+ {
+ ReplyError();
+ return;
+ }
+
+ var ctx = DebugProcess.GetThread(gThread.Value).Context;
+ string registers = "";
+ if (IsProcessAarch32)
+ {
+ for (int i = 0; i < GdbRegisterCount32; i++)
+ {
+ registers += GdbReadRegister32(ctx, i);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < GdbRegisterCount64; i++)
+ {
+ registers += GdbReadRegister64(ctx, i);
+ }
+ }
+
+ Reply(registers);
+ }
+
+ void CommandWriteRegisters(StringStream ss)
+ {
+ if (gThread == null)
+ {
+ ReplyError();
+ return;
+ }
+
+ var ctx = DebugProcess.GetThread(gThread.Value).Context;
+ if (IsProcessAarch32)
+ {
+ for (int i = 0; i < GdbRegisterCount32; i++)
+ {
+ if (!GdbWriteRegister32(ctx, i, ss))
+ {
+ ReplyError();
+ return;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < GdbRegisterCount64; i++)
+ {
+ if (!GdbWriteRegister64(ctx, i, ss))
+ {
+ ReplyError();
+ return;
+ }
+ }
+ }
+
+ if (ss.IsEmpty())
+ {
+ ReplyOK();
+ }
+ else
+ {
+ ReplyError();
+ }
+ }
+
+ void CommandSetThread(char op, ulong? threadId)
+ {
+ if (threadId == 0 || threadId == null)
+ {
+ threadId = GetThreads().First().ThreadUid;
+ }
+
+ if (DebugProcess.GetThread(threadId.Value) == null)
+ {
+ ReplyError();
+ return;
+ }
+
+ switch (op)
+ {
+ case 'c':
+ cThread = threadId;
+ ReplyOK();
+ return;
+ case 'g':
+ gThread = threadId;
+ ReplyOK();
+ return;
+ default:
+ ReplyError();
+ return;
+ }
+ }
+
+ void CommandReadMemory(ulong addr, ulong len)
+ {
+ try
+ {
+ var data = new byte[len];
+ DebugProcess.CpuMemory.Read(addr, data);
+ Reply(ToHex(data));
+ }
+ catch (InvalidMemoryRegionException)
+ {
+ // InvalidAccessHandler will show an error message, we log it again to tell user the error is from GDB (which can be ignored)
+ // TODO: Do not let InvalidAccessHandler show the error message
+ Logger.Notice.Print(LogClass.GdbStub, $"GDB failed to read memory at 0x{addr:X16}");
+ ReplyError();
+ }
+ }
+
+ void CommandWriteMemory(ulong addr, ulong len, StringStream ss)
+ {
+ try
+ {
+ var data = new byte[len];
+ for (ulong i = 0; i < len; i++)
+ {
+ data[i] = (byte)ss.ReadLengthAsHex(2);
+ }
+
+ DebugProcess.CpuMemory.Write(addr, data);
+ DebugProcess.InvalidateCacheRegion(addr, len);
+ ReplyOK();
+ }
+ catch (InvalidMemoryRegionException)
+ {
+ ReplyError();
+ }
+ }
+
+ void CommandReadRegister(int gdbRegId)
+ {
+ if (gThread == null)
+ {
+ ReplyError();
+ return;
+ }
+
+ var ctx = DebugProcess.GetThread(gThread.Value).Context;
+ string result;
+ if (IsProcessAarch32)
+ {
+ result = GdbReadRegister32(ctx, gdbRegId);
+ if (result != null)
+ {
+ Reply(result);
+ }
+ else
+ {
+ ReplyError();
+ }
+ }
+ else
+ {
+ result = GdbReadRegister64(ctx, gdbRegId);
+ if (result != null)
+ {
+ Reply(result);
+ }
+ else
+ {
+ ReplyError();
+ }
+ }
+ }
+
+ void CommandWriteRegister(int gdbRegId, StringStream ss)
+ {
+ if (gThread == null)
+ {
+ ReplyError();
+ return;
+ }
+
+ var ctx = DebugProcess.GetThread(gThread.Value).Context;
+ if (IsProcessAarch32)
+ {
+ if (GdbWriteRegister32(ctx, gdbRegId, ss) && ss.IsEmpty())
+ {
+ ReplyOK();
+ }
+ else
+ {
+ ReplyError();
+ }
+ }
+ else
+ {
+ if (GdbWriteRegister64(ctx, gdbRegId, ss) && ss.IsEmpty())
+ {
+ ReplyOK();
+ }
+ else
+ {
+ ReplyError();
+ }
+ }
+ }
+
+ private void CommandStep(ulong? newPc)
+ {
+ if (cThread == null)
+ {
+ ReplyError();
+ return;
+ }
+
+ var thread = DebugProcess.GetThread(cThread.Value);
+
+ if (newPc.HasValue)
+ {
+ thread.Context.DebugPc = newPc.Value;
+ }
+
+ if (!DebugProcess.DebugStep(thread))
+ {
+ ReplyError();
+ }
+ else
+ {
+ gThread = cThread = thread.ThreadUid;
+ Reply($"T05thread:{thread.ThreadUid:x};");
+ }
+ }
+
+ private void CommandIsAlive(ulong? threadId)
+ {
+ if (GetThreads().Any(x => x.ThreadUid == threadId))
+ {
+ ReplyOK();
+ }
+ else
+ {
+ Reply("E00");
+ }
+ }
+
+ private void HandleQRcmdCommand(string hexCommand)
+ {
+ try
+ {
+ string command = FromHex(hexCommand);
+ Logger.Debug?.Print(LogClass.GdbStub, $"Received Rcmd: {command}");
+
+ string response = command.Trim().ToLowerInvariant() switch
+ {
+ "help" => "backtrace\nbt\nregisters\nreg\nget info\n",
+ "get info" => GetProcessInfo(),
+ "backtrace" => GetStackTrace(),
+ "bt" => GetStackTrace(),
+ "registers" => GetRegisters(),
+ "reg" => GetRegisters(),
+ _ => $"Unknown command: {command}\n"
+ };
+
+ Reply(ToHex(response));
+ }
+ catch (Exception e)
+ {
+ Logger.Error?.Print(LogClass.GdbStub, $"Error processing Rcmd: {e.Message}");
+ ReplyError();
+ }
+ }
+
+ private string GetStackTrace()
+ {
+ if (gThread == null)
+ return "No thread selected\n";
+
+ if (Process == null)
+ return "No application process found\n";
+
+ return Process.Debugger.GetGuestStackTrace(DebugProcess.GetThread(gThread.Value));
+ }
+
+ private string GetRegisters()
+ {
+ if (gThread == null)
+ return "No thread selected\n";
+
+ if (Process == null)
+ return "No application process found\n";
+
+ return Process.Debugger.GetCpuRegisterPrintout(DebugProcess.GetThread(gThread.Value));
+ }
+
+ private string GetProcessInfo()
+ {
+ try
+ {
+ if (Process == null)
+ return "No application process found\n";
+
+ KProcess kProcess = Process;
+
+ var sb = new StringBuilder();
+
+ sb.AppendLine($"Program Id: 0x{kProcess.TitleId:x16}");
+ sb.AppendLine($"Application: {(kProcess.IsApplication ? 1 : 0)}");
+ sb.AppendLine("Layout:");
+ sb.AppendLine($" Alias: 0x{kProcess.MemoryManager.AliasRegionStart:x10} - 0x{kProcess.MemoryManager.AliasRegionEnd - 1:x10}");
+ sb.AppendLine($" Heap: 0x{kProcess.MemoryManager.HeapRegionStart:x10} - 0x{kProcess.MemoryManager.HeapRegionEnd - 1:x10}");
+ sb.AppendLine($" Aslr: 0x{kProcess.MemoryManager.AslrRegionStart:x10} - 0x{kProcess.MemoryManager.AslrRegionEnd - 1:x10}");
+ sb.AppendLine($" Stack: 0x{kProcess.MemoryManager.StackRegionStart:x10} - 0x{kProcess.MemoryManager.StackRegionEnd - 1:x10}");
+
+ sb.AppendLine("Modules:");
+ var debugger = kProcess.Debugger;
+ if (debugger != null)
+ {
+ var images = debugger.GetLoadedImages();
+ for (int i = 0; i < images.Count; i++)
+ {
+ var image = images[i];
+ ulong endAddress = image.BaseAddress + image.Size - 1;
+ string name = debugger.GetGuessedNsoNameFromIndex(i);
+ sb.AppendLine($" 0x{image.BaseAddress:x10} - 0x{endAddress:x10} {name}");
+ }
+ }
+
+ return sb.ToString();
+ }
+ catch (Exception e)
+ {
+ Logger.Error?.Print(LogClass.GdbStub, $"Error getting process info: {e.Message}");
+ return $"Error getting process info: {e.Message}\n";
+ }
+ }
+
+ private void Reply(string cmd)
+ {
+ Logger.Debug?.Print(LogClass.GdbStub, $"Reply: {cmd}");
+ WriteStream.Write(Encoding.ASCII.GetBytes($"${cmd}#{CalculateChecksum(cmd):x2}"));
+ }
+
+ private void ReplyOK()
+ {
+ Reply("OK");
+ }
+
+ private void ReplyError()
+ {
+ Reply("E01");
+ }
+
+ private void DebuggerThreadMain()
+ {
+ var endpoint = new IPEndPoint(IPAddress.Any, GdbStubPort);
+ ListenerSocket = new TcpListener(endpoint);
+ ListenerSocket.Start();
+ Logger.Notice.Print(LogClass.GdbStub, $"Currently waiting on {endpoint} for GDB client");
+
+ while (!_shuttingDown)
+ {
+ try
+ {
+ ClientSocket = ListenerSocket.AcceptSocket();
+ }
+ catch (SocketException)
+ {
+ return;
+ }
+
+ // If the user connects before the application is running, wait for the application to start.
+ int retries = 10;
+ while (DebugProcess == null && retries-- > 0)
+ {
+ Thread.Sleep(200);
+ }
+ if (DebugProcess == null)
+ {
+ Logger.Warning?.Print(LogClass.GdbStub, "Application is not running, cannot accept GDB client connection");
+ ClientSocket.Close();
+ continue;
+ }
+
+ ClientSocket.NoDelay = true;
+ ReadStream = new NetworkStream(ClientSocket, System.IO.FileAccess.Read);
+ WriteStream = new NetworkStream(ClientSocket, System.IO.FileAccess.Write);
+ Logger.Notice.Print(LogClass.GdbStub, "GDB client connected");
+
+ while (true)
+ {
+ try
+ {
+ switch (ReadStream.ReadByte())
+ {
+ case -1:
+ goto eof;
+ case '+':
+ continue;
+ case '-':
+ Logger.Notice.Print(LogClass.GdbStub, "NACK received!");
+ continue;
+ case '\x03':
+ Messages.Add(new BreakInMessage());
+ break;
+ case '$':
+ string cmd = "";
+ while (true)
+ {
+ int x = ReadStream.ReadByte();
+ if (x == -1)
+ goto eof;
+ if (x == '#')
+ break;
+ cmd += (char)x;
+ }
+
+ string checksum = $"{(char)ReadStream.ReadByte()}{(char)ReadStream.ReadByte()}";
+ if (checksum == $"{CalculateChecksum(cmd):x2}")
+ {
+ Messages.Add(new CommandMessage(cmd));
+ }
+ else
+ {
+ Messages.Add(new SendNackMessage());
+ }
+
+ break;
+ }
+ }
+ catch (IOException)
+ {
+ goto eof;
+ }
+ }
+
+ eof:
+ Logger.Notice.Print(LogClass.GdbStub, "GDB client lost connection");
+ ReadStream.Close();
+ ReadStream = null;
+ WriteStream.Close();
+ WriteStream = null;
+ ClientSocket.Close();
+ ClientSocket = null;
+
+ BreakpointManager.ClearAll();
+ }
+ }
+
+ private byte CalculateChecksum(string cmd)
+ {
+ byte checksum = 0;
+ foreach (char x in cmd)
+ {
+ unchecked
+ {
+ checksum += (byte)x;
+ }
+ }
+
+ return checksum;
+ }
+
+ private string FromHex(string hexString)
+ {
+ if (string.IsNullOrEmpty(hexString))
+ return string.Empty;
+
+ byte[] bytes = Convert.FromHexString(hexString);
+ return Encoding.ASCII.GetString(bytes);
+ }
+
+ private string ToHex(byte[] bytes)
+ {
+ return string.Join("", bytes.Select(x => $"{x:x2}"));
+ }
+
+ private string ToHex(string str)
+ {
+ return ToHex(Encoding.ASCII.GetBytes(str));
+ }
+
+ private string ToBinaryFormat(byte[] bytes)
+ {
+ return string.Join("", bytes.Select(x =>
+ x switch
+ {
+ (byte)'#' => "}\x03",
+ (byte)'$' => "}\x04",
+ (byte)'*' => "}\x0a",
+ (byte)'}' => "}\x5d",
+ _ => Convert.ToChar(x).ToString(),
+ }
+ ));
+ }
+
+ private string ToBinaryFormat(string str)
+ {
+ return ToBinaryFormat(Encoding.ASCII.GetBytes(str));
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _shuttingDown = true;
+
+ ListenerSocket.Stop();
+ ClientSocket?.Shutdown(SocketShutdown.Both);
+ ClientSocket?.Close();
+ ReadStream?.Close();
+ WriteStream?.Close();
+ DebuggerThread.Join();
+ Messages.Add(new KillMessage());
+ MessageHandlerThread.Join();
+ Messages.Dispose();
+ _breakHandlerEvent.Dispose();
+ }
+ }
+
+ public void BreakHandler(IExecutionContext ctx, ulong address, int imm)
+ {
+ DebugProcess.DebugInterruptHandler(ctx);
+
+ _breakHandlerEvent.Reset();
+ Messages.Add(new ThreadBreakMessage(ctx, address, imm));
+ // Messages.Add can block, so we log it after adding the message to make sure user can see the log at the same time GDB receives the break message
+ Logger.Notice.Print(LogClass.GdbStub, $"Break hit on thread {ctx.ThreadUid} at pc {address:x016}");
+ // Wait for the process to stop before returning to avoid BreakHander being called multiple times from the same breakpoint
+ _breakHandlerEvent.Wait(5000);
+ }
+
+ public void StepHandler(IExecutionContext ctx)
+ {
+ DebugProcess.DebugInterruptHandler(ctx);
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/GdbSignal.cs b/src/Ryujinx.HLE/Debugger/GdbSignal.cs
new file mode 100644
index 000000000..ee4efbda4
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/GdbSignal.cs
@@ -0,0 +1,15 @@
+namespace Ryujinx.HLE.Debugger
+{
+ enum GdbSignal
+ {
+ Zero = 0,
+ Int = 2,
+ Quit = 3,
+ Trap = 5,
+ Abort = 6,
+ Alarm = 14,
+ IO = 23,
+ XCPU = 24,
+ Unknown = 143
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/GdbXml/aarch64-core.xml b/src/Ryujinx.HLE/Debugger/GdbXml/aarch64-core.xml
new file mode 100644
index 000000000..9899a0e4a
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/GdbXml/aarch64-core.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Ryujinx.HLE/Debugger/GdbXml/aarch64-fpu.xml b/src/Ryujinx.HLE/Debugger/GdbXml/aarch64-fpu.xml
new file mode 100644
index 000000000..a09120bc4
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/GdbXml/aarch64-fpu.xml
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Ryujinx.HLE/Debugger/GdbXml/arm-core.xml b/src/Ryujinx.HLE/Debugger/GdbXml/arm-core.xml
new file mode 100644
index 000000000..2307d65f9
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/GdbXml/arm-core.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Ryujinx.HLE/Debugger/GdbXml/arm-neon.xml b/src/Ryujinx.HLE/Debugger/GdbXml/arm-neon.xml
new file mode 100644
index 000000000..d61f6b854
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/GdbXml/arm-neon.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Ryujinx.HLE/Debugger/GdbXml/target32.xml b/src/Ryujinx.HLE/Debugger/GdbXml/target32.xml
new file mode 100644
index 000000000..890679858
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/GdbXml/target32.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ arm
+
+
+
diff --git a/src/Ryujinx.HLE/Debugger/GdbXml/target64.xml b/src/Ryujinx.HLE/Debugger/GdbXml/target64.xml
new file mode 100644
index 000000000..cfd5bf780
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/GdbXml/target64.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ aarch64
+
+
+
diff --git a/src/Ryujinx.HLE/Debugger/IDebuggableProcess.cs b/src/Ryujinx.HLE/Debugger/IDebuggableProcess.cs
new file mode 100644
index 000000000..0896f25d2
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/IDebuggableProcess.cs
@@ -0,0 +1,21 @@
+using Ryujinx.Cpu;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.Memory;
+
+namespace Ryujinx.HLE.Debugger
+{
+ internal interface IDebuggableProcess
+ {
+ void DebugStop();
+ void DebugContinue();
+ void DebugContinue(KThread thread);
+ bool DebugStep(KThread thread);
+ KThread GetThread(ulong threadUid);
+ DebugState GetDebugState();
+ bool IsThreadPaused(KThread thread);
+ ulong[] GetThreadUids();
+ public void DebugInterruptHandler(IExecutionContext ctx);
+ IVirtualMemoryManager CpuMemory { get; }
+ void InvalidateCacheRegion(ulong address, ulong size);
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/Message/BreakInMessage.cs b/src/Ryujinx.HLE/Debugger/Message/BreakInMessage.cs
new file mode 100644
index 000000000..81d8784ae
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/Message/BreakInMessage.cs
@@ -0,0 +1,6 @@
+namespace Ryujinx.HLE.Debugger
+{
+ struct BreakInMessage : IMessage
+ {
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/Message/CommandMessage.cs b/src/Ryujinx.HLE/Debugger/Message/CommandMessage.cs
new file mode 100644
index 000000000..ad265d432
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/Message/CommandMessage.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.HLE.Debugger
+{
+ struct CommandMessage : IMessage
+ {
+ public string Command;
+
+ public CommandMessage(string cmd)
+ {
+ Command = cmd;
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/Message/IMessage.cs b/src/Ryujinx.HLE/Debugger/Message/IMessage.cs
new file mode 100644
index 000000000..4b03183c5
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/Message/IMessage.cs
@@ -0,0 +1,6 @@
+namespace Ryujinx.HLE.Debugger
+{
+ interface IMessage
+ {
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/Message/KillMessage.cs b/src/Ryujinx.HLE/Debugger/Message/KillMessage.cs
new file mode 100644
index 000000000..43ae0f21e
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/Message/KillMessage.cs
@@ -0,0 +1,6 @@
+namespace Ryujinx.HLE.Debugger
+{
+ struct KillMessage : IMessage
+ {
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/Message/SendNackMessage.cs b/src/Ryujinx.HLE/Debugger/Message/SendNackMessage.cs
new file mode 100644
index 000000000..ce804c46e
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/Message/SendNackMessage.cs
@@ -0,0 +1,6 @@
+namespace Ryujinx.HLE.Debugger
+{
+ struct SendNackMessage : IMessage
+ {
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/Message/ThreadBreakMessage.cs b/src/Ryujinx.HLE/Debugger/Message/ThreadBreakMessage.cs
new file mode 100644
index 000000000..027096eeb
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/Message/ThreadBreakMessage.cs
@@ -0,0 +1,18 @@
+using IExecutionContext = Ryujinx.Cpu.IExecutionContext;
+
+namespace Ryujinx.HLE.Debugger
+{
+ public class ThreadBreakMessage : IMessage
+ {
+ public IExecutionContext Context { get; }
+ public ulong Address { get; }
+ public int Opcode { get; }
+
+ public ThreadBreakMessage(IExecutionContext context, ulong address, int opcode)
+ {
+ Context = context;
+ Address = address;
+ Opcode = opcode;
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/RegisterInformation.cs b/src/Ryujinx.HLE/Debugger/RegisterInformation.cs
new file mode 100644
index 000000000..b5fd88ea5
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/RegisterInformation.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Ryujinx.HLE.Debugger
+{
+ class RegisterInformation
+ {
+ public static readonly Dictionary Features = new()
+ {
+ { "target64.xml", GetEmbeddedResourceContent("target64.xml") },
+ { "target32.xml", GetEmbeddedResourceContent("target32.xml") },
+ { "aarch64-core.xml", GetEmbeddedResourceContent("aarch64-core.xml") },
+ { "aarch64-fpu.xml", GetEmbeddedResourceContent("aarch64-fpu.xml") },
+ { "arm-core.xml", GetEmbeddedResourceContent("arm-core.xml") },
+ { "arm-neon.xml", GetEmbeddedResourceContent("arm-neon.xml") },
+ };
+
+ private static string GetEmbeddedResourceContent(string resourceName)
+ {
+ Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("Ryujinx.HLE.Debugger.GdbXml." + resourceName);
+ StreamReader reader = new StreamReader(stream);
+ string result = reader.ReadToEnd();
+ reader.Dispose();
+ stream.Dispose();
+ return result;
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/Debugger/StringStream.cs b/src/Ryujinx.HLE/Debugger/StringStream.cs
new file mode 100644
index 000000000..d8148a9c2
--- /dev/null
+++ b/src/Ryujinx.HLE/Debugger/StringStream.cs
@@ -0,0 +1,109 @@
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Ryujinx.HLE.Debugger
+{
+ class StringStream
+ {
+ private readonly string Data;
+ private int Position;
+
+ public StringStream(string s)
+ {
+ Data = s;
+ }
+
+ public char ReadChar()
+ {
+ return Data[Position++];
+ }
+
+ public string ReadUntil(char needle)
+ {
+ int needlePos = Data.IndexOf(needle, Position);
+
+ if (needlePos == -1)
+ {
+ needlePos = Data.Length;
+ }
+
+ string result = Data.Substring(Position, needlePos - Position);
+ Position = needlePos + 1;
+ return result;
+ }
+
+ public string ReadLength(int len)
+ {
+ string result = Data.Substring(Position, len);
+ Position += len;
+ return result;
+ }
+
+ public string ReadRemaining()
+ {
+ string result = Data.Substring(Position);
+ Position = Data.Length;
+ return result;
+ }
+
+ public ulong ReadRemainingAsHex()
+ {
+ return ulong.Parse(ReadRemaining(), NumberStyles.HexNumber);
+ }
+
+ public ulong ReadUntilAsHex(char needle)
+ {
+ return ulong.Parse(ReadUntil(needle), NumberStyles.HexNumber);
+ }
+
+ public ulong ReadLengthAsHex(int len)
+ {
+ return ulong.Parse(ReadLength(len), NumberStyles.HexNumber);
+ }
+
+ public ulong ReadLengthAsLEHex(int len)
+ {
+ Debug.Assert(len % 2 == 0);
+
+ ulong result = 0;
+ int pos = 0;
+ while (pos < len)
+ {
+ result += ReadLengthAsHex(2) << (4 * pos);
+ pos += 2;
+ }
+ return result;
+ }
+
+ public ulong? ReadRemainingAsThreadUid()
+ {
+ string s = ReadRemaining();
+ return s == "-1" ? null : ulong.Parse(s, NumberStyles.HexNumber);
+ }
+
+ public bool ConsumePrefix(string prefix)
+ {
+ if (Data.Substring(Position).StartsWith(prefix))
+ {
+ Position += prefix.Length;
+ return true;
+ }
+ return false;
+ }
+
+ public bool ConsumeRemaining(string match)
+ {
+ if (Data.Substring(Position) == match)
+ {
+ Position += match.Length;
+ return true;
+ }
+ return false;
+ }
+
+ public bool IsEmpty()
+ {
+ return Position >= Data.Length;
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs
index 759780c42..28f7ef25f 100644
--- a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs
+++ b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs
@@ -69,7 +69,7 @@ namespace Ryujinx.HLE.HOS
mode = MemoryManagerMode.SoftwarePageTable;
}
- ICpuEngine cpuEngine = isArm64Host && (mode == MemoryManagerMode.HostMapped || mode == MemoryManagerMode.HostMappedUnsafe)
+ ICpuEngine cpuEngine = isArm64Host && (mode == MemoryManagerMode.HostMapped || mode == MemoryManagerMode.HostMappedUnsafe) && !context.Device.Configuration.EnableGdbStub
? new LightningJitEngine(_tickSource)
: new JitEngine(_tickSource);
diff --git a/src/Ryujinx.HLE/HOS/Horizon.cs b/src/Ryujinx.HLE/HOS/Horizon.cs
index 5063b4329..517f8ef16 100644
--- a/src/Ryujinx.HLE/HOS/Horizon.cs
+++ b/src/Ryujinx.HLE/HOS/Horizon.cs
@@ -5,6 +5,7 @@ using LibHac.Fs.Shim;
using LibHac.FsSystem;
using LibHac.Tools.FsSystem;
using Ryujinx.Cpu;
+using Ryujinx.HLE.Debugger;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.HOS.Kernel.Memory;
@@ -500,5 +501,21 @@ namespace Ryujinx.HLE.HOS
IsPaused = pause;
}
+
+ internal IDebuggableProcess DebugGetApplicationProcessDebugInterface()
+ {
+ lock (KernelContext.Processes)
+ {
+ return KernelContext.Processes.Values.FirstOrDefault(x => x.IsApplication)?.DebugInterface;
+ }
+ }
+
+ internal KProcess DebugGetApplicationProcess()
+ {
+ lock (KernelContext.Processes)
+ {
+ return KernelContext.Processes.Values.FirstOrDefault(x => x.IsApplication);
+ }
+ }
}
}
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlockManager.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlockManager.cs
index f13a3554a..6a57aa3d1 100644
--- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlockManager.cs
+++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlockManager.cs
@@ -89,13 +89,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
if (baseAddress > currBaseAddr)
{
KMemoryBlock newBlock = currBlock.SplitRightAtAddress(baseAddress);
- _blockTree.Add(newBlock);
+ if (currBlock.Left == null)
+ _blockTree.Add(newBlock, currBlock);
+ else
+ _blockTree.Add(newBlock, currBlock.Predecessor);
}
if (endAddr < currEndAddr)
{
KMemoryBlock newBlock = currBlock.SplitRightAtAddress(endAddr);
- _blockTree.Add(newBlock);
+ if (currBlock.Left == null)
+ _blockTree.Add(newBlock, currBlock);
+ else
+ _blockTree.Add(newBlock, currBlock.Predecessor);
currBlock = newBlock;
}
@@ -143,13 +149,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
if (baseAddress > currBaseAddr)
{
KMemoryBlock newBlock = currBlock.SplitRightAtAddress(baseAddress);
- _blockTree.Add(newBlock);
+ if (currBlock.Left == null)
+ _blockTree.Add(newBlock, currBlock);
+ else
+ _blockTree.Add(newBlock, currBlock.Predecessor);
}
if (endAddr < currEndAddr)
{
KMemoryBlock newBlock = currBlock.SplitRightAtAddress(endAddr);
- _blockTree.Add(newBlock);
+ if (currBlock.Left == null)
+ _blockTree.Add(newBlock, currBlock);
+ else
+ _blockTree.Add(newBlock, currBlock.Predecessor);
currBlock = newBlock;
}
@@ -199,13 +211,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
if (baseAddress > currBaseAddr)
{
KMemoryBlock newBlock = currBlock.SplitRightAtAddress(baseAddress);
- _blockTree.Add(newBlock);
+ if (currBlock.Left == null)
+ _blockTree.Add(newBlock, currBlock);
+ else
+ _blockTree.Add(newBlock, currBlock.Predecessor);
}
if (endAddr < currEndAddr)
{
KMemoryBlock newBlock = currBlock.SplitRightAtAddress(endAddr);
- _blockTree.Add(newBlock);
+ if (currBlock.Left == null)
+ _blockTree.Add(newBlock, currBlock);
+ else
+ _blockTree.Add(newBlock, currBlock.Predecessor);
currBlock = newBlock;
}
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs
index c4a9835cc..87da9f7a6 100644
--- a/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs
+++ b/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs
@@ -4,6 +4,7 @@ using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.HLE.Loaders.Elf;
using Ryujinx.Memory;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -17,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
private readonly KProcess _owner;
- private class Image
+ public class Image
{
public ulong BaseAddress { get; }
public ulong Size { get; }
@@ -54,6 +55,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
trace.AppendLine($"Process: {_owner.Name}, PID: {_owner.Pid}");
+ string ThreadName = thread.GetThreadName();
+
+ if (!String.IsNullOrEmpty(ThreadName))
+ {
+ trace.AppendLine($"Thread ID: {thread.ThreadUid} ({ThreadName})");
+ } else {
+ trace.AppendLine($"Thread ID: {thread.ThreadUid}");
+ }
+
void AppendTrace(ulong address)
{
if (AnalyzePointer(out PointerInfo info, address, thread))
@@ -283,7 +293,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return null;
}
- private string GetGuessedNsoNameFromIndex(int index)
+ public string GetGuessedNsoNameFromIndex(int index)
{
if ((uint)index > 11)
{
@@ -316,6 +326,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
}
}
+ public List GetLoadedImages()
+ {
+ EnsureLoaded();
+
+ lock (_images)
+ {
+ return [.. _images];
+ }
+ }
+
private void EnsureLoaded()
{
if (Interlocked.CompareExchange(ref _loaded, 1, 0) == 0)
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
index 478b4e864..0a57f5bc6 100644
--- a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
+++ b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
@@ -1,6 +1,7 @@
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Cpu;
+using Ryujinx.HLE.Debugger;
using Ryujinx.HLE.Exceptions;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Memory;
@@ -11,6 +12,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
+using ExceptionCallback = Ryujinx.Cpu.ExceptionCallback;
+using ExceptionCallbackNoArgs = Ryujinx.Cpu.ExceptionCallbackNoArgs;
namespace Ryujinx.HLE.HOS.Kernel.Process
{
@@ -89,6 +92,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public IVirtualMemoryManager CpuMemory => Context.AddressSpace;
public HleProcessDebugger Debugger { get; private set; }
+ public IDebuggableProcess DebugInterface { get; private set; }
+ protected int debugState = (int)DebugState.Running;
public KProcess(KernelContext context, bool allowCodeMemoryForJit = false) : base(context)
{
@@ -110,6 +115,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
_threads = [];
Debugger = new HleProcessDebugger(this);
+ DebugInterface = new DebuggerInterface(this);
}
public Result InitializeKip(
@@ -679,6 +685,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
SetState(newState);
+ if (KernelContext.Device.Configuration.DebuggerSuspendOnStart && IsApplication)
+ {
+ mainThread.Suspend(ThreadSchedState.ThreadPauseFlag);
+ debugState = (int)DebugState.Stopped;
+ Logger.Notice.Print(LogClass.Kernel, $"Application is suspended on start for debugging.");
+ }
+
result = mainThread.Start();
if (result != Result.Success)
@@ -727,9 +740,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public IExecutionContext CreateExecutionContext()
{
+ ExceptionCallback breakCallback = null;
+ ExceptionCallbackNoArgs stepCallback = null;
+
+ if (KernelContext.Device.Configuration.EnableGdbStub && KernelContext.Device.Debugger != null)
+ {
+ breakCallback = KernelContext.Device.Debugger.BreakHandler;
+ stepCallback = KernelContext.Device.Debugger.StepHandler;
+ }
+
return Context?.CreateExecutionContext(new ExceptionCallbacks(
InterruptHandler,
- null,
+ breakCallback,
+ stepCallback,
KernelContext.SyscallHandler.SvcCall,
UndefinedInstructionHandler));
}
@@ -1174,5 +1197,186 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
return Capabilities.IsSvcPermitted(svcId);
}
+
+ private class DebuggerInterface : IDebuggableProcess
+ {
+ private Barrier StepBarrier;
+ private readonly KProcess _parent;
+ private readonly KernelContext _kernelContext;
+ private KThread steppingThread;
+
+ public DebuggerInterface(KProcess p)
+ {
+ _parent = p;
+ _kernelContext = p.KernelContext;
+ StepBarrier = new(2);
+ }
+
+ public void DebugStop()
+ {
+ if (Interlocked.CompareExchange(ref _parent.debugState, (int)DebugState.Stopping,
+ (int)DebugState.Running) != (int)DebugState.Running)
+ {
+ return;
+ }
+
+ _kernelContext.CriticalSection.Enter();
+ lock (_parent._threadingLock)
+ {
+ foreach (KThread thread in _parent._threads)
+ {
+ thread.Suspend(ThreadSchedState.ThreadPauseFlag);
+ thread.Context.RequestInterrupt();
+ if (!thread.DebugHalt.WaitOne(TimeSpan.FromMilliseconds(50)))
+ {
+ Logger.Warning?.Print(LogClass.Kernel, $"Failed to suspend thread {thread.ThreadUid} in time.");
+ }
+ }
+ }
+
+ _parent.debugState = (int)DebugState.Stopped;
+ _kernelContext.CriticalSection.Leave();
+ }
+
+ public void DebugContinue()
+ {
+ if (Interlocked.CompareExchange(ref _parent.debugState, (int)DebugState.Running,
+ (int)DebugState.Stopped) != (int)DebugState.Stopped)
+ {
+ return;
+ }
+
+ _kernelContext.CriticalSection.Enter();
+ lock (_parent._threadingLock)
+ {
+ foreach (KThread thread in _parent._threads)
+ {
+ thread.Resume(ThreadSchedState.ThreadPauseFlag);
+ }
+ }
+ _kernelContext.CriticalSection.Leave();
+ }
+
+ public void DebugContinue(KThread target)
+ {
+ Interlocked.Exchange(ref _parent.debugState, (int)DebugState.Running);
+
+ _kernelContext.CriticalSection.Enter();
+ lock (_parent._threadingLock)
+ {
+ target.Resume(ThreadSchedState.ThreadPauseFlag);
+ }
+ _kernelContext.CriticalSection.Leave();
+ }
+
+ public bool DebugStep(KThread target)
+ {
+ if (!IsThreadPaused(target))
+ {
+ return false;
+ }
+
+ _kernelContext.CriticalSection.Enter();
+ steppingThread = target;
+ bool waiting = target.MutexOwner != null || target.WaitingSync || target.WaitingInArbitration;
+ target.Context.RequestDebugStep();
+ if (waiting)
+ {
+ lock (_parent._threadingLock)
+ {
+ foreach (KThread thread in _parent._threads)
+ {
+ thread.Resume(ThreadSchedState.ThreadPauseFlag);
+ }
+ }
+ }
+ else
+ {
+ target.Resume(ThreadSchedState.ThreadPauseFlag);
+ }
+ _kernelContext.CriticalSection.Leave();
+
+ bool stepTimedOut = false;
+ if (!StepBarrier.SignalAndWait(TimeSpan.FromMilliseconds(2000)))
+ {
+ Logger.Warning?.Print(LogClass.Kernel, $"Failed to step thread {target.ThreadUid} in time.");
+ stepTimedOut = true;
+ }
+
+ _kernelContext.CriticalSection.Enter();
+ steppingThread = null;
+ if (waiting)
+ {
+ lock (_parent._threadingLock)
+ {
+ foreach (KThread thread in _parent._threads)
+ {
+ thread.Suspend(ThreadSchedState.ThreadPauseFlag);
+ }
+ }
+ }
+ else
+ {
+ target.Suspend(ThreadSchedState.ThreadPauseFlag);
+ }
+ _kernelContext.CriticalSection.Leave();
+
+ if (stepTimedOut)
+ {
+ return false;
+ }
+
+ StepBarrier.SignalAndWait();
+ return true;
+ }
+
+ public DebugState GetDebugState()
+ {
+ return (DebugState)_parent.debugState;
+ }
+
+ public bool IsThreadPaused(KThread target)
+ {
+ return (target.SchedFlags & ThreadSchedState.ThreadPauseFlag) != 0;
+ }
+
+ public ulong[] GetThreadUids()
+ {
+ lock (_parent._threadingLock)
+ {
+ var threads = _parent._threads.Where(x => !x.TerminationRequested).ToArray();
+ return threads.Select(x => x.ThreadUid).ToArray();
+ }
+ }
+
+ public KThread GetThread(ulong threadUid)
+ {
+ lock (_parent._threadingLock)
+ {
+ var threads = _parent._threads.Where(x => !x.TerminationRequested).ToArray();
+ return threads.FirstOrDefault(x => x.ThreadUid == threadUid);
+ }
+ }
+
+ public void DebugInterruptHandler(IExecutionContext ctx)
+ {
+ _kernelContext.CriticalSection.Enter();
+ bool stepping = steppingThread != null;
+ _kernelContext.CriticalSection.Leave();
+ if (stepping)
+ {
+ StepBarrier.SignalAndWait();
+ StepBarrier.SignalAndWait();
+ }
+ _parent.InterruptHandler(ctx);
+ }
+
+ public IVirtualMemoryManager CpuMemory { get { return _parent.CpuMemory; } }
+
+ public void InvalidateCacheRegion(ulong address, ulong size)
+ {
+ _parent.Context.InvalidateCacheRegion(address, size);
+ }
+ }
}
}
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessExecutionContext.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessExecutionContext.cs
index b8118fbb4..f0e44c4b7 100644
--- a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessExecutionContext.cs
+++ b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessExecutionContext.cs
@@ -1,5 +1,6 @@
using ARMeilleure.State;
using Ryujinx.Cpu;
+using System.Threading;
namespace Ryujinx.HLE.HOS.Kernel.Process
{
@@ -17,10 +18,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public bool IsAarch32 { get => false; set { } }
+ public ulong ThreadUid { get; set; }
+
public bool Running { get; private set; } = true;
private readonly ulong[] _x = new ulong[32];
+ public ulong DebugPc { get; set; }
+
public ulong GetX(int index) => _x[index];
public void SetX(int index, ulong value) => _x[index] = value;
@@ -31,6 +36,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
}
+ public void RequestDebugStep()
+ {
+ }
+
public void StopRunning()
{
Running = false;
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs
index 7471702c3..54b20ff99 100644
--- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs
+++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs
@@ -301,6 +301,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
currentThread.SchedulerWaitEvent.Reset();
currentThread.ThreadContext.Unlock();
+ currentThread.DebugHalt.Set();
// Wake all the threads that might be waiting until this thread context is unlocked.
for (int core = 0; core < CpuCoresCount; core++)
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs
index b5a14ad5b..20fb426ba 100644
--- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs
+++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs
@@ -1,12 +1,15 @@
using Ryujinx.Common.Logging;
using Ryujinx.Cpu;
+using Ryujinx.HLE.Debugger;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.SupervisorCall;
using Ryujinx.Horizon.Common;
+using Ryujinx.Memory;
using System;
using System.Collections.Generic;
using System.Numerics;
+using System.Text;
using System.Threading;
namespace Ryujinx.HLE.HOS.Kernel.Threading
@@ -16,6 +19,23 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
private const int TlsUserDisableCountOffset = 0x100;
private const int TlsUserInterruptFlagOffset = 0x102;
+ // Tls -> ThreadType
+ private const int TlsThreadTypeOffsetAArch64 = 0x1F8;
+ private const int TlsThreadTypeOffsetAArch32 = 0x1FC;
+
+ // Tls -> ThreadType -> Version
+ private const int TlsThreadTypeVersionOffsetAArch64 = 0x46;
+ private const int TlsThreadTypeVersionOffsetAArch32 = 0x26;
+
+ // Tls -> ThreadType (Version 0) -> ThreadNamePointer
+ private const int TlsThreadTypeVersion0ThreadNamePointerOffsetAArch64 = 0x1A8;
+ private const int TlsThreadTypeVersion0ThreadNamePointerOffsetAArch32 = 0xE8;
+
+ // Tls -> ThreadType (Version 1) -> ThreadNamePointer
+ private const int TlsThreadTypeThreadNamePointerOffsetAArch64 = 0x1A0;
+ private const int TlsThreadTypeThreadNamePointerOffsetAArch32 = 0xE4;
+
+
public const int MaxWaitSyncObjects = 64;
private ManualResetEvent _schedulerWaitEvent;
@@ -114,6 +134,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
private readonly Lock _activityOperationLock = new();
+ internal readonly ManualResetEvent DebugHalt = new(false);
+
public KThread(KernelContext context) : base(context)
{
WaitSyncObjects = new KSynchronizationObject[MaxWaitSyncObjects];
@@ -202,8 +224,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
}
Context.TpidrroEl0 = (long)_tlsAddress;
+ Context.DebugPc = _entrypoint;
ThreadUid = KernelContext.NewThreadUid();
+ Context.ThreadUid = ThreadUid;
HostThread.Name = customThreadStart != null ? $"HLE.OsThread.{ThreadUid}" : $"HLE.GuestThread.{ThreadUid}";
@@ -307,7 +331,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
KernelContext.CriticalSection.Enter();
- if (Owner != null && Owner.PinnedThreads[KernelStatic.GetCurrentThread().CurrentCore] == this)
+ KThread currentThread = KernelStatic.GetCurrentThread();
+
+ if (Owner != null && currentThread != null && Owner.PinnedThreads[currentThread.CurrentCore] == this)
{
Owner.UnpinThread(this);
}
@@ -362,7 +388,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
ThreadSchedState state = PrepareForTermination();
- if (state != ThreadSchedState.TerminationPending)
+ if (KernelStatic.GetCurrentThread() == this && state != ThreadSchedState.TerminationPending)
{
KernelContext.Synchronization.WaitFor(new KSynchronizationObject[] { this }, -1, out _);
}
@@ -1248,6 +1274,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
private void ThreadStart()
{
_schedulerWaitEvent.WaitOne();
+ DebugHalt.Reset();
KernelStatic.SetKernelContext(KernelContext, this);
if (_customThreadStart != null)
@@ -1431,5 +1458,84 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
Owner.CpuMemory.Write(_tlsAddress + TlsUserInterruptFlagOffset, 0);
}
+
+ public string GetThreadName()
+ {
+ try
+ {
+ ulong threadNamePtr = 0;
+ if (Context.IsAarch32)
+ {
+ uint threadTypePtr32 = Owner.CpuMemory.Read(_tlsAddress + TlsThreadTypeOffsetAArch32);
+ if (threadTypePtr32 == 0)
+ {
+ return "";
+ }
+
+ ushort version = Owner.CpuMemory.Read(threadTypePtr32 + TlsThreadTypeVersionOffsetAArch32);
+ switch (version)
+ {
+ case 0x0000:
+ case 0xFFFF:
+ threadNamePtr = Owner.CpuMemory.Read(threadTypePtr32 + TlsThreadTypeVersion0ThreadNamePointerOffsetAArch32);
+ break;
+ case 0x0001:
+ threadNamePtr = Owner.CpuMemory.Read(threadTypePtr32 + TlsThreadTypeThreadNamePointerOffsetAArch32);
+ break;
+ default:
+ Logger.Warning?.Print(LogClass.Kernel, $"Unknown ThreadType struct version: {version}");
+ break;
+ }
+ }
+ else
+ {
+ ulong threadTypePtr64 = Owner.CpuMemory.Read(_tlsAddress + TlsThreadTypeOffsetAArch64);
+ if (threadTypePtr64 == 0)
+ {
+ return "";
+ }
+
+ ushort version = Owner.CpuMemory.Read(threadTypePtr64 + TlsThreadTypeVersionOffsetAArch64);
+ switch (version)
+ {
+ case 0x0000:
+ case 0xFFFF:
+ threadNamePtr = Owner.CpuMemory.Read(threadTypePtr64 + TlsThreadTypeVersion0ThreadNamePointerOffsetAArch64);
+ break;
+ case 0x0001:
+ threadNamePtr = Owner.CpuMemory.Read(threadTypePtr64 + TlsThreadTypeThreadNamePointerOffsetAArch64);
+ break;
+ default:
+ Logger.Warning?.Print(LogClass.Kernel, $"Unknown ThreadType struct version: {version}");
+ break;
+ }
+ }
+
+ if (threadNamePtr == 0)
+ {
+ return "";
+ }
+
+ List nameBytes = new();
+ for (int i = 0; i < 0x20; i++)
+ {
+ byte b = Owner.CpuMemory.Read(threadNamePtr + (ulong)i);
+ if (b == 0)
+ {
+ break;
+ }
+ nameBytes.Add(b);
+ }
+ return Encoding.UTF8.GetString(nameBytes.ToArray());
+
+ } catch (InvalidMemoryRegionException)
+ {
+ Logger.Warning?.Print(LogClass.Kernel, "Failed to get thread name.");
+ return "";
+ } catch (Exception e) {
+ Logger.Error?.Print(LogClass.Kernel, $"Error getting thread name: {e.Message}");
+ return "";
+ }
+ }
}
}
diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IPurchaseEventManager.cs b/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IPurchaseEventManager.cs
index c92a10d66..8521adc6e 100644
--- a/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IPurchaseEventManager.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IPurchaseEventManager.cs
@@ -62,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
Logger.Debug?.PrintStub(LogClass.ServiceNs); // NOTE: Uses Debug to avoid spamming.
- return ResultCode.Success;
+ return ResultCode.NoPurchasedProductInfoAvailable;
}
}
}
diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/ResultCode.cs b/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/ResultCode.cs
index b795a7563..296d65f32 100644
--- a/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/ResultCode.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/ResultCode.cs
@@ -2,6 +2,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
{
enum ResultCode
{
+ EShopModuleId = 164,
ModuleId = 166,
ErrorCodeShift = 9,
@@ -9,5 +10,6 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
InvalidBufferSize = (200 << ErrorCodeShift) | ModuleId,
InvalidPid = (300 << ErrorCodeShift) | ModuleId,
+ NoPurchasedProductInfoAvailable = (400 << ErrorCodeShift) | EShopModuleId
}
}
diff --git a/src/Ryujinx.HLE/HleConfiguration.cs b/src/Ryujinx.HLE/HleConfiguration.cs
index 10c2a1f30..e2f95ede7 100644
--- a/src/Ryujinx.HLE/HleConfiguration.cs
+++ b/src/Ryujinx.HLE/HleConfiguration.cs
@@ -194,6 +194,21 @@ namespace Ryujinx.HLE
///
public Action RefreshInputConfig { internal get; set; }
+ ///
+ /// Enables gdbstub to allow for debugging of the guest .
+ ///
+ public bool EnableGdbStub { internal get; set; }
+
+ ///
+ /// A TCP port to use to expose a gdbstub for a debugger to connect to.
+ ///
+ public ushort GdbStubPort { internal get; set; }
+
+ ///
+ /// Suspend execution when starting an application
+ ///
+ public bool DebuggerSuspendOnStart { internal get; set; }
+
///
/// The desired hacky workarounds.
///
@@ -222,6 +237,9 @@ namespace Ryujinx.HLE
bool multiplayerDisableP2p,
string multiplayerLdnPassphrase,
string multiplayerLdnServer,
+ bool enableGdbStub,
+ ushort gdbStubPort,
+ bool debuggerSuspendOnStart,
int customVSyncInterval,
EnabledDirtyHack[] dirtyHacks = null)
{
@@ -248,6 +266,9 @@ namespace Ryujinx.HLE
MultiplayerDisableP2p = multiplayerDisableP2p;
MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
MultiplayerLdnServer = multiplayerLdnServer;
+ EnableGdbStub = enableGdbStub;
+ GdbStubPort = gdbStubPort;
+ DebuggerSuspendOnStart = debuggerSuspendOnStart;
Hacks = dirtyHacks ?? [];
}
diff --git a/src/Ryujinx.HLE/Ryujinx.HLE.csproj b/src/Ryujinx.HLE/Ryujinx.HLE.csproj
index 5139d9276..1938796e8 100644
--- a/src/Ryujinx.HLE/Ryujinx.HLE.csproj
+++ b/src/Ryujinx.HLE/Ryujinx.HLE.csproj
@@ -33,6 +33,12 @@
+
+
+
+
+
+
@@ -42,6 +48,12 @@
+
+
+
+
+
+
diff --git a/src/Ryujinx.HLE/Switch.cs b/src/Ryujinx.HLE/Switch.cs
index bdcbe82c7..e1aa8e0e4 100644
--- a/src/Ryujinx.HLE/Switch.cs
+++ b/src/Ryujinx.HLE/Switch.cs
@@ -14,6 +14,7 @@ using Ryujinx.HLE.Loaders.Processes;
using Ryujinx.HLE.UI;
using Ryujinx.Memory;
using System;
+using System.Threading;
namespace Ryujinx.HLE
{
@@ -41,6 +42,7 @@ namespace Ryujinx.HLE
public Hid Hid { get; }
public TamperMachine TamperMachine { get; }
public IHostUIHandler UIHandler { get; }
+ public Debugger.Debugger Debugger { get; }
public int CpuCoresCount = 4; // Switch has a quad-core Tegra X1 SoC
@@ -72,6 +74,7 @@ namespace Ryujinx.HLE
AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver);
Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags);
Gpu = new GpuContext(Configuration.GpuRenderer, DirtyHacks);
+ Debugger = Configuration.EnableGdbStub ? new Debugger.Debugger(this, Configuration.GdbStubPort) : null;
System = new HOS.Horizon(this);
Statistics = new PerformanceStatistics(this);
Hid = new Hid(this, System.HidStorage);
@@ -173,6 +176,7 @@ namespace Ryujinx.HLE
AudioDeviceDriver.Dispose();
FileSystem.Dispose();
Memory.Dispose();
+ Debugger?.Dispose();
TitleIDs.CurrentApplication.Value = null;
Shared = null;
diff --git a/src/Ryujinx.Memory/Range/INonOverlappingRange.cs b/src/Ryujinx.Memory/Range/INonOverlappingRange.cs
index 23194e0f2..c6a0197d4 100644
--- a/src/Ryujinx.Memory/Range/INonOverlappingRange.cs
+++ b/src/Ryujinx.Memory/Range/INonOverlappingRange.cs
@@ -3,7 +3,7 @@ namespace Ryujinx.Memory.Range
///
/// Range of memory that can be split in two.
///
- interface INonOverlappingRange : IRange
+ public interface INonOverlappingRange : IRange
{
///
/// Split this region into two, around the specified address.
diff --git a/src/Ryujinx.Memory/Range/NonOverlappingRangeList.cs b/src/Ryujinx.Memory/Range/NonOverlappingRangeList.cs
index 894078aee..7803b03d1 100644
--- a/src/Ryujinx.Memory/Range/NonOverlappingRangeList.cs
+++ b/src/Ryujinx.Memory/Range/NonOverlappingRangeList.cs
@@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Threading;
namespace Ryujinx.Memory.Range
{
@@ -7,8 +10,284 @@ namespace Ryujinx.Memory.Range
/// A range list that assumes ranges are non-overlapping, with list items that can be split in two to avoid overlaps.
///
/// Type of the range.
- class NonOverlappingRangeList : RangeList where T : INonOverlappingRange
+ public class NonOverlappingRangeList : RangeListBase where T : INonOverlappingRange
{
+ private readonly Dictionary> _quickAccess = new(AddressEqualityComparer.Comparer);
+ private readonly Dictionary> _fastQuickAccess = new(AddressEqualityComparer.Comparer);
+
+ public readonly ReaderWriterLockSlim Lock = new();
+
+ ///
+ /// Creates a new non-overlapping range list.
+ ///
+ public NonOverlappingRangeList() { }
+
+ ///
+ /// Creates a new non-overlapping range list.
+ ///
+ /// The initial size of the backing array
+ public NonOverlappingRangeList(int backingInitialSize) : base(backingInitialSize) { }
+
+ ///
+ /// Adds a new item to the list.
+ ///
+ /// The item to be added
+ public override void Add(T item)
+ {
+ int index = BinarySearch(item.Address);
+
+ if (index < 0)
+ {
+ index = ~index;
+ }
+
+ RangeItem rangeItem = new(item);
+
+ Insert(index, rangeItem);
+
+ _quickAccess.Add(item.Address, rangeItem);
+ }
+
+ ///
+ /// Updates an item's end address on the list. Address must be the same.
+ ///
+ /// The item to be updated
+ /// True if the item was located and updated, false otherwise
+ protected override bool Update(T item)
+ {
+ int index = BinarySearch(item.Address);
+
+ if (index >= 0 && Items[index].Value.Equals(item))
+ {
+ RangeItem rangeItem = new(item) { Previous = Items[index].Previous, Next = Items[index].Next };
+
+ if (index > 0)
+ {
+ Items[index - 1].Next = rangeItem;
+ }
+
+ if (index < Count - 1)
+ {
+ Items[index + 1].Previous = rangeItem;
+ }
+
+ foreach (ulong addr in Items[index].QuickAccessAddresses)
+ {
+ _quickAccess.Remove(addr);
+ _fastQuickAccess.Remove(addr);
+ }
+
+ Items[index] = rangeItem;
+
+ _quickAccess[item.Address] = rangeItem;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void Insert(int index, RangeItem item)
+ {
+ Debug.Assert(item.Address != item.EndAddress);
+
+ if (Count + 1 > Items.Length)
+ {
+ Array.Resize(ref Items, Items.Length + BackingGrowthSize);
+ }
+
+ if (index >= Count)
+ {
+ if (index == Count)
+ {
+ if (index != 0)
+ {
+ item.Previous = Items[index - 1];
+ Items[index - 1].Next = item;
+ }
+ Items[index] = item;
+ Count++;
+ }
+ }
+ else
+ {
+ Array.Copy(Items, index, Items, index + 1, Count - index);
+
+ Items[index] = item;
+ if (index != 0)
+ {
+ item.Previous = Items[index - 1];
+ Items[index - 1].Next = item;
+ }
+
+ item.Next = Items[index + 1];
+ Items[index + 1].Previous = item;
+
+ Count++;
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void RemoveAt(int index)
+ {
+ if (index < Count - 1)
+ {
+ Items[index + 1].Previous = index > 0 ? Items[index - 1] : null;
+ }
+
+ if (index > 0)
+ {
+ Items[index - 1].Next = index < Count - 1 ? Items[index + 1] : null;
+ }
+
+ if (index < --Count)
+ {
+ Array.Copy(Items, index + 1, Items, index, Count - index);
+ }
+ }
+
+ ///
+ /// Removes an item from the list.
+ ///
+ /// The item to be removed
+ /// True if the item was removed, or false if it was not found
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override bool Remove(T item)
+ {
+ int index = BinarySearch(item.Address);
+
+ if (index >= 0 && Items[index].Value.Equals(item))
+ {
+ _quickAccess.Remove(item.Address);
+
+ foreach (ulong addr in Items[index].QuickAccessAddresses)
+ {
+ _quickAccess.Remove(addr);
+ _fastQuickAccess.Remove(addr);
+ }
+
+ RemoveAt(index);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Removes a range of items from the item list
+ ///
+ /// The first item in the range of items to be removed
+ /// The last item in the range of items to be removed
+ public override void RemoveRange(RangeItem startItem, RangeItem endItem)
+ {
+ if (startItem is null)
+ {
+ return;
+ }
+
+ if (startItem == endItem)
+ {
+ Remove(startItem.Value);
+ return;
+ }
+
+ int startIndex = BinarySearch(startItem.Address);
+ int endIndex = BinarySearch(endItem.Address);
+
+ if (endIndex < Count - 1)
+ {
+ Items[endIndex + 1].Previous = startIndex > 0 ? Items[startIndex - 1] : null;
+ }
+
+ if (startIndex > 0)
+ {
+ Items[startIndex - 1].Next = endIndex < Count - 1 ? Items[endIndex + 1] : null;
+ }
+
+
+ if (endIndex < Count - 1)
+ {
+ Array.Copy(Items, endIndex + 1, Items, startIndex, Count - endIndex - 1);
+ }
+
+ Count -= endIndex - startIndex + 1;
+
+ while (startItem != endItem.Next)
+ {
+ _quickAccess.Remove(startItem.Address);
+ foreach (ulong addr in startItem.QuickAccessAddresses)
+ {
+ _quickAccess.Remove(addr);
+ _fastQuickAccess.Remove(addr);
+ }
+ startItem = startItem.Next;
+ }
+ }
+
+ ///
+ /// Removes a range of items from the item list
+ ///
+ /// Start address of the range
+ /// Size of the range
+ public void RemoveRange(ulong address, ulong size)
+ {
+ int startIndex = BinarySearchLeftEdge(address, address + size);
+
+ if (startIndex < 0)
+ {
+ return;
+ }
+
+ RangeItem startItem = Items[startIndex];
+
+ int endIndex = startIndex;
+
+ while (startItem is not null && startItem.Address < address + size)
+ {
+ _quickAccess.Remove(startItem.Address);
+ foreach (ulong addr in startItem.QuickAccessAddresses)
+ {
+ _quickAccess.Remove(addr);
+ _fastQuickAccess.Remove(addr);
+ }
+ startItem = startItem.Next;
+ endIndex++;
+ }
+
+ if (endIndex < Count - 1)
+ {
+ Items[endIndex + 1].Previous = startIndex > 0 ? Items[startIndex - 1] : null;
+ }
+
+ if (startIndex > 0)
+ {
+ Items[startIndex - 1].Next = endIndex < Count - 1 ? Items[endIndex + 1] : null;
+ }
+
+
+ if (endIndex < Count - 1)
+ {
+ Array.Copy(Items, endIndex + 1, Items, startIndex, Count - endIndex - 1);
+ }
+
+ Count -= endIndex - startIndex + 1;
+ }
+
+ ///
+ /// Clear all ranges.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void Clear()
+ {
+ Lock.EnterWriteLock();
+ Count = 0;
+ _quickAccess.Clear();
+ _fastQuickAccess.Clear();
+ Lock.ExitWriteLock();
+ }
+
///
/// Finds a list of regions that cover the desired (address, size) range.
/// If this range starts or ends in the middle of an existing region, it is split and only the relevant part is added.
@@ -19,17 +298,18 @@ namespace Ryujinx.Memory.Range
/// Start address of the search region
/// Size of the search region
/// Factory for creating new ranges
- public void GetOrAddRegions(List list, ulong address, ulong size, Func factory)
+ public void GetOrAddRegions(out List list, ulong address, ulong size, Func factory)
{
// (regarding the specific case this generalized function is used for)
// A new region may be split into multiple parts if multiple virtual regions have mapped to it.
// For instance, while a virtual mapping could cover 0-2 in physical space, the space 0-1 may have already been reserved...
// So we need to return both the split 0-1 and 1-2 ranges.
-
- T[] results = new T[1];
- int count = FindOverlapsNonOverlapping(address, size, ref results);
-
- if (count == 0)
+
+ Lock.EnterWriteLock();
+ (RangeItem first, RangeItem last) = FindOverlaps(address, size);
+ list = new List();
+
+ if (first is null)
{
// The region is fully unmapped. Create and add it to the range list.
T region = factory(address, size);
@@ -41,13 +321,15 @@ namespace Ryujinx.Memory.Range
ulong lastAddress = address;
ulong endAddress = address + size;
- for (int i = 0; i < count; i++)
+ RangeItem current = first;
+ while (last is not null && current is not null && current.Address < endAddress)
{
- T region = results[i];
- if (count == 1 && region.Address == address && region.Size == size)
+ T region = current.Value;
+ if (first == last && region.Address == address && region.Size == size)
{
// Exact match, no splitting required.
list.Add(region);
+ Lock.ExitWriteLock();
return;
}
@@ -75,6 +357,7 @@ namespace Ryujinx.Memory.Range
list.Add(region);
lastAddress = region.EndAddress;
+ current = current.Next;
}
if (lastAddress < endAddress)
@@ -85,6 +368,8 @@ namespace Ryujinx.Memory.Range
Add(fillRegion);
}
}
+
+ Lock.ExitWriteLock();
}
///
@@ -95,6 +380,7 @@ namespace Ryujinx.Memory.Range
/// The region to split
/// The address to split with
/// The new region (high part)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private T Split(T region, ulong splitAddress)
{
T newRegion = (T)region.Split(splitAddress);
@@ -102,5 +388,113 @@ namespace Ryujinx.Memory.Range
Add(newRegion);
return newRegion;
}
+
+ ///
+ /// Gets an item on the list overlapping the specified memory range.
+ ///
+ /// Start address of the range
+ /// Size in bytes of the range
+ /// The leftmost overlapping item, or null if none is found
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override RangeItem FindOverlap(ulong address, ulong size)
+ {
+ if (_quickAccess.TryGetValue(address, out RangeItem overlap))
+ {
+ return overlap;
+ }
+
+ int index = BinarySearchLeftEdge(address, address + size);
+
+ if (index < 0)
+ {
+ return null;
+ }
+
+ if (Items[index].Address < address)
+ {
+ _quickAccess.TryAdd(address, Items[index]);
+ Items[index].QuickAccessAddresses.Add(address);
+ }
+
+ return Items[index];
+ }
+
+ ///
+ /// Gets an item on the list overlapping the specified memory range.
+ ///
+ /// Start address of the range
+ /// Size in bytes of the range
+ /// The overlapping item, or null if none is found
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override RangeItem FindOverlapFast(ulong address, ulong size)
+ {
+ if (_quickAccess.TryGetValue(address, out RangeItem overlap) || _fastQuickAccess.TryGetValue(address, out overlap))
+ {
+ return overlap;
+ }
+
+ int index = BinarySearch(address, address + size);
+
+ if (index < 0)
+ {
+ return null;
+ }
+
+ if (Items[index].Address < address)
+ {
+ _quickAccess.TryAdd(address, Items[index]);
+ }
+ else
+ {
+ _fastQuickAccess.TryAdd(address, Items[index]);
+ }
+
+ Items[index].QuickAccessAddresses.Add(address);
+
+ return Items[index];
+ }
+
+ ///
+ /// Gets all items on the list overlapping the specified memory range.
+ ///
+ /// Start address of the range
+ /// Size in bytes of the range
+ /// The first and last overlapping items, or null if none are found
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public (RangeItem, RangeItem) FindOverlaps(ulong address, ulong size)
+ {
+ if (_quickAccess.TryGetValue(address, out RangeItem overlap))
+ {
+ if (overlap.Next is null || overlap.Next.Address >= address + size)
+ {
+ return (overlap, overlap);
+ }
+
+ return (overlap, Items[BinarySearchRightEdge(address, address + size)]);
+ }
+
+ (int index, int endIndex) = BinarySearchEdges(address, address + size);
+
+ if (index < 0)
+ {
+ return (null, null);
+ }
+
+ if (Items[index].Address < address)
+ {
+ _quickAccess.TryAdd(address, Items[index]);
+ Items[index].QuickAccessAddresses.Add(address);
+ }
+
+ return (Items[index], Items[endIndex - 1]);
+ }
+
+ public override IEnumerator GetEnumerator()
+ {
+ for (int i = 0; i < Count; i++)
+ {
+ yield return Items[i].Value;
+ }
+ }
}
}
diff --git a/src/Ryujinx.Memory/Range/RangeList.cs b/src/Ryujinx.Memory/Range/RangeList.cs
index 72cef1de0..600ff748e 100644
--- a/src/Ryujinx.Memory/Range/RangeList.cs
+++ b/src/Ryujinx.Memory/Range/RangeList.cs
@@ -1,61 +1,91 @@
using System;
-using System.Collections;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Runtime.CompilerServices;
+using System.Threading;
namespace Ryujinx.Memory.Range
{
+ public class RangeItem(TValue value) where TValue : IRange
+ {
+ public RangeItem Next;
+ public RangeItem Previous;
+
+ public readonly ulong Address = value.Address;
+ public readonly ulong EndAddress = value.Address + value.Size;
+
+ public readonly TValue Value = value;
+
+ public readonly List QuickAccessAddresses = [];
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool OverlapsWith(ulong address, ulong endAddress)
+ {
+ return Address < endAddress && address < EndAddress;
+ }
+ }
+
+ class AddressEqualityComparer : IEqualityComparer
+ {
+ public bool Equals(ulong u1, ulong u2)
+ {
+ return u1 == u2;
+ }
+
+ public int GetHashCode(ulong value) => (int)(value >> 5);
+
+ public static readonly AddressEqualityComparer Comparer = new();
+ }
+
+ ///
+ /// Result of an Overlaps Finder function. WARNING: if the result is from the optimized
+ /// Overlaps Finder, the StartIndex will be -1 even when the result isn't empty
+ ///
+ ///
+ /// startIndex is inclusive.
+ /// endIndex is exclusive.
+ ///
+ public readonly struct OverlapResult where T : IRange
+ {
+ public readonly int StartIndex = -1;
+ public readonly int EndIndex = -1;
+ public readonly RangeItem QuickResult;
+ public int Count => EndIndex - StartIndex;
+
+ public OverlapResult(int startIndex, int endIndex, RangeItem quickResult = null)
+ {
+ this.StartIndex = startIndex;
+ this.EndIndex = endIndex;
+ this.QuickResult = quickResult;
+ }
+ }
+
///
/// Sorted list of ranges that supports binary search.
///
/// Type of the range.
- public class RangeList : IEnumerable where T : IRange
+ public class RangeList : RangeListBase where T : IRange
{
- private readonly struct RangeItem where TValue : IRange
- {
- public readonly ulong Address;
- public readonly ulong EndAddress;
-
- public readonly TValue Value;
-
- public RangeItem(TValue value)
- {
- Value = value;
-
- Address = value.Address;
- EndAddress = value.Address + value.Size;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool OverlapsWith(ulong address, ulong endAddress)
- {
- return Address < endAddress && address < EndAddress;
- }
- }
-
- private const int BackingInitialSize = 1024;
- private const int ArrayGrowthSize = 32;
-
- private RangeItem[] _items;
- private readonly int _backingGrowthSize;
-
- public int Count { get; protected set; }
+ public readonly ReaderWriterLockSlim Lock = new();
+
+ private readonly Dictionary> _quickAccess = new(AddressEqualityComparer.Comparer);
+ ///
+ /// Creates a new range list.
+ ///
+ public RangeList() { }
+
///
/// Creates a new range list.
///
/// The initial size of the backing array
- public RangeList(int backingInitialSize = BackingInitialSize)
- {
- _backingGrowthSize = backingInitialSize;
- _items = new RangeItem[backingInitialSize];
- }
+ public RangeList(int backingInitialSize) : base(backingInitialSize) { }
///
/// Adds a new item to the list.
///
/// The item to be added
- public void Add(T item)
+ public override void Add(T item)
{
int index = BinarySearch(item.Address);
@@ -72,27 +102,27 @@ namespace Ryujinx.Memory.Range
///
/// The item to be updated
/// True if the item was located and updated, false otherwise
- public bool Update(T item)
+ protected override bool Update(T item)
{
int index = BinarySearch(item.Address);
if (index >= 0)
{
- while (index > 0 && _items[index - 1].Address == item.Address)
- {
- index--;
- }
-
while (index < Count)
{
- if (_items[index].Value.Equals(item))
+ if (Items[index].Value.Equals(item))
{
- _items[index] = new RangeItem(item);
+ foreach (ulong address in Items[index].QuickAccessAddresses)
+ {
+ _quickAccess.Remove(address);
+ }
+
+ Items[index] = new RangeItem(item);
return true;
}
- if (_items[index].Address > item.Address)
+ if (Items[index].Address > item.Address)
{
break;
}
@@ -107,23 +137,42 @@ namespace Ryujinx.Memory.Range
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Insert(int index, RangeItem item)
{
- if (Count + 1 > _items.Length)
+ Debug.Assert(item.Address != item.EndAddress);
+
+ Debug.Assert(item.Address % 32 == 0);
+
+ if (Count + 1 > Items.Length)
{
- Array.Resize(ref _items, _items.Length + _backingGrowthSize);
+ Array.Resize(ref Items, Items.Length + BackingGrowthSize);
}
if (index >= Count)
{
if (index == Count)
{
- _items[Count++] = item;
+ if (index != 0)
+ {
+ item.Previous = Items[index - 1];
+ Items[index - 1].Next = item;
+ }
+ Items[index] = item;
+ Count++;
}
}
else
{
- Array.Copy(_items, index, _items, index + 1, Count - index);
+ Array.Copy(Items, index, Items, index + 1, Count - index);
- _items[index] = item;
+ Items[index] = item;
+ if (index != 0)
+ {
+ item.Previous = Items[index - 1];
+ Items[index - 1].Next = item;
+ }
+
+ item.Next = Items[index + 1];
+ Items[index + 1].Previous = item;
+
Count++;
}
}
@@ -131,9 +180,71 @@ namespace Ryujinx.Memory.Range
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void RemoveAt(int index)
{
+ foreach (ulong address in Items[index].QuickAccessAddresses)
+ {
+ _quickAccess.Remove(address);
+ }
+
+ if (index < Count - 1)
+ {
+ Items[index + 1].Previous = index > 0 ? Items[index - 1] : null;
+ }
+
+ if (index > 0)
+ {
+ Items[index - 1].Next = index < Count - 1 ? Items[index + 1] : null;
+ }
+
if (index < --Count)
{
- Array.Copy(_items, index + 1, _items, index, Count - index);
+ Array.Copy(Items, index + 1, Items, index, Count - index);
+ }
+ }
+
+ ///
+ /// Removes a range of items from the item list
+ ///
+ /// The first item in the range of items to be removed
+ /// The last item in the range of items to be removed
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override void RemoveRange(RangeItem startItem, RangeItem endItem)
+ {
+ if (endItem.Next is not null)
+ {
+ endItem.Next.Previous = startItem.Previous;
+ }
+
+ if (startItem.Previous is not null)
+ {
+ startItem.Previous.Next = endItem.Next;
+ }
+
+ RangeItem current = startItem;
+ while (current != endItem.Next)
+ {
+ foreach (ulong address in current.QuickAccessAddresses)
+ {
+ _quickAccess.Remove(address);
+ }
+
+ current = current.Next;
+ }
+
+ RangeItem[] array = [];
+ OverlapResult overlapResult = FindOverlaps(startItem.Address, endItem.EndAddress, ref array);
+
+ if (overlapResult.EndIndex < Count)
+ {
+ Array.Copy(Items, overlapResult.EndIndex, Items, overlapResult.StartIndex, Count - overlapResult.EndIndex);
+ Count -= overlapResult.Count;
+ }
+ else if (overlapResult.EndIndex == Count)
+ {
+ Count = overlapResult.StartIndex;
+ }
+ else
+ {
+ Debug.Assert(false);
}
}
@@ -142,27 +253,22 @@ namespace Ryujinx.Memory.Range
///
/// The item to be removed
/// True if the item was removed, or false if it was not found
- public bool Remove(T item)
+ public override bool Remove(T item)
{
int index = BinarySearch(item.Address);
if (index >= 0)
{
- while (index > 0 && _items[index - 1].Address == item.Address)
- {
- index--;
- }
-
while (index < Count)
{
- if (_items[index].Value.Equals(item))
+ if (Items[index].Value.Equals(item))
{
RemoveAt(index);
return true;
}
- if (_items[index].Address > item.Address)
+ if (Items[index].Address > item.Address)
{
break;
}
@@ -173,310 +279,130 @@ namespace Ryujinx.Memory.Range
return false;
}
-
+
///
- /// Updates an item's end address.
- ///
- /// The item to be updated
- public void UpdateEndAddress(T item)
- {
- int index = BinarySearch(item.Address);
-
- if (index >= 0)
- {
- while (index > 0 && _items[index - 1].Address == item.Address)
- {
- index--;
- }
-
- while (index < Count)
- {
- if (_items[index].Value.Equals(item))
- {
- _items[index] = new RangeItem(item);
-
- return;
- }
-
- if (_items[index].Address > item.Address)
- {
- break;
- }
-
- index++;
- }
- }
- }
-
- ///
- /// Gets the first item on the list overlapping in memory with the specified item.
+ /// Gets an item on the list overlapping the specified memory range.
///
///
- /// Despite the name, this has no ordering guarantees of the returned item.
- /// It only ensures that the item returned overlaps the specified item.
- ///
- /// Item to check for overlaps
- /// The overlapping item, or the default value for the type if none found
- public T FindFirstOverlap(T item)
- {
- return FindFirstOverlap(item.Address, item.Size);
- }
-
- ///
- /// Gets the first item on the list overlapping the specified memory range.
- ///
- ///
- /// Despite the name, this has no ordering guarantees of the returned item.
+ /// This has no ordering guarantees of the returned item.
/// It only ensures that the item returned overlaps the specified memory range.
///
/// Start address of the range
/// Size in bytes of the range
/// The overlapping item, or the default value for the type if none found
- public T FindFirstOverlap(ulong address, ulong size)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override RangeItem FindOverlap(ulong address, ulong size)
{
+ int index = BinarySearchLeftEdge(address, address + size);
+
+ if (index < 0)
+ {
+ return null;
+ }
+
+ return Items[index];
+ }
+
+ ///
+ /// Gets an item on the list overlapping the specified memory range.
+ ///
+ ///
+ /// This has no ordering guarantees of the returned item.
+ /// It only ensures that the item returned overlaps the specified memory range.
+ ///
+ /// Start address of the range
+ /// Size in bytes of the range
+ /// The overlapping item, or the default value for the type if none found
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override RangeItem FindOverlapFast(ulong address, ulong size)
+ {
+ if (_quickAccess.TryGetValue(address, out RangeItem quickResult))
+ {
+ return quickResult;
+ }
+
int index = BinarySearch(address, address + size);
if (index < 0)
{
- return default;
+ return null;
}
- return _items[index].Value;
- }
+ if (Items[index].OverlapsWith(address, address + 1))
+ {
+ _quickAccess.Add(address, Items[index]);
+ Items[index].QuickAccessAddresses.Add(address);
+ }
- ///
- /// Gets all items overlapping with the specified item in memory.
- ///
- /// Item to check for overlaps
- /// Output array where matches will be written. It is automatically resized to fit the results
- /// The number of overlapping items found
- public int FindOverlaps(T item, ref T[] output)
- {
- return FindOverlaps(item.Address, item.Size, ref output);
+ return Items[index];
}
-
+
///
/// Gets all items on the list overlapping the specified memory range.
///
/// Start address of the range
/// Size in bytes of the range
/// Output array where matches will be written. It is automatically resized to fit the results
- /// The number of overlapping items found
- public int FindOverlaps(ulong address, ulong size, ref T[] output)
+ /// Range information of overlapping items found
+ private OverlapResult FindOverlaps(ulong address, ulong size, ref RangeItem[] output)
{
- int outputIndex = 0;
+ int outputCount = 0;
ulong endAddress = address + size;
+
+ int startIndex = BinarySearch(address, endAddress);
+ if (startIndex < 0)
+ startIndex = ~startIndex;
+ int endIndex = -1;
- for (int i = 0; i < Count; i++)
+ for (int i = startIndex; i < Count; i++)
{
- ref RangeItem item = ref _items[i];
+ ref RangeItem item = ref Items[i];
if (item.Address >= endAddress)
{
+ endIndex = i;
break;
}
if (item.OverlapsWith(address, endAddress))
{
- if (outputIndex == output.Length)
- {
- Array.Resize(ref output, outputIndex + ArrayGrowthSize);
- }
-
- output[outputIndex++] = item.Value;
+ outputCount++;
}
}
- return outputIndex;
- }
-
- ///
- /// Gets all items overlapping with the specified item in memory.
- ///
- ///
- /// This method only returns correct results if none of the items on the list overlaps with
- /// each other. If that is not the case, this method should not be used.
- /// This method is faster than the regular method to find all overlaps.
- ///
- /// Item to check for overlaps
- /// Output array where matches will be written. It is automatically resized to fit the results
- /// The number of overlapping items found
- public int FindOverlapsNonOverlapping(T item, ref T[] output)
- {
- return FindOverlapsNonOverlapping(item.Address, item.Size, ref output);
- }
-
- ///
- /// Gets all items on the list overlapping the specified memory range.
- ///
- ///
- /// This method only returns correct results if none of the items on the list overlaps with
- /// each other. If that is not the case, this method should not be used.
- /// This method is faster than the regular method to find all overlaps.
- ///
- /// Start address of the range
- /// Size in bytes of the range
- /// Output array where matches will be written. It is automatically resized to fit the results
- /// The number of overlapping items found
- public int FindOverlapsNonOverlapping(ulong address, ulong size, ref T[] output)
- {
- // This is a bit faster than FindOverlaps, but only works
- // when none of the items on the list overlaps with each other.
- int outputIndex = 0;
-
- ulong endAddress = address + size;
-
- int index = BinarySearch(address, endAddress);
-
- if (index >= 0)
+ if (endIndex == -1 && outputCount > 0)
{
- while (index > 0 && _items[index - 1].OverlapsWith(address, endAddress))
- {
- index--;
- }
-
- do
- {
- if (outputIndex == output.Length)
- {
- Array.Resize(ref output, outputIndex + ArrayGrowthSize);
- }
-
- output[outputIndex++] = _items[index++].Value;
- }
- while (index < Count && _items[index].OverlapsWith(address, endAddress));
+ endIndex = Count;
}
- return outputIndex;
- }
-
- ///
- /// Gets all items on the list with the specified memory address.
- ///
- /// Address to find
- /// Output array where matches will be written. It is automatically resized to fit the results
- /// The number of matches found
- public int FindOverlaps(ulong address, ref T[] output)
- {
- int index = BinarySearch(address);
-
- int outputIndex = 0;
-
- if (index >= 0)
+ if (outputCount > 0 && outputCount == endIndex - startIndex)
{
- while (index > 0 && _items[index - 1].Address == address)
- {
- index--;
- }
-
- while (index < Count)
- {
- ref RangeItem overlap = ref _items[index++];
-
- if (overlap.Address != address)
- {
- break;
- }
-
- if (outputIndex == output.Length)
- {
- Array.Resize(ref output, outputIndex + ArrayGrowthSize);
- }
-
- output[outputIndex++] = overlap.Value;
- }
+ Array.Resize(ref output, outputCount);
+ Array.Copy(Items, endIndex - outputCount, output, 0, outputCount);
+
+ return new OverlapResult(startIndex, endIndex);
}
-
- return outputIndex;
- }
-
- ///
- /// Performs binary search on the internal list of items.
- ///
- /// Address to find
- /// List index of the item, or complement index of nearest item with lower value on the list
- private int BinarySearch(ulong address)
- {
- int left = 0;
- int right = Count - 1;
-
- while (left <= right)
+ else if (outputCount > 0)
{
- int range = right - left;
-
- int middle = left + (range >> 1);
-
- ref RangeItem item = ref _items[middle];
-
- if (item.Address == address)
+ Array.Resize(ref output, outputCount);
+ int arrIndex = 0;
+ for (int i = startIndex; i < endIndex; i++)
{
- return middle;
- }
-
- if (address < item.Address)
- {
- right = middle - 1;
- }
- else
- {
- left = middle + 1;
+ output[arrIndex++] = Items[i];
}
+
+ return new OverlapResult(endIndex - outputCount, endIndex);
}
-
- return ~left;
+
+ return new OverlapResult();
}
- ///
- /// Performs binary search for items overlapping a given memory range.
- ///
- /// Start address of the range
- /// End address of the range
- /// List index of the item, or complement index of nearest item with lower value on the list
- private int BinarySearch(ulong address, ulong endAddress)
- {
- int left = 0;
- int right = Count - 1;
-
- while (left <= right)
- {
- int range = right - left;
-
- int middle = left + (range >> 1);
-
- ref RangeItem item = ref _items[middle];
-
- if (item.OverlapsWith(address, endAddress))
- {
- return middle;
- }
-
- if (address < item.Address)
- {
- right = middle - 1;
- }
- else
- {
- left = middle + 1;
- }
- }
-
- return ~left;
- }
-
- public IEnumerator GetEnumerator()
+ public override IEnumerator GetEnumerator()
{
for (int i = 0; i < Count; i++)
{
- yield return _items[i].Value;
- }
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- for (int i = 0; i < Count; i++)
- {
- yield return _items[i].Value;
+ yield return Items[i].Value;
}
}
}
diff --git a/src/Ryujinx.Memory/Range/RangeListBase.cs b/src/Ryujinx.Memory/Range/RangeListBase.cs
new file mode 100644
index 000000000..7e26442f0
--- /dev/null
+++ b/src/Ryujinx.Memory/Range/RangeListBase.cs
@@ -0,0 +1,359 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace Ryujinx.Memory.Range
+{
+ public abstract class RangeListBase : IEnumerable where T : IRange
+ {
+ protected const int BackingInitialSize = 1024;
+
+ protected RangeItem[] Items;
+ protected readonly int BackingGrowthSize;
+
+ public int Count { get; protected set; }
+
+ ///
+ /// Creates a new range list.
+ ///
+ /// The initial size of the backing array
+ protected RangeListBase(int backingInitialSize = BackingInitialSize)
+ {
+ BackingGrowthSize = backingInitialSize;
+ Items = new RangeItem[backingInitialSize];
+ }
+
+ public abstract void Add(T item);
+
+ ///
+ /// Updates an item's end address on the list. Address must be the same.
+ ///
+ /// The item to be updated
+ /// True if the item was located and updated, false otherwise
+ protected abstract bool Update(T item);
+
+ public abstract bool Remove(T item);
+
+ public abstract void RemoveRange(RangeItem startItem, RangeItem endItem);
+
+ public abstract RangeItem FindOverlap(ulong address, ulong size);
+
+ public abstract RangeItem FindOverlapFast(ulong address, ulong size);
+
+ ///
+ /// Performs binary search on the internal list of items.
+ ///
+ /// Address to find
+ /// List index of the item, or complement index of nearest item with lower value on the list
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected int BinarySearch(ulong address)
+ {
+ int left = 0;
+ int right = Count - 1;
+
+ while (left <= right)
+ {
+ int range = right - left;
+
+ int middle = left + (range >> 1);
+
+ ref RangeItem item = ref Items[middle];
+
+ if (item.Address == address)
+ {
+ return middle;
+ }
+
+ if (address < item.Address)
+ {
+ right = middle - 1;
+ }
+ else
+ {
+ left = middle + 1;
+ }
+ }
+
+ return ~left;
+ }
+
+ ///
+ /// Performs binary search for items overlapping a given memory range.
+ ///
+ /// Start address of the range
+ /// End address of the range
+ /// List index of the item, or complement index of nearest item with lower value on the list
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected int BinarySearch(ulong address, ulong endAddress)
+ {
+ int left = 0;
+ int right = Count - 1;
+
+ while (left <= right)
+ {
+ int range = right - left;
+
+ int middle = left + (range >> 1);
+
+ ref RangeItem item = ref Items[middle];
+
+ if (item.OverlapsWith(address, endAddress))
+ {
+ return middle;
+ }
+
+ if (address < item.Address)
+ {
+ right = middle - 1;
+ }
+ else
+ {
+ left = middle + 1;
+ }
+ }
+
+ return ~left;
+ }
+
+ ///
+ /// Performs binary search for items overlapping a given memory range.
+ ///
+ /// Start address of the range
+ /// End address of the range
+ /// List index of the item, or complement index of nearest item with lower value on the list
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected int BinarySearchLeftEdge(ulong address, ulong endAddress)
+ {
+ if (Count == 0)
+ return ~0;
+
+ int left = 0;
+ int right = Count - 1;
+
+ while (left <= right)
+ {
+ int range = right - left;
+
+ int middle = left + (range >> 1);
+
+ ref RangeItem item = ref Items[middle];
+
+ bool match = item.OverlapsWith(address, endAddress);
+
+ if (range == 0)
+ {
+ if (match)
+ return middle;
+ else if (address < item.Address)
+ return ~(right);
+ else
+ return ~(right + 1);
+ }
+
+ if (match)
+ {
+ right = middle;
+ }
+ else if (address < item.Address)
+ {
+ right = middle - 1;
+ }
+ else
+ {
+ left = middle + 1;
+ }
+ }
+
+ return ~left;
+ }
+
+ ///
+ /// Performs binary search for items overlapping a given memory range.
+ ///
+ /// Start address of the range
+ /// End address of the range
+ /// List index of the item, or complement index of nearest item with lower value on the list
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected int BinarySearchRightEdge(ulong address, ulong endAddress)
+ {
+ if (Count == 0)
+ return ~0;
+
+ int left = 0;
+ int right = Count - 1;
+
+ while (left <= right)
+ {
+ int range = right - left;
+
+ int middle = right - (range >> 1);
+
+ ref RangeItem item = ref Items[middle];
+
+ bool match = item.OverlapsWith(address, endAddress);
+
+ if (range == 0)
+ {
+ if (match)
+ return middle;
+ else if (endAddress > item.EndAddress)
+ return ~(left + 1);
+ else
+ return ~(left);
+ }
+
+ if (match)
+ {
+ left = middle;
+ }
+ else if (address < item.Address)
+ {
+ right = middle - 1;
+ }
+ else
+ {
+ left = middle + 1;
+ }
+ }
+
+ return ~left;
+ }
+
+ ///
+ /// Performs binary search for items overlapping a given memory range.
+ ///
+ /// Start address of the range
+ /// End address of the range
+ /// Range information (inclusive, exclusive) of items that overlaps, or complement index of nearest item with lower value on the list
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected (int, int) BinarySearchEdges(ulong address, ulong endAddress)
+ {
+ if (Count == 0)
+ return (~0, ~0);
+
+ if (Count == 1)
+ {
+ ref RangeItem item = ref Items[0];
+
+ if (item.OverlapsWith(address, endAddress))
+ {
+ return (0, 1);
+ }
+
+ if (address < item.Address)
+ {
+ return (~0, ~0);
+ }
+ else
+ {
+ return (~1, ~1);
+ }
+ }
+
+ int left = 0;
+ int right = Count - 1;
+
+ int leftEdge = -1;
+ int rightEdgeMatch = -1;
+ int rightEdgeNoMatch = -1;
+
+ while (left <= right)
+ {
+ int range = right - left;
+
+ int middle = left + (range >> 1);
+
+ ref RangeItem item = ref Items[middle];
+
+ bool match = item.OverlapsWith(address, endAddress);
+
+ if (range == 0)
+ {
+ if (match)
+ {
+ leftEdge = middle;
+ break;
+ }
+ else if (address < item.Address)
+ {
+ return (~right, ~right);
+ }
+ else
+ {
+ return (~(right + 1), ~(right + 1));
+ }
+ }
+
+ if (match)
+ {
+ right = middle;
+ if (rightEdgeMatch == -1)
+ rightEdgeMatch = middle;
+ }
+ else if (address < item.Address)
+ {
+ right = middle - 1;
+ rightEdgeNoMatch = middle;
+ }
+ else
+ {
+ left = middle + 1;
+ }
+ }
+
+ if (left > right)
+ {
+ return (~left, ~left);
+ }
+
+ if (rightEdgeMatch == -1)
+ {
+ return (leftEdge, leftEdge + 1);
+ }
+
+ left = rightEdgeMatch;
+ right = rightEdgeNoMatch > 0 ? rightEdgeNoMatch : Count - 1;
+
+ while (left <= right)
+ {
+ int range = right - left;
+
+ int middle = right - (range >> 1);
+
+ ref RangeItem item = ref Items[middle];
+
+ bool match = item.OverlapsWith(address, endAddress);
+
+ if (range == 0)
+ {
+ if (match)
+ return (leftEdge, middle + 1);
+ else
+ return (leftEdge, middle);
+ }
+
+ if (match)
+ {
+ left = middle;
+ }
+ else if (address < item.Address)
+ {
+ right = middle - 1;
+ }
+ else
+ {
+ left = middle + 1;
+ }
+ }
+
+ return (leftEdge, right + 1);
+ }
+
+ public abstract IEnumerator GetEnumerator();
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
diff --git a/src/Ryujinx.Memory/Tracking/MemoryTracking.cs b/src/Ryujinx.Memory/Tracking/MemoryTracking.cs
index e7791fec3..8f7ef0be2 100644
--- a/src/Ryujinx.Memory/Tracking/MemoryTracking.cs
+++ b/src/Ryujinx.Memory/Tracking/MemoryTracking.cs
@@ -1,4 +1,3 @@
-using Ryujinx.Common.Pools;
using Ryujinx.Memory.Range;
using System.Collections.Generic;
@@ -76,17 +75,16 @@ namespace Ryujinx.Memory.Tracking
lock (TrackingLock)
{
- ref VirtualRegion[] overlaps = ref ThreadStaticArray.Get();
-
for (int type = 0; type < 2; type++)
{
NonOverlappingRangeList regions = type == 0 ? _virtualRegions : _guestVirtualRegions;
-
- int count = regions.FindOverlapsNonOverlapping(va, size, ref overlaps);
-
- for (int i = 0; i < count; i++)
+ regions.Lock.EnterReadLock();
+ (RangeItem first, RangeItem last) = regions.FindOverlaps(va, size);
+
+ RangeItem current = first;
+ while (last != null && current != last.Next)
{
- VirtualRegion region = overlaps[i];
+ VirtualRegion region = current.Value;
// If the region has been fully remapped, signal that it has been mapped again.
bool remapped = _memoryManager.IsRangeMapped(region.Address, region.Size);
@@ -96,7 +94,9 @@ namespace Ryujinx.Memory.Tracking
}
region.UpdateProtection();
+ current = current.Next;
}
+ regions.Lock.ExitReadLock();
}
}
}
@@ -114,20 +114,21 @@ namespace Ryujinx.Memory.Tracking
lock (TrackingLock)
{
- ref VirtualRegion[] overlaps = ref ThreadStaticArray.Get();
-
for (int type = 0; type < 2; type++)
{
NonOverlappingRangeList regions = type == 0 ? _virtualRegions : _guestVirtualRegions;
-
- int count = regions.FindOverlapsNonOverlapping(va, size, ref overlaps);
-
- for (int i = 0; i < count; i++)
+ regions.Lock.EnterReadLock();
+ (RangeItem first, RangeItem last) = regions.FindOverlaps(va, size);
+
+ RangeItem current = first;
+ while (last != null && current != last.Next)
{
- VirtualRegion region = overlaps[i];
+ VirtualRegion region = current.Value;
region.SignalMappingChanged(false);
+ current = current.Next;
}
+ regions.Lock.ExitReadLock();
}
}
}
@@ -165,10 +166,11 @@ namespace Ryujinx.Memory.Tracking
/// A list of virtual regions within the given range
internal List GetVirtualRegionsForHandle(ulong va, ulong size, bool guest)
{
- List result = [];
NonOverlappingRangeList regions = guest ? _guestVirtualRegions : _virtualRegions;
- regions.GetOrAddRegions(result, va, size, (va, size) => new VirtualRegion(this, va, size, guest));
-
+ regions.Lock.EnterUpgradeableReadLock();
+ regions.GetOrAddRegions(out List result, va, size, (va, size) => new VirtualRegion(this, va, size, guest));
+ regions.Lock.ExitUpgradeableReadLock();
+
return result;
}
@@ -296,25 +298,33 @@ namespace Ryujinx.Memory.Tracking
lock (TrackingLock)
{
- ref VirtualRegion[] overlaps = ref ThreadStaticArray.Get();
-
NonOverlappingRangeList regions = guest ? _guestVirtualRegions : _virtualRegions;
+ List> overlaps = [];
+
+ // We use the non-span method here because keeping the lock will cause a deadlock.
+ regions.Lock.EnterReadLock();
+ (RangeItem first, RangeItem last) = regions.FindOverlaps(address, size);
+
+ RangeItem current = first;
+ while (last != null && current != last.Next)
+ {
+ overlaps.Add(current);
+ current = current.Next;
+ }
+ regions.Lock.ExitReadLock();
- int count = regions.FindOverlapsNonOverlapping(address, size, ref overlaps);
-
- if (count == 0 && !precise)
+ if (first is null && !precise)
{
if (_memoryManager.IsRangeMapped(address, size))
{
// TODO: There is currently the possibility that a page can be protected after its virtual region is removed.
// This code handles that case when it happens, but it would be better to find out how this happens.
_memoryManager.TrackingReprotect(address & ~(ulong)(_pageSize - 1), (ulong)_pageSize, MemoryPermission.ReadAndWrite, guest);
+
return true; // This memory _should_ be mapped, so we need to try again.
}
- else
- {
- shouldThrow = true;
- }
+
+ shouldThrow = true;
}
else
{
@@ -324,9 +334,9 @@ namespace Ryujinx.Memory.Tracking
size += (ulong)_pageSize;
}
- for (int i = 0; i < count; i++)
+ for (int i = 0; i < overlaps.Count; i++)
{
- VirtualRegion region = overlaps[i];
+ VirtualRegion region = overlaps[i].Value;
if (precise)
{
diff --git a/src/Ryujinx/Assets/Styles/Styles.xaml b/src/Ryujinx/Assets/Styles/Styles.xaml
index ea6096792..34c7e2516 100644
--- a/src/Ryujinx/Assets/Styles/Styles.xaml
+++ b/src/Ryujinx/Assets/Styles/Styles.xaml
@@ -266,7 +266,7 @@