Compare commits

...

19 Commits

Author SHA1 Message Date
Vladimir Sokolov
f9fe7ffc6b Merge 03b4a2412b into 9f94aa1c79 2025-02-01 12:32:31 +00:00
Vova
03b4a2412b Added ReleaseInformation 2025-02-01 22:32:07 +10:00
Vova
9397ef8a8a Merge branch 'master' of https://github.com/Goodfeat/Ryujinx_alt 2025-02-01 21:39:54 +10:00
Vova
720a81ef6f Add ConfigFileNameOverride in ReleaseInformation 2025-02-01 21:38:12 +10:00
Vladimir Sokolov
25c47368db Merge branch 'master' into master 2025-02-01 20:52:57 +10:00
Evan Husted
9f94aa1c79 misc: chore: gpu: Lower default Syncpoint wait timeout from 1 second to 500ms 2025-02-01 03:30:13 -06:00
Evan Husted
2c9a26c11c misc: chore: Regular Architecture bool properties in RunningPlatform without OS constraint 2025-02-01 03:29:24 -06:00
Evan Husted
a4a15a4c80 misc: chore: simplify graphics backend selection logic in RendererHost constructor 2025-02-01 03:28:49 -06:00
Evan Husted
cc3b95eee1 misc: chore: More descriptive error for trying to create a Metal EmbeddedWindow on non-ARM Mac 2025-02-01 03:28:26 -06:00
Vladimir Sokolov
32df1da773 Merge branch 'master' into master 2025-02-01 17:45:47 +10:00
Evan Husted
2ab806f759 UI: [ci skip] Fix ContentDialog symbols being backwards for right-to-left languages 2025-02-01 01:42:12 -06:00
Vova
3a8737f0e6 fixed bugs and renamed method to GetArguments 2025-02-01 17:07:04 +10:00
Vova
d8cf67d358 Merge branch 'master' of https://github.com/Goodfeat/Ryujinx_alt 2025-02-01 16:25:04 +10:00
Vladimir Sokolov
fd258a1f6a Merge branch 'Ryubing:master' into master 2025-02-01 16:22:54 +10:00
Vova
b8fe778299 Added a window with settings for shortcuts.
Added new arguments for shortcuts.
When starting a game with arguments, a separate independent setting will be used
2025-02-01 16:21:32 +10:00
Evan Husted
6d75410bd2 UI: Use the dynamic Ryujinx/Ryujinx Canary for dialog titles 2025-01-30 21:57:03 -06:00
Evan Husted
196b2eaf66 misc: chore: [ci skip] Remove needless fs integrity checks get in aoc extractor 2025-01-30 20:54:08 -06:00
Evan Husted
82fe519766 misc: chore: [ci skip] fix log on AOC extraction failure 2025-01-30 20:52:12 -06:00
Vova
d76da6e4df Added --backend-threading parameter for launching games via shortcut 2025-01-29 21:45:48 +10:00
20 changed files with 938 additions and 230 deletions

View File

@@ -10,14 +10,18 @@ namespace Ryujinx.Common.Helper
public static bool IsMacOS => OperatingSystem.IsMacOS();
public static bool IsWindows => OperatingSystem.IsWindows();
public static bool IsLinux => OperatingSystem.IsLinux();
public static bool IsArm => RuntimeInformation.OSArchitecture is Architecture.Arm64;
public static bool IsX64 => RuntimeInformation.OSArchitecture is Architecture.X64;
public static bool IsIntelMac => IsMacOS && RuntimeInformation.OSArchitecture is Architecture.X64;
public static bool IsArmMac => IsMacOS && RuntimeInformation.OSArchitecture is Architecture.Arm64;
public static bool IsIntelMac => IsMacOS && IsX64;
public static bool IsArmMac => IsMacOS && IsArm;
public static bool IsX64Windows => IsWindows && (RuntimeInformation.OSArchitecture is Architecture.X64);
public static bool IsArmWindows => IsWindows && (RuntimeInformation.OSArchitecture is Architecture.Arm64);
public static bool IsX64Windows => IsWindows && IsX64;
public static bool IsArmWindows => IsWindows && IsArm;
public static bool IsX64Linux => IsLinux && (RuntimeInformation.OSArchitecture is Architecture.X64);
public static bool IsArmLinux => IsLinux && (RuntimeInformation.OSArchitecture is Architecture.Arm64);
public static bool IsX64Linux => IsLinux && IsX64;
public static bool IsArmLinux => IsLinux && IsArmMac;
}
}

View File

@@ -13,12 +13,14 @@ namespace Ryujinx.Common
public const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%";
private const string ReleaseChannelName = "%%RYUJINX_TARGET_RELEASE_CHANNEL_NAME%%";
private const string ConfigFileName = "%%RYUJINX_CONFIG_FILE_NAME%%";
private const string ConfigFileNameOverride = "%%RYUJINX_CONFIG_FILE_NAME_OVERRIDE%%";
public const string ReleaseChannelOwner = "%%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER%%";
public const string ReleaseChannelSourceRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO%%";
public const string ReleaseChannelRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_REPO%%";
public static string ConfigName => !ConfigFileName.StartsWith("%%") ? ConfigFileName : "Config.json";
public static string CustomConfigNameOverride => !ConfigFileNameOverride.StartsWith("%%") ? ConfigFileNameOverride : "CustomConfigOverride.json";
public static bool IsValid =>
!BuildGitHash.StartsWith("%%") &&
@@ -26,7 +28,8 @@ namespace Ryujinx.Common
!ReleaseChannelOwner.StartsWith("%%") &&
!ReleaseChannelSourceRepo.StartsWith("%%") &&
!ReleaseChannelRepo.StartsWith("%%") &&
!ConfigFileName.StartsWith("%%");
!ConfigFileName.StartsWith("%%") &&
!ConfigFileNameOverride.StartsWith("%%");
public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel);

View File

@@ -83,11 +83,11 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
// TODO: Remove this when GPU channel scheduling will be implemented.
if (timeout == Timeout.InfiniteTimeSpan)
{
timeout = TimeSpan.FromSeconds(1);
timeout = TimeSpan.FromMilliseconds(500);
}
using ManualResetEvent waitEvent = new(false);
SyncpointWaiterHandle info = _syncpoints[id].RegisterCallback(threshold, (x) => waitEvent.Set());
SyncpointWaiterHandle info = _syncpoints[id].RegisterCallback(threshold, _ => waitEvent.Set());
if (info == null)
{
@@ -96,7 +96,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
bool signaled = waitEvent.WaitOne(timeout);
if (!signaled && info != null)
if (!signaled)
{
Logger.Error?.Print(LogClass.Gpu, $"Wait on syncpoint {id} for threshold {threshold} took more than {timeout.TotalMilliseconds}ms, resuming execution...");

View File

@@ -11475,126 +11475,126 @@
{
"ID": "DialogConfirmationTitle",
"Translations": {
"ar_SA": "ريوجينكس - تأكيد",
"de_DE": "Ryujinx - Bestätigung",
"el_GR": "Ryujinx - Επιβεβαίωση",
"en_US": "Ryujinx - Confirmation",
"es_ES": "Ryujinx - Confirmación",
"ar_SA": "{0} - تأكيد",
"de_DE": "{0} - Bestätigung",
"el_GR": "{0} - Επιβεβαίωση",
"en_US": "{0} - Confirmation",
"es_ES": "{0} - Confirmación",
"fr_FR": "",
"he_IL": "ריוג'ינקס - אישור",
"it_IT": "Ryujinx - Conferma",
"ja_JP": "Ryujinx - 確認",
"ko_KR": "Ryujinx - 확인",
"no_NO": "Ryujinx - Bekreftelse",
"pl_PL": "Ryujinx - Potwierdzenie",
"pt_BR": "Ryujinx - Confirmação",
"ru_RU": "Ryujinx - Подтверждение",
"sv_SE": "Ryujinx - Bekräftelse",
"th_TH": "Ryujinx - ยืนยัน",
"tr_TR": "Ryujinx - Onay",
"uk_UA": "Ryujinx - Підтвердження",
"zh_CN": "Ryujinx - 确认",
"zh_TW": "Ryujinx - 確認"
"he_IL": "{0} - אישור",
"it_IT": "{0} - Conferma",
"ja_JP": "{0} - 確認",
"ko_KR": "{0} - 확인",
"no_NO": "{0} - Bekreftelse",
"pl_PL": "{0} - Potwierdzenie",
"pt_BR": "{0} - Confirmação",
"ru_RU": "{0} - Подтверждение",
"sv_SE": "{0} - Bekräftelse",
"th_TH": "{0} - ยืนยัน",
"tr_TR": "{0} - Onay",
"uk_UA": "{0} - Підтвердження",
"zh_CN": "{0} - 确认",
"zh_TW": "{0} - 確認"
}
},
{
"ID": "DialogUpdaterTitle",
"Translations": {
"ar_SA": "ريوجينكس - المحدث",
"ar_SA": "{0} - المحدث",
"de_DE": "",
"el_GR": "Ryujinx - Ενημερωτής",
"en_US": "Ryujinx - Updater",
"es_ES": "Ryujinx - Actualizador",
"fr_FR": "Ryujinx - Mise à Jour",
"he_IL": "ריוג'ינקס - מעדכן",
"it_IT": "Ryujinx - Aggiornamento",
"ja_JP": "Ryujinx - アップデータ",
"ko_KR": "Ryujinx - 업데이터",
"no_NO": "Ryujinx Oppdaterer",
"pl_PL": "Ryujinx - Asystent aktualizacji",
"pt_BR": "Ryujinx - Atualizador",
"ru_RU": "Ryujinx - Обновление",
"sv_SE": "Ryujinx - Uppdatering",
"th_TH": "Ryujinx - อัพเดต",
"tr_TR": "Ryujinx - Güncelleyici",
"uk_UA": "Ryujinx - Програма оновлення",
"zh_CN": "Ryujinx - 更新",
"zh_TW": "Ryujinx - 更新程式"
"el_GR": "{0} - Ενημερωτής",
"en_US": "{0} - Updater",
"es_ES": "{0} - Actualizador",
"fr_FR": "{0} - Mise à Jour",
"he_IL": "{0} - מעדכן",
"it_IT": "{0} - Aggiornamento",
"ja_JP": "{0} - アップデータ",
"ko_KR": "{0} - 업데이터",
"no_NO": "{0} Oppdaterer",
"pl_PL": "{0} - Asystent aktualizacji",
"pt_BR": "{0} - Atualizador",
"ru_RU": "{0} - Обновление",
"sv_SE": "{0} - Uppdatering",
"th_TH": "{0} - อัพเดต",
"tr_TR": "{0} - Güncelleyici",
"uk_UA": "{0} - Програма оновлення",
"zh_CN": "{0} - 更新",
"zh_TW": "{0} - 更新程式"
}
},
{
"ID": "DialogErrorTitle",
"Translations": {
"ar_SA": "ريوجينكس - خطأ",
"de_DE": "Ryujinx - Fehler",
"el_GR": "Ryujinx - Σφάλμα",
"en_US": "Ryujinx - Error",
"ar_SA": "{0} - خطأ",
"de_DE": "{0} - Fehler",
"el_GR": "{0} - Σφάλμα",
"en_US": "{0} - Error",
"es_ES": "",
"fr_FR": "Ryujinx - Erreur",
"he_IL": "ריוג'ינקס - שגיאה",
"it_IT": "Ryujinx - Errore",
"ja_JP": "Ryujinx - エラー",
"ko_KR": "Ryujinx - 오류",
"no_NO": "Ryujinx - Feil",
"pl_PL": "Ryujinx - Błąd",
"pt_BR": "Ryujinx - Erro",
"ru_RU": "Ryujinx - Ошибка",
"sv_SE": "Ryujinx - Fel",
"th_TH": "Ryujinx - ผิดพลาด",
"tr_TR": "Ryujinx - Hata",
"uk_UA": "Ryujinx - Помилка",
"zh_CN": "Ryujinx - 错误",
"zh_TW": "Ryujinx - 錯誤"
"fr_FR": "{0} - Erreur",
"he_IL": "{0} - שגיאה",
"it_IT": "{0} - Errore",
"ja_JP": "{0} - エラー",
"ko_KR": "{0} - 오류",
"no_NO": "{0} - Feil",
"pl_PL": "{0} - Błąd",
"pt_BR": "{0} - Erro",
"ru_RU": "{0} - Ошибка",
"sv_SE": "{0} - Fel",
"th_TH": "{0} - ผิดพลาด",
"tr_TR": "{0} - Hata",
"uk_UA": "{0} - Помилка",
"zh_CN": "{0} - 错误",
"zh_TW": "{0} - 錯誤"
}
},
{
"ID": "DialogWarningTitle",
"Translations": {
"ar_SA": "ريوجينكس - تحذير",
"de_DE": "Ryujinx - Warnung",
"el_GR": "Ryujinx - Προειδοποίηση",
"en_US": "Ryujinx - Warning",
"es_ES": "Ryujinx - Advertencia",
"fr_FR": "Ryujinx - Avertissement",
"he_IL": "ריוג'ינקס - אזהרה",
"it_IT": "Ryujinx - Avviso",
"ja_JP": "Ryujinx - 警告",
"ko_KR": "Ryujinx - 경고",
"no_NO": "Ryujinx - Advarsel",
"pl_PL": "Ryujinx - Ostrzeżenie",
"pt_BR": "Ryujinx - Alerta",
"ru_RU": "Ryujinx - Предупреждение",
"sv_SE": "Ryujinx - Varning",
"th_TH": "Ryujinx - คำเตือน",
"tr_TR": "Ryujinx - Uyarı",
"uk_UA": "Ryujinx - Попередження",
"zh_CN": "Ryujinx - 警告",
"zh_TW": "Ryujinx - 警告"
"ar_SA": "{0} - تحذير",
"de_DE": "{0} - Warnung",
"el_GR": "{0} - Προειδοποίηση",
"en_US": "{0} - Warning",
"es_ES": "{0} - Advertencia",
"fr_FR": "{0} - Avertissement",
"he_IL": "{0} - אזהרה",
"it_IT": "{0} - Avviso",
"ja_JP": "{0} - 警告",
"ko_KR": "{0} - 경고",
"no_NO": "{0} - Advarsel",
"pl_PL": "{0} - Ostrzeżenie",
"pt_BR": "{0} - Alerta",
"ru_RU": "{0} - Предупреждение",
"sv_SE": "{0} - Varning",
"th_TH": "{0} - คำเตือน",
"tr_TR": "{0} - Uyarı",
"uk_UA": "{0} - Попередження",
"zh_CN": "{0} - 警告",
"zh_TW": "{0} - 警告"
}
},
{
"ID": "DialogExitTitle",
"Translations": {
"ar_SA": "ريوجينكس - الخروج",
"de_DE": "Ryujinx - Beenden",
"el_GR": "Ryujinx - Έξοδος",
"en_US": "Ryujinx - Exit",
"es_ES": "Ryujinx - Salir",
"fr_FR": "Ryujinx - Quitter",
"he_IL": "ריוג'ינקס - יציאה",
"it_IT": "Ryujinx - Esci",
"ja_JP": "Ryujinx - 終了",
"ko_KR": "Ryujinx - 종료",
"no_NO": "Ryujinx - Avslutt",
"pl_PL": "Ryujinx - Wyjdź",
"pt_BR": "Ryujinx - Sair",
"ru_RU": "Ryujinx - Выход",
"sv_SE": "Ryujinx - Avslut",
"th_TH": "Ryujinx - ออก",
"tr_TR": "Ryujinx - Çıkış",
"uk_UA": "Ryujinx - Вихід",
"zh_CN": "Ryujinx - 退出",
"zh_TW": "Ryujinx - 結束"
"ar_SA": "{0} - الخروج",
"de_DE": "{0} - Beenden",
"el_GR": "{0} - Έξοδος",
"en_US": "{0} - Exit",
"es_ES": "{0} - Salir",
"fr_FR": "{0} - Quitter",
"he_IL": "{0} - יציאה",
"it_IT": "{0} - Esci",
"ja_JP": "{0} - 終了",
"ko_KR": "{0} - 종료",
"no_NO": "{0} - Avslutt",
"pl_PL": "{0} - Wyjdź",
"pt_BR": "{0} - Sair",
"ru_RU": "{0} - Выход",
"sv_SE": "{0} - Avslut",
"th_TH": "{0} - ออก",
"tr_TR": "{0} - Çıkış",
"uk_UA": "{0} - Вихід",
"zh_CN": "{0} - 退出",
"zh_TW": "{0} - 結束"
}
},
{
@@ -17025,26 +17025,26 @@
{
"ID": "DialogStopEmulationTitle",
"Translations": {
"ar_SA": "ريوجينكس - إيقاف المحاكاة",
"de_DE": "Ryujinx - Beende Emulation",
"el_GR": "Ryujinx - Διακοπή εξομοίωσης",
"en_US": "Ryujinx - Stop Emulation",
"es_ES": "Ryujinx - Detener emulación",
"fr_FR": "Ryujinx - Arrêt de l'émulation",
"he_IL": "ריוג'ינקס - עצור אמולציה",
"it_IT": "Ryujinx - Ferma emulazione",
"ja_JP": "Ryujinx - エミュレーションを中止",
"ko_KR": "Ryujinx - 에뮬레이션 중지",
"no_NO": "Ryujinx - Stopp emulasjon",
"pl_PL": "Ryujinx - Zatrzymaj Emulację",
"pt_BR": "Ryujinx - Parar emulação",
"ru_RU": "Ryujinx - Остановка эмуляции",
"sv_SE": "Ryujinx - Stoppa emulering",
"th_TH": "Ryujinx - หยุดการจำลอง",
"tr_TR": "Ryujinx - Emülasyonu Durdur",
"uk_UA": "Ryujinx - Зупинити емуляцію",
"zh_CN": "Ryujinx - 停止模拟",
"zh_TW": "Ryujinx - 停止模擬"
"ar_SA": "{0} - إيقاف المحاكاة",
"de_DE": "{0} - Beende Emulation",
"el_GR": "{0} - Διακοπή εξομοίωσης",
"en_US": "{0} - Stop Emulation",
"es_ES": "{0} - Detener emulación",
"fr_FR": "{0} - Arrêt de l'émulation",
"he_IL": "{0} - עצור אמולציה",
"it_IT": "{0} - Ferma emulazione",
"ja_JP": "{0} - エミュレーションを中止",
"ko_KR": "{0} - 에뮬레이션 중지",
"no_NO": "{0} - Stopp emulasjon",
"pl_PL": "{0} - Zatrzymaj Emulację",
"pt_BR": "{0} - Parar emulação",
"ru_RU": "{0} - Остановка эмуляции",
"sv_SE": "{0} - Stoppa emulering",
"th_TH": "{0} - หยุดการจำลอง",
"tr_TR": "{0} - Emülasyonu Durdur",
"uk_UA": "{0} - Зупинити емуляцію",
"zh_CN": "{0} - 停止模拟",
"zh_TW": "{0} - 停止模擬"
}
},
{
@@ -17950,51 +17950,51 @@
{
"ID": "RyujinxInfo",
"Translations": {
"ar_SA": "ريوجينكس - معلومات",
"ar_SA": "{0} - معلومات",
"de_DE": "",
"el_GR": "Ryujinx - Πληροφορίες",
"en_US": "Ryujinx - Info",
"el_GR": "{0} - Πληροφορίες",
"en_US": "{0} - Info",
"es_ES": "",
"fr_FR": "",
"he_IL": "ריוג'ינקס - מידע",
"it_IT": "Ryujinx - Informazioni",
"ja_JP": "Ryujinx - 情報",
"ko_KR": "Ryujinx - 정보",
"no_NO": "Ryujinx - Informasjon",
"he_IL": "{0} - מידע",
"it_IT": "{0} - Informazioni",
"ja_JP": "{0} - 情報",
"ko_KR": "{0} - 정보",
"no_NO": "{0} - Informasjon",
"pl_PL": "",
"pt_BR": "Ryujinx - Informação",
"ru_RU": "Ryujinx - Информация",
"pt_BR": "{0} - Informação",
"ru_RU": "{0} - Информация",
"sv_SE": "",
"th_TH": "Ryujinx ข้อมูล",
"tr_TR": "Ryujinx - Bilgi",
"uk_UA": "Ryujin x - Інформація",
"zh_CN": "Ryujinx - 信息",
"zh_TW": "Ryujinx - 資訊"
"th_TH": "{0} ข้อมูล",
"tr_TR": "{0} - Bilgi",
"uk_UA": "{0} - Інформація",
"zh_CN": "{0} - 信息",
"zh_TW": "{0} - 資訊"
}
},
{
"ID": "RyujinxConfirm",
"Translations": {
"ar_SA": "ريوجينكس - تأكيد",
"de_DE": "Ryujinx - Bestätigung",
"el_GR": "Ryujinx - Επιβεβαίωση",
"en_US": "Ryujinx - Confirmation",
"es_ES": "Ryujinx - Confirmación",
"ar_SA": "{0} - تأكيد",
"de_DE": "{0} - Bestätigung",
"el_GR": "{0} - Επιβεβαίωση",
"en_US": "{0} - Confirmation",
"es_ES": "{0} - Confirmación",
"fr_FR": "",
"he_IL": "ריוג'ינקס - אישור",
"it_IT": "Ryujinx - Conferma",
"ja_JP": "Ryujinx - 確認",
"ko_KR": "Ryujinx - 확인",
"no_NO": "Ryujinx - Bekreftelse",
"pl_PL": "Ryujinx - Potwierdzenie",
"pt_BR": "Ryujinx - Confirmação",
"ru_RU": "Ryujinx - Подтверждение",
"sv_SE": "Ryujinx - Bekräfta",
"th_TH": "Ryujinx - ยืนยัน",
"tr_TR": "Ryujinx - Doğrulama",
"uk_UA": "Ryujinx - Підтвердження",
"zh_CN": "Ryujinx - 确认",
"zh_TW": "Ryujinx - 確認"
"he_IL": "{0} - אישור",
"it_IT": "{0} - Conferma",
"ja_JP": "{0} - 確認",
"ko_KR": "{0} - 확인",
"no_NO": "{0} - Bekreftelse",
"pl_PL": "{0} - Potwierdzenie",
"pt_BR": "{0} - Confirmação",
"ru_RU": "{0} - Подтверждение",
"sv_SE": "{0} - Bekräfta",
"th_TH": "{0} - ยืนยัน",
"tr_TR": "{0} - Doğrulama",
"uk_UA": "{0} - Підтвердження",
"zh_CN": "{0} - 确认",
"zh_TW": "{0} - 確認"
}
},
{
@@ -18800,26 +18800,26 @@
{
"ID": "RyujinxUpdater",
"Translations": {
"ar_SA": "محدث ريوجينكس",
"de_DE": "Ryujinx - Updater",
"el_GR": "Ryujinx Ενημερωτής",
"en_US": "Ryujinx Updater",
"es_ES": "Actualizador de Ryujinx",
"fr_FR": "Mise à jour de Ryujinx",
"he_IL": "מעדכן ריוג'ינקס",
"it_IT": "Aggiornamento di Ryujinx",
"ja_JP": "Ryujinx アップデータ",
"ko_KR": "Ryujinx 업데이터",
"no_NO": "Ryujinx Oppgradering",
"pl_PL": "Aktualizator Ryujinx",
"pt_BR": "Atualizador do Ryujinx",
"ru_RU": "Ryujinx - Обновление",
"sv_SE": "Uppdaterare för Ryujinx",
"th_TH": "ตัวอัปเดต Ryujinx",
"tr_TR": "Ryujinx Güncelleyicisi",
"uk_UA": "Програма оновлення Ryujinx",
"zh_CN": "Ryujinx 更新",
"zh_TW": "Ryujinx 更新程式"
"ar_SA": "محدث {0}",
"de_DE": "",
"el_GR": "{0} Ενημερωτής",
"en_US": "{0} Updater",
"es_ES": "Actualizador de {0}",
"fr_FR": "Mise à jour de {0}",
"he_IL": "מעדכן {0}",
"it_IT": "Aggiornamento di {0}",
"ja_JP": "{0} アップデータ",
"ko_KR": "{0} 업데이터",
"no_NO": "{0} Oppgradering",
"pl_PL": "Aktualizator {0}",
"pt_BR": "Atualizador do {0}",
"ru_RU": "{0} Обновление",
"sv_SE": "Uppdaterare för {0}",
"th_TH": "ตัวอัปเดต {0}",
"tr_TR": "{0} Güncelleyicisi",
"uk_UA": "Програма оновлення {0}",
"zh_CN": "{0} 更新",
"zh_TW": "{0} 更新程式"
}
},
{

View File

@@ -337,7 +337,7 @@ namespace Ryujinx.Ava.Common
if (publicDataNca is null)
{
Logger.Error?.Print(LogClass.Application, "Extraction failure. The NCA was not present in the selected file");
Logger.Error?.Print(LogClass.Application, "Extraction failure. The PublicData NCA was not present in the selected file");
Dispatcher.UIThread.InvokeAsync(async () =>
{
@@ -349,10 +349,6 @@ namespace Ryujinx.Ava.Common
return;
}
IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
? IntegrityCheckLevel.ErrorOnInvalid
: IntegrityCheckLevel.None;
int index = Nca.GetSectionIndexFromType(NcaSectionType.Data, publicDataNca.Header.ContentType);
try

View File

@@ -44,6 +44,16 @@ namespace Ryujinx.Ava.Common.Locale
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
}
SetDynamicValues(LocaleKeys.DialogConfirmationTitle, RyujinxApp.FullAppName);
SetDynamicValues(LocaleKeys.DialogUpdaterTitle, RyujinxApp.FullAppName);
SetDynamicValues(LocaleKeys.DialogErrorTitle, RyujinxApp.FullAppName);
SetDynamicValues(LocaleKeys.DialogWarningTitle, RyujinxApp.FullAppName);
SetDynamicValues(LocaleKeys.DialogExitTitle, RyujinxApp.FullAppName);
SetDynamicValues(LocaleKeys.DialogStopEmulationTitle, RyujinxApp.FullAppName);
SetDynamicValues(LocaleKeys.RyujinxInfo, RyujinxApp.FullAppName);
SetDynamicValues(LocaleKeys.RyujinxConfirm, RyujinxApp.FullAppName);
SetDynamicValues(LocaleKeys.RyujinxUpdater, RyujinxApp.FullAppName);
}
public string this[LocaleKeys key]
@@ -88,11 +98,16 @@ namespace Ryujinx.Ava.Common.Locale
public static string FormatDynamicValue(LocaleKeys key, params object[] values)
=> Instance.UpdateAndGetDynamicValue(key, values);
public string UpdateAndGetDynamicValue(LocaleKeys key, params object[] values)
public void SetDynamicValues(LocaleKeys key, params object[] values)
{
_dynamicValues[key] = values;
OnPropertyChanged("Translation");
}
public string UpdateAndGetDynamicValue(LocaleKeys key, params object[] values)
{
SetDynamicValues(key, values);
return this[key];
}

View File

@@ -160,6 +160,28 @@ namespace Ryujinx.Ava
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
string overrideLocalConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.CustomConfigNameOverride);
string overrideAppDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.CustomConfigNameOverride);
// Copies and reloads the configuration file if the game was loaded with arguments
// based on global configuration
if (CommandLineState.CountArguments > 0)
{
if (File.Exists(localConfigurationPath))
{
File.Copy(localConfigurationPath, overrideLocalConfigurationPath, overwrite: true);
}
localConfigurationPath = overrideLocalConfigurationPath;
if (File.Exists(appDataConfigurationPath))
{
File.Copy(appDataConfigurationPath, overrideAppDataConfigurationPath, overwrite: true);
}
appDataConfigurationPath = overrideAppDataConfigurationPath;
}
// Now load the configuration as the other subsystems are now registered
if (File.Exists(localConfigurationPath))
{
@@ -232,8 +254,35 @@ namespace Ryujinx.Ava
_ => ConfigurationState.Instance.HideCursor,
};
// Check if memoryManagerMode was overridden.
if (CommandLineState.OverrideMemoryManagerMode is not null)
if (Enum.TryParse(CommandLineState.OverrideMemoryManagerMode, true, out MemoryManagerMode result))
{
ConfigurationState.Instance.System.MemoryManagerMode.Value = result;
}
// Check if hardware-acceleration was overridden.
// Check if PPTC was overridden.
if (CommandLineState.OverridePPTC is not null)
if (Enum.TryParse(CommandLineState.OverridePPTC, true, out bool result))
{
ConfigurationState.Instance.System.EnablePtc.Value = result;
}
// Check if region was overridden.
if (CommandLineState.OverrideSystemRegion is not null)
if (Enum.TryParse(CommandLineState.OverrideSystemRegion, true, out Ryujinx.HLE.HOS.SystemState.RegionCode result))
{
ConfigurationState.Instance.System.Region.Value = (Utilities.Configuration.System.Region)result;
}
//Check if language was overridden.
if (CommandLineState.OverrideSystemLanguage is not null)
if (Enum.TryParse(CommandLineState.OverrideSystemLanguage, true, out Ryujinx.HLE.HOS.SystemState.SystemLanguage result))
{
ConfigurationState.Instance.System.Language.Value = (Utilities.Configuration.System.Language)result;
}
// Check if hardware-acceleration was overridden. MemoryManagerMode ( outdated! )
if (CommandLineState.OverrideHardwareAcceleration != null)
UseHardwareAcceleration = CommandLineState.OverrideHardwareAcceleration.Value;
}

View File

@@ -22,12 +22,12 @@ namespace Ryujinx.Ava
{
public class RyujinxApp : Application
{
internal static string FormatTitle(LocaleKeys? windowTitleKey = null)
internal static string FormatTitle(LocaleKeys? windowTitleKey = null, bool includeVersion = true)
=> windowTitleKey is null
? $"{FullAppName} {Program.Version}"
: $"{FullAppName} {Program.Version} - {LocaleManager.Instance[windowTitleKey.Value]}";
? $"{FullAppName}{(includeVersion ? $" {Program.Version}" : string.Empty)}"
: $"{FullAppName}{(includeVersion ? $" {Program.Version}" : string.Empty)} - {LocaleManager.Instance[windowTitleKey.Value]}";
public static readonly string FullAppName = ReleaseInformation.IsCanaryBuild ? "Ryujinx Canary" : "Ryujinx";
public static readonly string FullAppName = string.Intern(ReleaseInformation.IsCanaryBuild ? "Ryujinx Canary" : "Ryujinx");
public static MainWindow MainWindow => Current!
.ApplicationLifetime.Cast<IClassicDesktopStyleApplicationLifetime>()

View File

@@ -375,15 +375,11 @@ namespace Ryujinx.Ava.UI.Controls
png.SaveTo(fileStream);
}
public void CreateApplicationShortcut_Click(object sender, RoutedEventArgs args)
public async void CreateApplicationShortcut_Click(object sender, RoutedEventArgs args)
{
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
ShortcutHelper.CreateAppShortcut(
viewModel.SelectedApplication.Path,
viewModel.SelectedApplication.Name,
viewModel.SelectedApplication.IdString,
viewModel.SelectedApplication.Icon
);
await new ArgumentsConfigWindows(viewModel).ShowDialog((Window)viewModel.TopLevel);
}
public async void RunApplication_Click(object sender, RoutedEventArgs args)

View File

@@ -159,6 +159,7 @@ namespace Ryujinx.Ava.UI.Helpers
Symbol = (Symbol)symbol,
Margin = new Thickness(10),
FontSize = 40,
FlowDirection = FlowDirection.LeftToRight,
VerticalAlignment = VerticalAlignment.Center,
};

View File

@@ -1,3 +1,4 @@
using Ryujinx.Common.Helper;
using SharpMetal.QuartzCore;
using System;
@@ -7,14 +8,12 @@ namespace Ryujinx.Ava.UI.Renderer
{
public CAMetalLayer CreateSurface()
{
if (OperatingSystem.IsMacOS())
if (OperatingSystem.IsMacOS() && RunningPlatform.IsArm)
{
return new CAMetalLayer(MetalLayer);
}
else
{
throw new NotSupportedException();
}
throw new NotSupportedException($"Cannot create a {nameof(CAMetalLayer)} without being on ARM Mac.");
}
}
}

View File

@@ -43,19 +43,19 @@ namespace Ryujinx.Ava.UI.Renderer
public RendererHost(string titleId)
{
switch (TitleIDs.SelectGraphicsBackend(titleId, ConfigurationState.Instance.Graphics.GraphicsBackend))
{
case GraphicsBackend.OpenGl:
EmbeddedWindow = new EmbeddedWindowOpenGL();
break;
case GraphicsBackend.Metal:
EmbeddedWindow = new EmbeddedWindowMetal();
break;
case GraphicsBackend.Vulkan:
EmbeddedWindow = new EmbeddedWindowVulkan();
break;
}
Focusable = true;
FlowDirection = FlowDirection.LeftToRight;
EmbeddedWindow =
#pragma warning disable CS8509
TitleIDs.SelectGraphicsBackend(titleId, ConfigurationState.Instance.Graphics.GraphicsBackend) switch
#pragma warning restore CS8509
{
GraphicsBackend.OpenGl => new EmbeddedWindowOpenGL(),
GraphicsBackend.Metal => new EmbeddedWindowMetal(),
GraphicsBackend.Vulkan => new EmbeddedWindowVulkan(),
};
string backendText = EmbeddedWindow switch
{
EmbeddedWindowVulkan => "Vulkan",

View File

@@ -1,8 +1,10 @@
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Media.Imaging;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using Gommon;
using LibHac.Tools.Fs;
using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Audio.Backends.SDL2;
@@ -25,6 +27,7 @@ using Ryujinx.HLE.HOS.Services.Time.TimeZone;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
@@ -62,12 +65,56 @@ namespace Ryujinx.Ava.UI.ViewModels
public event Action CloseWindow;
public event Action SaveSettingsEvent;
public event Action CompareSettingsEvent;
private int _networkInterfaceIndex;
private int _multiplayerModeIndex;
private string _ldnPassphrase;
[ObservableProperty] private string _ldnServer;
public SettingsHacksViewModel DirtyHacks { get; }
public string GamePath { get; }
public string GameName { get; }
private Bitmap _gameIcon;
private string _gameTitle;
private string _gameId;
public Bitmap GameIcon
{
get => _gameIcon;
set
{
if (_gameIcon != value)
{
_gameIcon = value;
}
}
}
public string GameTitle
{
get => _gameTitle;
set
{
if (_gameTitle != value)
{
_gameTitle = value;
}
}
}
public string GameId
{
get => _gameId;
set
{
if (_gameId != value)
{
_gameId = value;
}
}
}
public int ResolutionScale
{
@@ -348,6 +395,30 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager, string gamePath, string gameName, string gameId, byte[] gameIconData) : this()
{
_virtualFileSystem = virtualFileSystem;
_contentManager = contentManager;
if (gameIconData != null && gameIconData.Length > 0)
{
using (var ms = new MemoryStream(gameIconData))
{
GameIcon = new Bitmap(ms);
}
}
GameTitle = gameName;
GameId = gameId;
if (Program.PreviewerDetached)
{
Task.Run(LoadTimeZones);
DirtyHacks = new SettingsHacksViewModel(this);
}
}
public SettingsViewModel()
{
GameDirectories = [];
@@ -728,6 +799,11 @@ namespace Ryujinx.Ava.UI.ViewModels
SaveSettings();
}
public void CreateShortcut()
{
CompareSettingsEvent?.Invoke(); //raises an event to create a shortcut with arguments
}
public void OkButton()
{
SaveSettings();

View File

@@ -0,0 +1,236 @@
<UserControl
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsApplyOverride"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
mc:Ignorable="d"
x:DataType="viewModels:SettingsViewModel">
<Design.DataContext>
<viewModels:SettingsViewModel />
</Design.DataContext>
<ScrollViewer
Name="AllSettings"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<Border Classes="settings">
<StackPanel
Margin="10"
HorizontalAlignment="Stretch"
Orientation="Vertical"
Spacing="10">
<TextBlock Classes="h1" Text="{ext:Locale SettingsTabSystemCore}" />
<StackPanel
Margin="10,0,0,0"
Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="{ext:Locale SettingsTabSystemSystemRegion}" Width="250" />
<ComboBox
SelectedIndex="{Binding Region}"
ToolTip.Tip="{ext:Locale RegionTooltip}"
HorizontalContentAlignment="Left"
Width="350">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemRegionJapan}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemRegionUSA}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemRegionEurope}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemRegionAustralia}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemRegionChina}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemRegionKorea}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemRegionTaiwan}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel
Margin="10,0,0,0"
Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemSystemLanguage}"
ToolTip.Tip="{ext:Locale LanguageTooltip}"
Width="250" />
<ComboBox
SelectedIndex="{Binding Language}"
ToolTip.Tip="{ext:Locale LanguageTooltip}"
HorizontalContentAlignment="Left"
Width="350">
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageJapanese}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageAmericanEnglish}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageFrench}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageGerman}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageItalian}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageSpanish}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageChinese}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageKorean}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageDutch}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguagePortuguese}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageRussian}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageTaiwanese}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageBritishEnglish}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageCanadianFrench}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageLatinAmericanSpanish}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageSimplifiedChinese}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageTraditionalChinese}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageBrazilianPortuguese}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageSwedish}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageNorwegian}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
<Separator Height="1" />
<TextBlock Classes="h1" Text="{ext:Locale SettingsTabCpu}" />
<StackPanel
Margin="10,0,0,0"
HorizontalAlignment="Stretch"
Orientation="Vertical">
<CheckBox IsChecked="{Binding EnablePptc}">
<TextBlock Text="{ext:Locale SettingsTabSystemEnablePptc}"
ToolTip.Tip="{ext:Locale PptcToggleTooltip}" />
</CheckBox>
</StackPanel>
<StackPanel
Margin="10,0,0,0"
HorizontalAlignment="Stretch"
Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemMemoryManagerMode}"
ToolTip.Tip="{ext:Locale MemoryManagerTooltip}"
Width="250" />
<ComboBox SelectedIndex="{Binding MemoryMode}"
ToolTip.Tip="{ext:Locale MemoryManagerTooltip}"
HorizontalContentAlignment="Left"
Width="350">
<ComboBoxItem
ToolTip.Tip="{ext:Locale MemoryManagerSoftwareTooltip}">
<TextBlock
Text="{ext:Locale SettingsTabSystemMemoryManagerModeSoftware}" />
</ComboBoxItem>
<ComboBoxItem
ToolTip.Tip="{ext:Locale MemoryManagerHostTooltip}">
<TextBlock Text="{ext:Locale SettingsTabSystemMemoryManagerModeHost}" />
</ComboBoxItem>
<ComboBoxItem
ToolTip.Tip="{ext:Locale MemoryManagerUnsafeTooltip}">
<TextBlock
Text="{ext:Locale SettingsTabSystemMemoryManagerModeHostUnchecked}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
<CheckBox IsChecked="{Binding UseHypervisor}"
IsVisible="{Binding IsAppleSiliconMac}"
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}">
<TextBlock Text="{ext:Locale SettingsTabSystemUseHypervisor}"
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}" />
</CheckBox>
</StackPanel>
<Separator Height="1" />
<TextBlock Classes="h1" Text="{ext:Locale SettingsTabGraphics}" />
<StackPanel Margin="10,0,0,0" Orientation="Vertical" Spacing="10">
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
ToolTip.Tip="{ext:Locale SettingsTabGraphicsBackendTooltip}"
Text="{ext:Locale SettingsTabGraphicsBackend}"
Width="250" />
<ComboBox
Name="GraphicsBackendSelector"
Width="350"
HorizontalContentAlignment="Left"
ToolTip.Tip="{ext:Locale SettingsTabGraphicsBackendTooltip}"
SelectedIndex="{Binding GraphicsBackendIndex}">
<ComboBoxItem IsVisible="{Binding IsVulkanAvailable}" ToolTip.Tip="{ext:Locale SettingsTabGraphicsBackendAutoTooltip}" >
<TextBlock Text="{ext:Locale SettingsTabGraphicsBackendAuto}" />
</ComboBoxItem>
<ComboBoxItem IsVisible="{Binding IsVulkanAvailable}">
<TextBlock Text="Vulkan" />
</ComboBoxItem>
<ComboBoxItem IsEnabled="{Binding IsOpenGLAvailable}">
<TextBlock Text="OpenGL" />
</ComboBoxItem>
<ComboBoxItem IsEnabled="{Binding IsAppleSiliconMac}">
<TextBlock Text="Metal (ARM Mac only, Experimental)" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
ToolTip.Tip="{ext:Locale GraphicsBackendThreadingTooltip}"
Text="{ext:Locale SettingsTabGraphicsBackendMultithreading}"
Width="250" />
<ComboBox Width="350"
HorizontalContentAlignment="Left"
ToolTip.Tip="{ext:Locale GalThreadingTooltip}"
SelectedIndex="{Binding GraphicsBackendMultithreadingIndex}">
<ComboBoxItem>
<TextBlock Text="{ext:Locale CommonAuto}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale CommonOff}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{ext:Locale CommonOn}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
</StackPanel>
</StackPanel>
</Border>
</ScrollViewer>
</UserControl>

View File

@@ -0,0 +1,12 @@
using Avalonia.Controls;
namespace Ryujinx.Ava.UI.Views.Settings
{
public partial class SettingsApplyOverride : UserControl
{
public SettingsApplyOverride()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,104 @@
<window:StyleableAppWindow
x:Class="Ryujinx.Ava.UI.Windows.ArgumentsConfigWindows"
xmlns="https://github.com/avaloniaui"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:window="clr-namespace:Ryujinx.Ava.UI.Windows"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
xmlns:settings="clr-namespace:Ryujinx.Ava.UI.Views.Settings"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
Width="1100"
Height="768"
MinWidth="800"
MinHeight="480"
WindowStartupLocation="CenterOwner"
x:DataType="viewModels:SettingsViewModel"
mc:Ignorable="d"
Focusable="True">
<Design.DataContext>
<viewModels:SettingsViewModel />
</Design.DataContext>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinWidth="600" RowDefinitions="Auto,*,Auto">
<ContentPresenter
x:Name="ContentPresenter"
Grid.Row="1"
IsVisible="False"
KeyboardNavigation.IsTabStop="False"/>
<Grid Name="Pages" IsVisible="False" Grid.Row="2">
<settings:SettingsApplyOverride Name="AllSettings" />
</Grid>
<ui:NavigationView
Grid.Row="1"
IsSettingsVisible="False"
Name="NavPanel"
IsBackEnabled="False"
PaneDisplayMode="Left"
Margin="2,10,10,0"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
OpenPaneLength="200"
IsPaneToggleButtonVisible="False">
<!-- For image -->
<ui:NavigationView.PaneHeader>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="5"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding GameId}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0,0,0,10"
TextAlignment="Center" Grid.Row="0" />
<Image Source="{Binding GameIcon}"
Width="160"
Height="160"
Grid.Row="1"
Margin="0,0,0,10"
HorizontalAlignment="Center" />
<TextBlock Text="{Binding GameTitle}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0,0,0,10"
TextAlignment="Center" Grid.Row="2" />
<Separator Height="1" Grid.Row="3" Margin="0,0,0,10" HorizontalAlignment="Stretch"/>
</Grid>
</ui:NavigationView.PaneHeader>
<ui:NavigationView.MenuItems>
<ui:NavigationViewItem
Margin="2,10,10,0"
Content="{ext:Locale Settings}"
Tag="AllSettings">
<ui:NavigationViewItem.IconSource>
<ui:FontIconSource
FontFamily="avares://Ryujinx/Assets/Fonts#Segoe Fluent Icons"
Glyph="{helpers:GlyphValueConverter Chip}" />
</ui:NavigationViewItem.IconSource>
</ui:NavigationViewItem>
</ui:NavigationView.MenuItems>
</ui:NavigationView>
<ReversibleStackPanel
Grid.Row="2"
Margin="10"
Spacing="10"
Orientation="Horizontal"
HorizontalAlignment="Right"
ReverseOrder="{Binding IsMacOS}">
<Button
Content="{ext:Locale GameListContextMenuCreateShortcut}"
Command="{Binding CreateShortcut}" />
<Button
HotKey="Escape"
Content="{ext:Locale ControllerSettingsClose}"
Command="{Binding CancelButton}" />
</ReversibleStackPanel>
</Grid>
</window:StyleableAppWindow>

View File

@@ -0,0 +1,162 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Media.Imaging;
using FluentAvalonia.Core;
using FluentAvalonia.UI.Controls;
using Projektanker.Icons.Avalonia;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.ViewModels.Input;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common.Configuration;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.Input;
using System;
using System.IO;
using System.Linq;
using Key = Avalonia.Input.Key;
namespace Ryujinx.Ava.UI.Windows
{
public partial class ArgumentsConfigWindows : StyleableAppWindow
{
internal readonly SettingsViewModel ViewModel;
public string GamePath { get; }
public string GameName { get; }
public string GameId { get; }
public byte[] GameIconData { get; }
public static int OverrideBackendThreading { get; private set; }
public static int OverrideGraphicsBackend { get; private set; }
public static int OverrideSystemLanguage { get; private set; }
public static int OverrideSystemRegion { get; private set; }
public static bool OverridePPTC { get; private set; }
public static int OverrideMemoryManagerMode { get; private set; }
public ArgumentsConfigWindows(MainWindowViewModel viewModel)
{
Title = RyujinxApp.FormatTitle(LocaleKeys.Settings);
DataContext = ViewModel = new SettingsViewModel(
viewModel.VirtualFileSystem,
viewModel.ContentManager,
viewModel.SelectedApplication.Path,
viewModel.SelectedApplication.Name,
viewModel.SelectedApplication.IdString,
viewModel.SelectedApplication.Icon);
GamePath = viewModel.SelectedApplication.Path;
GameName = viewModel.SelectedApplication.Name;
GameId = viewModel.SelectedApplication.IdString;
GameIconData = viewModel.SelectedApplication.Icon;
OverrideBackendThreading = ViewModel.GraphicsBackendMultithreadingIndex;
OverrideGraphicsBackend = ViewModel.GraphicsBackendIndex;
OverrideSystemLanguage = ViewModel.Language;
OverrideSystemRegion = ViewModel.Region;
OverridePPTC = ViewModel.EnablePptc;
OverrideMemoryManagerMode = ViewModel.MemoryMode;
ViewModel.CloseWindow += Close;
ViewModel.CompareSettingsEvent += CompareConfiguration;
InitializeComponent();
Load();
#if DEBUG
this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt));
#endif
}
public void CompareConfiguration()
{
ShortcutHelper.CreateAppShortcut(
GamePath,
GameName,
GameId,
GameIconData,
GetArguments()
);
}
private string GetArguments()
{
string line = "";
if (OverrideBackendThreading != ViewModel.GraphicsBackendMultithreadingIndex)
{
string _result = Enum.GetName(typeof(BackendThreading), ViewModel.GraphicsBackendMultithreadingIndex);
line += " --backend-threading " + _result;
}
if (OverrideGraphicsBackend != ViewModel.GraphicsBackendIndex)
{
string _result = Enum.GetName(typeof(GraphicsBackend), ViewModel.GraphicsBackendIndex);
line += " -g " + _result;
}
if (OverridePPTC != ViewModel.EnablePptc)
{
string _result = ViewModel.EnablePptc.ToString();
line += " --pptc " + _result;
}
if (OverrideMemoryManagerMode != ViewModel.MemoryMode)
{
string _result = Enum.GetName(typeof(MemoryManagerMode), ViewModel.MemoryMode);
line += " -m " + _result;
}
if (OverrideSystemRegion != ViewModel.Region)
{
string _result = Enum.GetName(typeof(RegionCode), ViewModel.Region);
line += " --system-region " + _result;
}
if (OverrideSystemLanguage != ViewModel.Language)
{
string _result = Enum.GetName(typeof(SystemLanguage), ViewModel.Language);
line += " --system-language " + _result;
}
return line;
}
private void Load()
{
Pages.Children.Clear();
NavPanel.SelectionChanged += NavPanelOnSelectionChanged;
NavPanel.SelectedItem = NavPanel.MenuItems.ElementAt(0);
}
private void NavPanelOnSelectionChanged(object sender, NavigationViewSelectionChangedEventArgs e)
{
if (e.SelectedItem is NavigationViewItem navItem && navItem.Tag is not null)
{
switch (navItem.Tag.ToString())
{
case nameof(AllSettings):
NavPanel.Content = AllSettings;
break;
default:
throw new NotImplementedException();
}
}
}
protected override void OnClosing(WindowClosingEventArgs e)
{
base.OnClosing(e);
}
}
}

View File

@@ -302,7 +302,7 @@ namespace Ryujinx.Ava.UI.Windows
LinuxHelper.RecommendedVmMaxMapCount);
UserResult response = await ContentDialogHelper.ShowTextDialog(
$"Ryujinx - {LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTitle]}",
RyujinxApp.FormatTitle(LocaleKeys.LinuxVmMaxMapCountDialogTitle, false),
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTextPrimary],
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTextSecondary],
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogButtonUntilRestart],

View File

@@ -6,11 +6,15 @@ namespace Ryujinx.Ava.Utilities
public static class CommandLineState
{
public static string[] Arguments { get; private set; }
public static int CountArguments { get; private set; }
public static bool? OverrideDockedMode { get; private set; }
public static bool? OverrideHardwareAcceleration { get; private set; }
public static string OverrideGraphicsBackend { get; private set; }
public static string OverrideBackendThreading { get; private set; }
public static string OverridePPTC { get; private set; }
public static string OverrideMemoryManagerMode { get; private set; }
public static string OverrideSystemRegion { get; private set; }
public static string OverrideSystemLanguage { get; private set; }
public static string OverrideHideCursor { get; private set; }
public static string BaseDirPathArg { get; private set; }
public static string Profile { get; private set; }
@@ -28,6 +32,11 @@ namespace Ryujinx.Ava.Utilities
{
string arg = args[i];
if (arg.Contains("-") || arg.Contains("--"))
{
CountArguments++;
}
switch (arg)
{
case "-r":
@@ -85,6 +94,47 @@ namespace Ryujinx.Ava.Utilities
OverrideBackendThreading = args[++i];
break;
case "--pptc":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
OverridePPTC = args[++i];
break;
case "-m":
case "--memory-manager-mode":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
OverrideMemoryManagerMode = args[++i];
break;
case "--system-region":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
OverrideSystemRegion = args[++i];
break;
case "--system-language":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
OverrideSystemLanguage = args[++i];
break;
case "-i":
case "--application-id":
LaunchApplicationId = args[++i];

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Ava.Utilities
public static class ShortcutHelper
{
[SupportedOSPlatform("windows")]
private static void CreateShortcutWindows(string applicationFilePath, string applicationId, byte[] iconData, string iconPath, string cleanedAppName, string desktopPath)
private static void CreateShortcutWindows(string applicationFilePath, string applicationId, byte[] iconData, string iconPath, string cleanedAppName, string desktopPath, string args = "")
{
string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.FriendlyName + ".exe");
iconPath += ".ico";
@@ -22,13 +22,13 @@ namespace Ryujinx.Ava.Utilities
image.Resize(new SKImageInfo(128, 128), SKFilterQuality.High);
SaveBitmapAsIcon(image, iconPath);
Shortcut shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath, applicationId), iconPath, 0);
Shortcut shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath, applicationId, args), iconPath, 0);
shortcut.StringData.NameString = cleanedAppName;
shortcut.WriteToFile(Path.Combine(desktopPath, cleanedAppName + ".lnk"));
}
[SupportedOSPlatform("linux")]
private static void CreateShortcutLinux(string applicationFilePath, string applicationId, byte[] iconData, string iconPath, string desktopPath, string cleanedAppName)
private static void CreateShortcutLinux(string applicationFilePath, string applicationId, byte[] iconData, string iconPath, string desktopPath, string cleanedAppName, string args = "")
{
string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.sh");
string desktopFile = EmbeddedResources.ReadAllText("Ryujinx/Assets/ShortcutFiles/shortcut-template.desktop");
@@ -40,11 +40,11 @@ namespace Ryujinx.Ava.Utilities
data.SaveTo(file);
using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
outputFile.Write(desktopFile, cleanedAppName, iconPath, $"{basePath} {GetArgsString(applicationFilePath, applicationId)}");
outputFile.Write(desktopFile, cleanedAppName, iconPath, $"{basePath} {GetArgsString(applicationFilePath, applicationId, args)}");
}
[SupportedOSPlatform("macos")]
private static void CreateShortcutMacos(string appFilePath, string applicationId, byte[] iconData, string desktopPath, string cleanedAppName)
private static void CreateShortcutMacos(string appFilePath, string applicationId, byte[] iconData, string desktopPath, string cleanedAppName, string args = "")
{
string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx");
string plistFile = EmbeddedResources.ReadAllText("Ryujinx/Assets/ShortcutFiles/shortcut-template.plist");
@@ -63,7 +63,7 @@ namespace Ryujinx.Ava.Utilities
string scriptPath = Path.Combine(scriptFolderPath, ScriptName);
using StreamWriter scriptFile = new(scriptPath);
scriptFile.Write(shortcutScript, basePath, GetArgsString(appFilePath, applicationId));
scriptFile.Write(shortcutScript, basePath, GetArgsString(appFilePath, applicationId, args));
// Set execute permission
FileInfo fileInfo = new(scriptPath);
@@ -87,7 +87,7 @@ namespace Ryujinx.Ava.Utilities
outputFile.Write(plistFile, ScriptName, cleanedAppName, IconName);
}
public static void CreateAppShortcut(string applicationFilePath, string applicationName, string applicationId, byte[] iconData)
public static void CreateAppShortcut(string applicationFilePath, string applicationName, string applicationId, byte[] iconData, string args = "")
{
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
string cleanedAppName = string.Join("_", applicationName.Split(Path.GetInvalidFileNameChars()));
@@ -96,7 +96,7 @@ namespace Ryujinx.Ava.Utilities
{
string iconPath = Path.Combine(AppDataManager.BaseDirPath, "games", applicationId, "app");
CreateShortcutWindows(applicationFilePath, applicationId, iconData, iconPath, cleanedAppName, desktopPath);
CreateShortcutWindows(applicationFilePath, applicationId, iconData, iconPath, cleanedAppName, desktopPath, args);
return;
}
@@ -106,14 +106,14 @@ namespace Ryujinx.Ava.Utilities
string iconPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "icons", "Ryujinx");
Directory.CreateDirectory(iconPath);
CreateShortcutLinux(applicationFilePath, applicationId, iconData, Path.Combine(iconPath, applicationId), desktopPath, cleanedAppName);
CreateShortcutLinux(applicationFilePath, applicationId, iconData, Path.Combine(iconPath, applicationId), desktopPath, cleanedAppName, args);
return;
}
if (OperatingSystem.IsMacOS())
{
CreateShortcutMacos(applicationFilePath, applicationId, iconData, desktopPath, cleanedAppName);
CreateShortcutMacos(applicationFilePath, applicationId, iconData, desktopPath, cleanedAppName, args);
return;
}
@@ -121,7 +121,7 @@ namespace Ryujinx.Ava.Utilities
throw new NotImplementedException("Shortcut support has not been implemented yet for this OS.");
}
private static string GetArgsString(string appFilePath, string applicationId)
private static string GetArgsString(string appFilePath, string applicationId, string config = "")
{
// args are first defined as a list, for easier adjustments in the future
List<string> argsList = [];
@@ -132,6 +132,11 @@ namespace Ryujinx.Ava.Utilities
argsList.Add($"\"{CommandLineState.BaseDirPathArg}\"");
}
if (!string.IsNullOrEmpty(config))
{
argsList.Add(config);
}
if (appFilePath.ToLower().EndsWith(".xci"))
{
argsList.Add("--application-id");