Compare commits
51 Commits
Canary-1.2
...
139e86915b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
139e86915b | ||
|
|
91f73a4891 | ||
|
|
883d4d863a | ||
|
|
ca5de909a1 | ||
|
|
ca8329d3da | ||
|
|
4f02b6a6de | ||
|
|
1dedf4c8d5 | ||
|
|
3f185f580c | ||
|
|
2dd787fb7b | ||
|
|
42bd99193f | ||
|
|
22299e69c6 | ||
|
|
acc06a8430 | ||
|
|
5d061a1871 | ||
|
|
c21e63eb02 | ||
|
|
32f9b3357a | ||
|
|
7f7055a037 | ||
|
|
af13f4bb3b | ||
|
|
03692e6072 | ||
|
|
6f4930d547 | ||
|
|
1ca5407c22 | ||
|
|
8efceb3c28 | ||
|
|
0399af0ff9 | ||
|
|
3e40532dee | ||
|
|
1d68546aa0 | ||
|
|
966860a464 | ||
|
|
b9982c02e3 | ||
|
|
a301a14074 | ||
|
|
7568dd4d7a | ||
|
|
4bbcec2076 | ||
|
|
57ac90a55b | ||
|
|
cdc4557d82 | ||
|
|
ae16360685 | ||
|
|
45b1794a45 | ||
|
|
39fbbb39e0 | ||
|
|
11a68a204f | ||
|
|
e4e38c4bdd | ||
|
|
5f5c76107c | ||
|
|
a92475b8fd | ||
|
|
4d5ae23b0b | ||
|
|
4cb2170ad1 | ||
|
|
fc01f7b58f | ||
|
|
fa463c51f8 | ||
|
|
3a8e6e3117 | ||
|
|
7f4a161ca5 | ||
|
|
df1c7613e8 | ||
|
|
6d37d79cc7 | ||
|
|
afdfcc1720 | ||
|
|
fe94224d01 | ||
|
|
fbe1a7d966 | ||
|
|
5dc7fb4495 | ||
|
|
2640f083b6 |
@@ -582,6 +582,13 @@ namespace Ryujinx.Ava
|
||||
Rainbow.Disable();
|
||||
Rainbow.Reset();
|
||||
|
||||
// Reload settings when the game is turned off
|
||||
// (resets custom settings if there were any)
|
||||
Program.ReloadConfig();
|
||||
|
||||
//Updates the gameList (changes the status of the user setting if it was added or removed during the game)
|
||||
RyujinxApp.MainWindow.GameListUpdate();
|
||||
|
||||
_isStopped = true;
|
||||
Stop();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<Styles
|
||||
<Styles
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||
xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia">
|
||||
<Design.PreviewWith>
|
||||
<Border Height="2000"
|
||||
@@ -30,7 +31,8 @@
|
||||
<Button
|
||||
Name="btnRem"
|
||||
HorizontalAlignment="Right"
|
||||
Content="Add" />
|
||||
Content="Add"
|
||||
Classes="red"/>
|
||||
<TextBox
|
||||
Width="100"
|
||||
VerticalAlignment="Center"
|
||||
@@ -41,7 +43,11 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<ui:NumberBox Value="1" />
|
||||
<MenuItem
|
||||
Header="123 0000"
|
||||
ToolTip.Tip="What this"/>
|
||||
</StackPanel>
|
||||
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
<Style Selector="DropDownButton">
|
||||
@@ -373,6 +379,16 @@
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource AppListHoverBackgroundColor}" />
|
||||
</Style>
|
||||
<Style Selector="Button.red /template/ ContentPresenter">
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
<Setter Property="Background" Value="red"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Style>
|
||||
<Style Selector="Button.red:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
<Setter Property="Background" Value="{DynamicResource WarningBackgroundColor}" />
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Style>
|
||||
<Styles.Resources>
|
||||
<SolidColorBrush x:Key="ThemeAccentColorBrush"
|
||||
Color="{DynamicResource SystemAccentColor}" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
@@ -12,11 +12,13 @@
|
||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
||||
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
||||
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
||||
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||
<Color x:Key="Switch">#FF2EEAC9</Color>
|
||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||
<Color x:Key="Custom">#6483F5</Color>
|
||||
<Color x:Key="Warning">#800080</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||
@@ -29,11 +31,13 @@
|
||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
||||
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
||||
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
||||
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||
<Color x:Key="Switch">#13c3a4</Color>
|
||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||
<Color x:Key="Custom">#6483F5</Color>
|
||||
<Color x:Key="Warning">#800080</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||
@@ -46,11 +50,13 @@
|
||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color>
|
||||
<Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color>
|
||||
<Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color>
|
||||
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
||||
<Color x:Key="SecondaryTextColor">#A0FFFFFF</Color>
|
||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||
<Color x:Key="Switch">#FF2EEAC9</Color>
|
||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||
<Color x:Key="Custom">#6483F5</Color>
|
||||
<Color x:Key="Warning">#FFA500</Color>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
"ID": "MenuBarFileOpenAppletOpenMiiApplet",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Mii-Bearbeitungsapplet",
|
||||
"el_GR": "",
|
||||
"en_US": "Mii Edit Applet",
|
||||
"es_ES": "Applet Editor Mii",
|
||||
@@ -176,7 +176,7 @@
|
||||
"ID": "SettingsTabSystemMemoryManagerModeSoftware",
|
||||
"Translations": {
|
||||
"ar_SA": "البرنامج",
|
||||
"de_DE": "",
|
||||
"de_DE": "Programme",
|
||||
"el_GR": "Λογισμικό",
|
||||
"en_US": "Software",
|
||||
"es_ES": "",
|
||||
@@ -326,7 +326,7 @@
|
||||
"ID": "MenuBarFileOpenFromFileError",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Keine Anwendungen im ausgewählten Datei gefunden.",
|
||||
"el_GR": "",
|
||||
"en_US": "No applications found in selected file.",
|
||||
"es_ES": "No se encontraron aplicaciones en el archivo seleccionado.",
|
||||
@@ -376,7 +376,7 @@
|
||||
"ID": "MenuBarFileLoadDlcFromFolder",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "DLC aus Ordner laden",
|
||||
"el_GR": "",
|
||||
"en_US": "Load DLC From Folder",
|
||||
"es_ES": "Cargar DLC Desde Carpeta",
|
||||
@@ -401,7 +401,7 @@
|
||||
"ID": "MenuBarFileLoadTitleUpdatesFromFolder",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Titel-Updates aus Ordner laden",
|
||||
"el_GR": "",
|
||||
"en_US": "Load Title Updates From Folder",
|
||||
"es_ES": "Cargar Actualizaciones de Títulos Desde Carpeta",
|
||||
@@ -576,7 +576,7 @@
|
||||
"ID": "MenuBarOptionsStartGamesWithoutUI",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Spiele ohne Benutzeroberfläche starten",
|
||||
"el_GR": "",
|
||||
"en_US": "Start Games with UI Hidden",
|
||||
"es_ES": "",
|
||||
@@ -589,7 +589,7 @@
|
||||
"pl_PL": "",
|
||||
"pt_BR": "Iniciar jogos ocultando a interface",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"sv_SE": "Starta spel med dolt användargränssnitt",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
@@ -751,7 +751,7 @@
|
||||
"ID": "MenuBarActionsScanAmiiboBin",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Amiibo scannen (aus Bin-Datei)",
|
||||
"el_GR": "",
|
||||
"en_US": "Scan An Amiibo (From Bin)",
|
||||
"es_ES": "",
|
||||
@@ -851,7 +851,7 @@
|
||||
"ID": "MenuBarActionsInstallKeys",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Schlüssel installieren",
|
||||
"el_GR": "",
|
||||
"en_US": "Install Keys",
|
||||
"es_ES": "",
|
||||
@@ -876,7 +876,7 @@
|
||||
"ID": "MenuBarFileActionsInstallKeysFromFile",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Schlüssel aus KEYS oder ZIP installieren",
|
||||
"el_GR": "",
|
||||
"en_US": "Install keys from KEYS or ZIP",
|
||||
"es_ES": "Instalar keys de KEYS o ZIP",
|
||||
@@ -901,7 +901,7 @@
|
||||
"ID": "MenuBarFileActionsInstallKeysFromFolder",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Schlüssel aus einem Verzeichnis installieren",
|
||||
"el_GR": "",
|
||||
"en_US": "Install keys from a directory",
|
||||
"es_ES": "Instalar keys de un directorio",
|
||||
@@ -1001,7 +1001,7 @@
|
||||
"ID": "MenuBarActionsXCITrimmer",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "XCI-Dateien trimmen",
|
||||
"el_GR": "",
|
||||
"en_US": "Trim XCI Files",
|
||||
"es_ES": "Recortar archivos XCI",
|
||||
@@ -1226,7 +1226,7 @@
|
||||
"ID": "MenuBarHelpFaqAndGuides",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "FAQ & Anleitungen",
|
||||
"el_GR": "",
|
||||
"en_US": "FAQ & Guides",
|
||||
"es_ES": "",
|
||||
@@ -1251,7 +1251,7 @@
|
||||
"ID": "MenuBarHelpFaq",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "FAQ & Fehlerbehebung Seite",
|
||||
"el_GR": "",
|
||||
"en_US": "FAQ & Troubleshooting Page",
|
||||
"es_ES": "",
|
||||
@@ -1276,7 +1276,7 @@
|
||||
"ID": "MenuBarHelpFaqTooltip",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Öffnet die FAQ- und Fehlerbehebungsseite im offiziellen Ryujinx-Wiki",
|
||||
"el_GR": "",
|
||||
"en_US": "Opens the FAQ and Troubleshooting page on the official Ryujinx wiki",
|
||||
"es_ES": "",
|
||||
@@ -1301,7 +1301,7 @@
|
||||
"ID": "MenuBarHelpSetup",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Setup- und Konfigurationsanleitung",
|
||||
"el_GR": "",
|
||||
"en_US": "Setup & Configuration Guide",
|
||||
"es_ES": "",
|
||||
@@ -1326,7 +1326,7 @@
|
||||
"ID": "MenuBarHelpSetupTooltip",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Öffnet die Setup- und Konfigurationsanleitung im offiziellen Ryujinx-Wiki",
|
||||
"el_GR": "",
|
||||
"en_US": "Opens the Setup & Configuration guide on the official Ryujinx wiki",
|
||||
"es_ES": "",
|
||||
@@ -1351,7 +1351,7 @@
|
||||
"ID": "MenuBarHelpMultiplayer",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Multiplayer (LDN/LAN) Anleitung",
|
||||
"el_GR": "",
|
||||
"en_US": "Multiplayer (LDN/LAN) Guide",
|
||||
"es_ES": "",
|
||||
@@ -1376,7 +1376,7 @@
|
||||
"ID": "MenuBarHelpMultiplayerTooltip",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Öffnet die Multiplayer-Anleitung im offiziellen Ryujinx-Wiki",
|
||||
"el_GR": "",
|
||||
"en_US": "Opens the Multiplayer guide on the official Ryujinx wiki",
|
||||
"es_ES": "",
|
||||
@@ -1526,7 +1526,7 @@
|
||||
"ID": "GameListHeaderDeveloper",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Entwickelt von {0}",
|
||||
"el_GR": "",
|
||||
"en_US": "Developed by {0}",
|
||||
"es_ES": "",
|
||||
@@ -1826,7 +1826,7 @@
|
||||
"ID": "GameListHeaderCompatibilityStatus",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Kompatibilität:",
|
||||
"el_GR": "",
|
||||
"en_US": "Compatibility:",
|
||||
"es_ES": "",
|
||||
@@ -2614,7 +2614,7 @@
|
||||
"pl_PL": "",
|
||||
"pt_BR": "Extraia o RomFS de um arquivo DLC selecionado",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"sv_SE": "Extrahera RomFS från en vald DLC-fil",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
@@ -2722,6 +2722,31 @@
|
||||
"zh_TW": "建立桌面捷徑,啟動選取的應用程式"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "GameListContextMenuEditGameConfiguration",
|
||||
"Translations": {
|
||||
"ar_SA": "تعديل تكوين اللعبة",
|
||||
"de_DE": "Spielkonfiguration bearbeiten",
|
||||
"el_GR": "Επεξεργασία ρυθμίσεων παιχνιδιού",
|
||||
"en_US": "Edit Game Configuration",
|
||||
"es_ES": "Editar configuración del juego",
|
||||
"fr_FR": "Modifier la configuration du jeu",
|
||||
"he_IL": "ערוך את הגדרת המשחק",
|
||||
"it_IT": "Modifica configurazione gioco",
|
||||
"ja_JP": "ゲーム設定を編集",
|
||||
"ko_KR": "게임 설정 편집",
|
||||
"no_NO": "Rediger spillkonfig.",
|
||||
"pl_PL": "Edytuj konfigurację gry",
|
||||
"pt_BR": "Editar configuração do jogo",
|
||||
"ru_RU": "Редактировать конфигурацию игры",
|
||||
"sv_SE": "Redigera spelkonfiguration",
|
||||
"th_TH": "แก้ไขการตั้งค่าเกม",
|
||||
"tr_TR": "Oyunun yapılandırmasını düzenle",
|
||||
"uk_UA": "Редагувати конфігурацію гри",
|
||||
"zh_CN": "编辑游戏配置",
|
||||
"zh_TW": "編輯遊戲設定"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "GameListContextMenuCreateShortcutToolTipMacOS",
|
||||
"Translations": {
|
||||
@@ -2747,6 +2772,31 @@
|
||||
"zh_TW": "在 macOS 的應用程式資料夾中建立捷徑,啟動選取的應用程式"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "EditGameConfigurationToolTip",
|
||||
"Translations": {
|
||||
"ar_SA": "ينشئ تكوينًا مستقلًا للعبة الحالية",
|
||||
"de_DE": "Erstellt eine unabhängige Konfiguration für das aktuelle Spiel",
|
||||
"el_GR": "Δημιουργεί μια ανεξάρτητη διαμόρφωση για το τρέχον παιχνίδι",
|
||||
"en_US": "Creates an independent configuration for the current game",
|
||||
"es_ES": "Crea una configuración independiente para el juego actual",
|
||||
"fr_FR": "Crée une configuration indépendante pour le jeu en cours",
|
||||
"he_IL": "יוצר תצורה עצמאית למשחק הנוכחי",
|
||||
"it_IT": "Crea una configurazione indipendente per il gioco attuale",
|
||||
"ja_JP": "現在のゲーム用の独立した設定を作成します",
|
||||
"ko_KR": "현재 게임에 대한 독립적인 설정을 생성합니다",
|
||||
"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": "Создает независимую конфигурацию для текущей игры",
|
||||
"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",
|
||||
"uk_UA": "Створює незалежну конфігурацію для поточної гри",
|
||||
"zh_CN": "为当前游戏创建独立的配置",
|
||||
"zh_TW": "為當前遊戲創建獨立的配置"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "GameListContextMenuShowCompatEntry",
|
||||
"Translations": {
|
||||
@@ -3062,7 +3112,7 @@
|
||||
"ko_KR": "XCI 파일 '{0}' 트리밍",
|
||||
"no_NO": "Trimming av XCI-filen '{0}'",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "Reduzindo arquivo XCI '{0}",
|
||||
"pt_BR": "Reduzindo arquivo XCI '{0}'",
|
||||
"ru_RU": "Обрезается XCI файл '{0}'",
|
||||
"sv_SE": "Optimerar XCI-filen '{0}'",
|
||||
"th_TH": "",
|
||||
@@ -3272,6 +3322,31 @@
|
||||
"zh_TW": "設定"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SettingsWithInfo",
|
||||
"Translations": {
|
||||
"ar_SA": "{0} - إعدادات",
|
||||
"de_DE": "Einstellungen - {0}",
|
||||
"el_GR": "Ρυθμίσεις - {0}",
|
||||
"en_US": "Settings - {0}",
|
||||
"es_ES": "Configuración - {0}",
|
||||
"fr_FR": "Paramètres - {0}",
|
||||
"he_IL": "{0} - הגדרות",
|
||||
"it_IT": "Impostazioni - {0}",
|
||||
"ja_JP": "設定 - {0}",
|
||||
"ko_KR": "설정 - {0}",
|
||||
"no_NO": "Innstillinger - {0}",
|
||||
"pl_PL": "Ustawienia - {0}",
|
||||
"pt_BR": "Configurações - {0}",
|
||||
"ru_RU": "Параметры - {0}",
|
||||
"sv_SE": "Inställningar - {0}",
|
||||
"th_TH": "ตั้งค่า - {0}",
|
||||
"tr_TR": "Ayarlar - {0}",
|
||||
"uk_UA": "Налаштування - {0}",
|
||||
"zh_CN": "设置 - {0}",
|
||||
"zh_TW": "設定 - {0}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SettingsTabGeneral",
|
||||
"Translations": {
|
||||
@@ -4621,7 +4696,7 @@
|
||||
"zh_CN": "繁体中文(推荐)",
|
||||
"zh_TW": "正體中文 (建議)"
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"ID": "SettingsTabSystemSystemLanguageSwedish",
|
||||
"Translations": {
|
||||
@@ -4646,7 +4721,7 @@
|
||||
"zh_CN": "瑞典语",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"ID": "SettingsTabSystemSystemLanguageNorwegian",
|
||||
"Translations": {
|
||||
@@ -6464,7 +6539,7 @@
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"sv_SE": "Ok",
|
||||
"th_TH": "ตกลง",
|
||||
"tr_TR": "Tamam",
|
||||
"uk_UA": "",
|
||||
@@ -8364,7 +8439,7 @@
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"sv_SE": "Inaktivera",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
@@ -8389,7 +8464,7 @@
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"sv_SE": "Regnbåge",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
@@ -8439,7 +8514,7 @@
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"sv_SE": "Färg",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
@@ -12672,6 +12747,31 @@
|
||||
"zh_TW": "正在下載更新..."
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "DialogRebooterMessage",
|
||||
"Translations": {
|
||||
"ar_SA": "من فضلك انتظر، المحاكي في طور إعادة التشغيل",
|
||||
"de_DE": "Bitte warten Sie, der Emulator wird neu gestartet",
|
||||
"el_GR": "Παρακαλώ περιμένετε, ο εξομοιωτής επανεκκινείται",
|
||||
"en_US": "Please wait, the emulator is restarting",
|
||||
"es_ES": "Por favor, espere, el emulador se está reiniciando",
|
||||
"fr_FR": "Veuillez patienter, l'émulateur est en train de redémarrer",
|
||||
"he_IL": "אנא המתן, המחקה מתארגן מחדש",
|
||||
"it_IT": "Attendere prego, l'emulatore si sta riavviando",
|
||||
"ja_JP": "お待ちください、エミュレーターが再起動しています",
|
||||
"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",
|
||||
"ru_RU": "Пожалуйста, подождите, эмулятор перезапускается",
|
||||
"sv_SE": "Vänligen vänta, emulatorn startar om",
|
||||
"th_TH": "กรุณารอสักครู่, ตัวจำลองกำลังเริ่มใหม่",
|
||||
"tr_TR": "Lütfen bekleyin, emülatör yeniden başlatılıyor",
|
||||
"uk_UA": "Будь ласка, зачекайте, емулятор перезавантажується",
|
||||
"zh_CN": "请稍等,模拟器正在重新启动",
|
||||
"zh_TW": "請稍候,模擬器正在重新啟動"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "DialogUpdaterExtractionMessage",
|
||||
"Translations": {
|
||||
@@ -15239,7 +15339,7 @@
|
||||
"pl_PL": "Seria Amiibo",
|
||||
"pt_BR": "Franquia Amiibo",
|
||||
"ru_RU": "Серия Amiibo",
|
||||
"sv_SE": "",
|
||||
"sv_SE": "Amiibo-serie",
|
||||
"th_TH": "",
|
||||
"tr_TR": "Amiibo Serisi",
|
||||
"uk_UA": "Серія Amiibo",
|
||||
@@ -18664,7 +18764,7 @@
|
||||
"pl_PL": "",
|
||||
"pt_BR": "{0} - Informação",
|
||||
"ru_RU": "{0} - Информация",
|
||||
"sv_SE": "",
|
||||
"sv_SE": "{0} - Information",
|
||||
"th_TH": "{0} – ข้อมูล",
|
||||
"tr_TR": "{0} - Bilgi",
|
||||
"uk_UA": "{0} - Інформація",
|
||||
@@ -19522,6 +19622,31 @@
|
||||
"zh_TW": "{0} 更新程式"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "RyujinxRebooter",
|
||||
"Translations": {
|
||||
"ar_SA": "إعادة تشغيل {0}",
|
||||
"de_DE": "Neustart von {0}",
|
||||
"el_GR": "Επανεκκίνηση {0}",
|
||||
"en_US": "{0} Reboot",
|
||||
"es_ES": "Reinicio de {0}",
|
||||
"fr_FR": "Redémarrage de {0}",
|
||||
"he_IL": "אתחול {0}",
|
||||
"it_IT": "Riavvio di {0}",
|
||||
"ja_JP": "{0} 再起動",
|
||||
"ko_KR": "{0} 재부팅",
|
||||
"no_NO": "Omstart av {0}",
|
||||
"pl_PL": "Ponowne uruchomienie {0}",
|
||||
"pt_BR": "Reinício de {0}",
|
||||
"ru_RU": "{0} Перезагрузка",
|
||||
"sv_SE": "Ominläsning av {0}",
|
||||
"th_TH": "เริ่มต้นใหม่ {0}",
|
||||
"tr_TR": "{0} Yeniden Başlatma",
|
||||
"uk_UA": "Перезавантаження {0}",
|
||||
"zh_CN": "{0} 重启",
|
||||
"zh_TW": "{0} 重新啟動"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SettingsTabHotkeys",
|
||||
"Translations": {
|
||||
@@ -19739,7 +19864,7 @@
|
||||
"pl_PL": "",
|
||||
"pt_BR": "Configurações de LED",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"sv_SE": "LED-inställningar",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
@@ -21939,7 +22064,7 @@
|
||||
"pl_PL": "Głoś",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "Громкость",
|
||||
"sv_SE": "",
|
||||
"sv_SE": "Volym",
|
||||
"th_TH": "ระดับเสียง",
|
||||
"tr_TR": "Ses",
|
||||
"uk_UA": "Гуч.",
|
||||
@@ -23351,7 +23476,7 @@
|
||||
"ID": "SettingsTabSystemVSyncModeTooltip",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Emulierte vertikale Synchronisation. \"Switch\" emuliert die 60Hz-Bildwiederholfrequenz der Switch. \"Unbounded\" ist eine unbegrenzte Bildwiederholfrequenz.",
|
||||
"el_GR": "",
|
||||
"en_US": "Emulated Vertical Sync. 'Switch' emulates the Switch's refresh rate of 60Hz. 'Unbounded' is an unbounded refresh rate.",
|
||||
"es_ES": "",
|
||||
@@ -23376,7 +23501,7 @@
|
||||
"ID": "SettingsTabSystemVSyncModeTooltipCustom",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Emulierte vertikale Synchronisation. \"Switch\" emuliert die 60Hz-Bildwiederholfrequenz der Switch. „Unbounded“ ist eine unbegrenzte Bildwiederholfrequenz. „Benutzerdefinierte Bildwiederholfrequenz“ emuliert die angegebene benutzerdefinierte Bildwiederholfrequenz.",
|
||||
"el_GR": "",
|
||||
"en_US": "Emulated Vertical Sync. 'Switch' emulates the Switch's refresh rate of 60Hz. 'Unbounded' is an unbounded refresh rate. 'Custom Refresh Rate' emulates the specified custom refresh rate.",
|
||||
"es_ES": "",
|
||||
@@ -23401,7 +23526,7 @@
|
||||
"ID": "SettingsTabSystemEnableCustomVSyncIntervalTooltip",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Ermöglicht es dem Benutzer, eine emulierte Bildwiederholfrequenz festzulegen. In einigen Titeln kann dies die Geschwindigkeit der Spiel-Logik erhöhen oder verringern. In anderen Titeln kann dies dazu führen, dass die FPS auf ein Vielfaches der Bildwiederholfrequenz begrenzt werden oder zu unvorhersehbarem Verhalten führen. Dies ist eine experimentelle Funktion, ohne Garantien dafür, wie sich das Gameplay auswirkt. \n\nLassen Sie diese Option deaktiviert, wenn Sie sich nicht sicher sind.",
|
||||
"el_GR": "",
|
||||
"en_US": "Allows the user to specify an emulated refresh rate. In some titles, this may speed up or slow down the rate of gameplay logic. In other titles, it may allow for capping FPS at some multiple of the refresh rate, or lead to unpredictable behavior. This is an experimental feature, with no guarantees for how gameplay will be affected. \n\nLeave OFF if unsure.",
|
||||
"es_ES": "",
|
||||
@@ -23426,7 +23551,7 @@
|
||||
"ID": "SettingsTabSystemCustomVSyncIntervalValueTooltip",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Der Zielwert für die benutzerdefinierte Bildwiederholfrequenz.",
|
||||
"el_GR": "",
|
||||
"en_US": "The custom refresh rate target value.",
|
||||
"es_ES": "",
|
||||
@@ -23451,7 +23576,7 @@
|
||||
"ID": "SettingsTabSystemCustomVSyncIntervalSliderTooltip",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Die benutzerdefinierte Bildwiederholfrequenz als Prozentsatz der normalen Switch-Bildwiederholfrequenz.",
|
||||
"el_GR": "",
|
||||
"en_US": "The custom refresh rate, as a percentage of the normal Switch refresh rate.",
|
||||
"es_ES": "",
|
||||
@@ -23476,7 +23601,7 @@
|
||||
"ID": "SettingsTabSystemCustomVSyncIntervalPercentage",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Benutzerdefinierte Bildwiederholfrequenz %:",
|
||||
"el_GR": "",
|
||||
"en_US": "Custom Refresh Rate %:",
|
||||
"es_ES": "",
|
||||
@@ -23501,7 +23626,7 @@
|
||||
"ID": "SettingsTabSystemCustomVSyncIntervalValue",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Wert für benutzerdefinierte Bildwiederholfrequenz:",
|
||||
"el_GR": "",
|
||||
"en_US": "Custom Refresh Rate Value:",
|
||||
"es_ES": "",
|
||||
@@ -23551,7 +23676,7 @@
|
||||
"ID": "SettingsTabHotkeysToggleVSyncModeHotkey",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "VSync-Modus umschalten:",
|
||||
"el_GR": "",
|
||||
"en_US": "Toggle VSync mode:",
|
||||
"es_ES": "",
|
||||
@@ -23576,7 +23701,7 @@
|
||||
"ID": "SettingsTabHotkeysIncrementCustomVSyncIntervalHotkey",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Benutzerdefinierte Bildwiederholfrequenz erhöhen:",
|
||||
"el_GR": "",
|
||||
"en_US": "Raise custom refresh rate",
|
||||
"es_ES": "",
|
||||
@@ -23601,7 +23726,7 @@
|
||||
"ID": "SettingsTabHotkeysDecrementCustomVSyncIntervalHotkey",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Benutzerdefinierte Bildwiederholfrequenz senken:",
|
||||
"el_GR": "",
|
||||
"en_US": "Lower custom refresh rate:",
|
||||
"es_ES": "",
|
||||
@@ -23626,7 +23751,7 @@
|
||||
"ID": "CompatibilityListLastUpdated",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Zuletzt aktualisiert: {0}",
|
||||
"el_GR": "",
|
||||
"en_US": "Last updated: {0}",
|
||||
"es_ES": "",
|
||||
@@ -23651,7 +23776,7 @@
|
||||
"ID": "CompatibilityListWarning",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Diese Kompatibilitätsliste könnte veraltete Einträge enthalten. Teste dennoch Spiele im \"Ingame\"-Status.",
|
||||
"el_GR": "",
|
||||
"en_US": "This compatibility list might contain out of date entries.\nDo not be opposed to testing games in the \"Ingame\" status.",
|
||||
"es_ES": "",
|
||||
@@ -23676,7 +23801,7 @@
|
||||
"ID": "CompatibilityListSearchBoxWatermark",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Kompatibilitätseinträge durchsuchen...",
|
||||
"el_GR": "",
|
||||
"en_US": "Search compatibility entries...",
|
||||
"es_ES": "",
|
||||
@@ -23726,7 +23851,7 @@
|
||||
"ID": "CompatibilityListOnlyShowOwnedGames",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Nur eigene Spiele anzeigen",
|
||||
"el_GR": "",
|
||||
"en_US": "Only show owned games",
|
||||
"es_ES": "",
|
||||
@@ -23751,7 +23876,7 @@
|
||||
"ID": "CompatibilityListPlayable",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Spielbar",
|
||||
"el_GR": "",
|
||||
"en_US": "Playable",
|
||||
"es_ES": "",
|
||||
@@ -23776,7 +23901,7 @@
|
||||
"ID": "CompatibilityListIngame",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Im Spiel",
|
||||
"el_GR": "",
|
||||
"en_US": "Ingame",
|
||||
"es_ES": "",
|
||||
@@ -23951,7 +24076,7 @@
|
||||
"ID": "CompatibilityListBootsTooltip",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Startet, kommt aber nicht über den Titelbildschirm hinaus.",
|
||||
"el_GR": "",
|
||||
"en_US": "Boots but does not make it past the title screen.",
|
||||
"es_ES": "",
|
||||
@@ -23976,7 +24101,7 @@
|
||||
"ID": "CompatibilityListNothingTooltip",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"de_DE": "Startet nicht oder zeigt keine Anzeichen von Aktivität.",
|
||||
"el_GR": "",
|
||||
"en_US": "Does not boot or shows no signs of activity.",
|
||||
"es_ES": "",
|
||||
@@ -23998,11 +24123,36 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "ExtractAocListHeader",
|
||||
"ID": "UserConfigurationHeader",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "User Config",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "ExtractAocListHeader",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "Wähle ein DLC zum Extrahieren aus",
|
||||
"el_GR": "",
|
||||
"en_US": "Select a DLC to Extract",
|
||||
"es_ES": "",
|
||||
"fr_FR": "Choisissez un DLC à extraire",
|
||||
@@ -24014,7 +24164,7 @@
|
||||
"pl_PL": "",
|
||||
"pt_BR": "Selecione um DLC para extrair",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"sv_SE": "Välj en DLC att extrahera",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace Ryujinx.Ava.Common.Locale
|
||||
SetDynamicValues(LocaleKeys.RyujinxInfo, RyujinxApp.FullAppName);
|
||||
SetDynamicValues(LocaleKeys.RyujinxConfirm, RyujinxApp.FullAppName);
|
||||
SetDynamicValues(LocaleKeys.RyujinxUpdater, RyujinxApp.FullAppName);
|
||||
SetDynamicValues(LocaleKeys.RyujinxRebooter, RyujinxApp.FullAppName);
|
||||
}
|
||||
|
||||
public string this[LocaleKeys key]
|
||||
|
||||
@@ -32,8 +32,10 @@ namespace Ryujinx.Ava
|
||||
public static double DesktopScaleFactor { get; set; } = 1.0;
|
||||
public static string Version { get; private set; }
|
||||
public static string ConfigurationPath { get; private set; }
|
||||
public static string GlobalConfigurationPath { get; private set; }
|
||||
public static bool PreviewerDetached { get; private set; }
|
||||
public static bool UseHardwareAcceleration { get; private set; }
|
||||
public static string BackendThreadingArg { get; private set; }
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
public static partial int MessageBoxA(nint hWnd, [MarshalAs(UnmanagedType.LPStr)] string text, [MarshalAs(UnmanagedType.LPStr)] string caption, uint type);
|
||||
@@ -155,11 +157,43 @@ namespace Ryujinx.Ava
|
||||
}
|
||||
}
|
||||
|
||||
public static bool FindGameConfig(string gameDir)
|
||||
{
|
||||
if (File.Exists(gameDir))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static string GetDirGameUserConfig(string gameId, bool rememberGlobalDir = false, bool changeFolderForGame = false)
|
||||
{
|
||||
string gameDir = Path.Combine(AppDataManager.GamesDirPath, gameId, ReleaseInformation.ConfigName);
|
||||
|
||||
// Should load with the game if there is a custom setting for the game
|
||||
if (rememberGlobalDir)
|
||||
{
|
||||
GlobalConfigurationPath = ConfigurationPath;
|
||||
}
|
||||
|
||||
if (changeFolderForGame)
|
||||
{
|
||||
ConfigurationPath = gameDir;
|
||||
}
|
||||
|
||||
return gameDir;
|
||||
}
|
||||
|
||||
public static void ReloadConfig()
|
||||
{
|
||||
//It is necessary that when a user setting appears, the global setting remains available
|
||||
GlobalConfigurationPath = null;
|
||||
|
||||
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
||||
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
||||
|
||||
|
||||
// Now load the configuration as the other subsystems are now registered
|
||||
if (File.Exists(localConfigurationPath))
|
||||
{
|
||||
@@ -217,6 +251,11 @@ namespace Ryujinx.Ava
|
||||
_ => ConfigurationState.Instance.Graphics.BackendThreading
|
||||
};
|
||||
|
||||
if (CommandLineState.OverrideBackendThreadingAfterReboot is not null)
|
||||
{
|
||||
BackendThreadingArg = CommandLineState.OverrideBackendThreadingAfterReboot;
|
||||
}
|
||||
|
||||
// Check if docked mode was overriden.
|
||||
if (CommandLineState.OverrideDockedMode.HasValue)
|
||||
ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value;
|
||||
@@ -232,6 +271,33 @@ 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 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.
|
||||
if (CommandLineState.OverrideHardwareAcceleration != null)
|
||||
|
||||
95
src/Ryujinx/Rebooter.cs
Normal file
95
src/Ryujinx/Rebooter.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using SkiaSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava
|
||||
{
|
||||
internal static class Rebooter
|
||||
{
|
||||
|
||||
private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
|
||||
|
||||
|
||||
public static void RebootAppWithGame(string gamePath, List<string> args)
|
||||
{
|
||||
_ = Reboot(gamePath, args);
|
||||
|
||||
}
|
||||
|
||||
private static async Task Reboot(string gamePath, List<string> args)
|
||||
{
|
||||
|
||||
bool shouldRestart = true;
|
||||
|
||||
TaskDialog taskDialog = new()
|
||||
{
|
||||
Header = LocaleManager.Instance[LocaleKeys.RyujinxRebooter],
|
||||
SubHeader = LocaleManager.Instance[LocaleKeys.DialogRebooterMessage],
|
||||
IconSource = new SymbolIconSource { Symbol = Symbol.Games },
|
||||
XamlRoot = RyujinxApp.MainWindow,
|
||||
};
|
||||
|
||||
if (shouldRestart)
|
||||
{
|
||||
List<string> arguments = CommandLineState.Arguments.ToList();
|
||||
string executableDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
// On macOS we perform the update at relaunch.
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
string baseBundlePath = Path.GetFullPath(Path.Combine(executableDirectory, "..", ".."));
|
||||
string newBundlePath = Path.Combine(_updateDir, "Ryujinx.app");
|
||||
string updaterScriptPath = Path.Combine(newBundlePath, "Contents", "Resources", "updater.sh");
|
||||
string currentPid = Environment.ProcessId.ToString();
|
||||
|
||||
arguments.InsertRange(0, new List<string> { updaterScriptPath, baseBundlePath, newBundlePath, currentPid });
|
||||
Process.Start("/bin/bash", arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
var dialogTask = taskDialog.ShowAsync(true);
|
||||
await Task.Delay(500);
|
||||
|
||||
// Find the process name.
|
||||
string ryuName = Path.GetFileName(Environment.ProcessPath) ?? string.Empty;
|
||||
|
||||
// Some operating systems can see the renamed executable, so strip off the .ryuold if found.
|
||||
if (ryuName.EndsWith(".ryuold"))
|
||||
{
|
||||
ryuName = ryuName[..^7];
|
||||
}
|
||||
|
||||
// Fallback if the executable could not be found.
|
||||
if (ryuName.Length == 0 || !Path.Exists(Path.Combine(executableDirectory, ryuName)))
|
||||
{
|
||||
ryuName = OperatingSystem.IsWindows() ? "Ryujinx.exe" : "Ryujinx";
|
||||
}
|
||||
|
||||
ProcessStartInfo processStart = new(ryuName)
|
||||
{
|
||||
UseShellExecute = true,
|
||||
WorkingDirectory = executableDirectory,
|
||||
};
|
||||
|
||||
foreach (var arg in args)
|
||||
{
|
||||
processStart.ArgumentList.Add(arg);
|
||||
}
|
||||
|
||||
processStart.ArgumentList.Add(gamePath);
|
||||
|
||||
Process.Start(processStart);
|
||||
}
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,11 @@
|
||||
Header="{ext:Locale GameListContextMenuCreateShortcut}"
|
||||
Icon="{ext:Icon fa-solid fa-bookmark}"
|
||||
ToolTip.Tip="{OnPlatform Default={ext:Locale GameListContextMenuCreateShortcutToolTip}, macOS={ext:Locale GameListContextMenuCreateShortcutToolTipMacOS}}" />
|
||||
<MenuItem
|
||||
Click="EditGameConfiguration_Click"
|
||||
Header="{ext:Locale GameListContextMenuEditGameConfiguration}"
|
||||
Icon="{ext:Icon fa-solid fa-gear}"
|
||||
ToolTip.Tip="{ext:Locale EditGameConfigurationToolTip}" />
|
||||
<MenuItem
|
||||
IsVisible="{Binding HasCompatibilityEntry}"
|
||||
Click="OpenApplicationCompatibility_Click"
|
||||
|
||||
@@ -386,13 +386,26 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
viewModel.SelectedApplication.Icon
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public async void EditGameConfiguration_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
{
|
||||
await new GameSpecificSettingsWindow(viewModel).ShowDialog((Window)viewModel.TopLevel);
|
||||
|
||||
//just checking for file presence
|
||||
viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false));
|
||||
|
||||
viewModel.RefreshView();
|
||||
}
|
||||
}
|
||||
|
||||
public async void OpenApplicationCompatibility_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
await CompatibilityList.Show(viewModel.SelectedApplication.IdString);
|
||||
}
|
||||
|
||||
|
||||
public async void OpenApplicationData_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
Focusable="True"
|
||||
@@ -73,12 +74,18 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
IsVisible="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ShowNames}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Name}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<TextBlock
|
||||
Text="{Binding Name}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
IsVisible="{Binding HasIndependentConfiguration}"
|
||||
Text="{ext:Locale UserConfigurationHeader}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource Warning}" />
|
||||
</StackPanel>
|
||||
</Panel>
|
||||
</Grid>
|
||||
</Border>
|
||||
@@ -86,10 +93,28 @@
|
||||
Margin="5,5,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
FontSize="16"
|
||||
FontSize="18"
|
||||
Foreground="{DynamicResource FavoriteApplicationIconColor}"
|
||||
IsVisible="{Binding Favorite}"
|
||||
Symbol="StarFilled" />
|
||||
<Grid IsVisible="{Binding !$parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ShowNames}">
|
||||
<Border
|
||||
Margin="15,35,5,15"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Bottom"
|
||||
Width="90"
|
||||
Height="20"
|
||||
CornerRadius="4"
|
||||
IsVisible="{Binding HasIndependentConfiguration}"
|
||||
Background="{DynamicResource ThemeContentBackgroundColor}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{ext:Locale UserConfigurationHeader}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
Focusable="True"
|
||||
@@ -156,6 +157,13 @@
|
||||
Text="{Binding Converter={x:Static helpers:MultiplayerInfoConverter.Instance}}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap"/>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
IsVisible="{Binding HasIndependentConfiguration}"
|
||||
Text="{ext:Locale UserConfigurationHeader}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource Warning}" />
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="4"
|
||||
|
||||
@@ -355,6 +355,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
set
|
||||
{
|
||||
ListSelectedApplication = value;
|
||||
GridSelectedApplication = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo;
|
||||
@@ -1084,7 +1089,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
_rendererWaitEvent.WaitOne();
|
||||
|
||||
AppHost?.Start();
|
||||
|
||||
|
||||
AppHost?.DisposeContext();
|
||||
}
|
||||
|
||||
@@ -1531,8 +1536,50 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool InitializeUserConfig(ApplicationData application)
|
||||
{
|
||||
// Code where conditions will be met before loading the user configuration (Global Config)
|
||||
BackendThreading backendThreadingValue = ConfigurationState.Instance.Graphics.BackendThreading.Value;
|
||||
string BackendThreadingInit = Program.BackendThreadingArg;
|
||||
|
||||
if (BackendThreadingInit is null)
|
||||
{
|
||||
BackendThreadingInit = ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString();
|
||||
}
|
||||
|
||||
// If a configuration is found in the "/games/xxxxxxxxxxxxxx" folder, the program will load the user setting.
|
||||
string idGame = application.IdBaseString;
|
||||
if (ConfigurationFileFormat.TryLoad(Program.GetDirGameUserConfig(idGame), out ConfigurationFileFormat configurationFileFormat))
|
||||
{
|
||||
// Loads the user configuration, having previously changed the global configuration to the user configuration
|
||||
ConfigurationState.Instance.Load(configurationFileFormat, Program.GetDirGameUserConfig(idGame, true, true), idGame);
|
||||
}
|
||||
|
||||
// Code where conditions will be executed after loading user configuration
|
||||
if (ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() != BackendThreadingInit)
|
||||
{
|
||||
|
||||
List<string> Arguments = new List<string>
|
||||
{
|
||||
"--bt", ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() // BackendThreading
|
||||
};
|
||||
|
||||
Rebooter.RebootAppWithGame(application.Path, Arguments);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task LoadApplication(ApplicationData application, bool startFullscreen = false, BlitStruct<ApplicationControlProperty>? customNacpData = null)
|
||||
{
|
||||
|
||||
if (InitializeUserConfig(application))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (AppHost != null)
|
||||
{
|
||||
await ContentDialogHelper.CreateInfoDialog(
|
||||
@@ -1548,7 +1595,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
#if RELEASE
|
||||
await PerformanceCheck();
|
||||
#endif
|
||||
|
||||
|
||||
Logger.RestartTime();
|
||||
|
||||
SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(application.Path, ConfigurationState.Instance.System.Language, application.Id);
|
||||
@@ -1593,6 +1640,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
|
||||
gameThread.Start();
|
||||
|
||||
}
|
||||
|
||||
public void SwitchToRenderer(bool startFullscreen) =>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Humanizer;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using Ryujinx.Audio.Backends.OpenAL;
|
||||
using Ryujinx.Audio.Backends.SDL2;
|
||||
@@ -27,6 +29,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.Threading.Tasks;
|
||||
@@ -69,6 +72,17 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public SettingsHacksViewModel DirtyHacks { get; }
|
||||
|
||||
private readonly bool _isGameRunning;
|
||||
private Bitmap _gameIcon;
|
||||
private string _gameTitle;
|
||||
private string _gamePath;
|
||||
private string _gameId;
|
||||
public bool IsGameRunning => _isGameRunning;
|
||||
public Bitmap GameIcon => _gameIcon;
|
||||
public string GamePath => _gamePath;
|
||||
public string GameTitle => _gameTitle;
|
||||
public string GameId => _gameId;
|
||||
|
||||
public int ResolutionScale
|
||||
{
|
||||
get => _resolutionScale;
|
||||
@@ -336,7 +350,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public bool IsInvalidLdnPassphraseVisible { get; set; }
|
||||
|
||||
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
|
||||
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this(false)
|
||||
{
|
||||
_virtualFileSystem = virtualFileSystem;
|
||||
_contentManager = contentManager;
|
||||
@@ -349,7 +363,51 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsViewModel()
|
||||
public SettingsViewModel(
|
||||
VirtualFileSystem virtualFileSystem,
|
||||
ContentManager contentManager,
|
||||
bool gameRunning,
|
||||
string gamePath,
|
||||
string gameName,
|
||||
string gameId,
|
||||
byte[] gameIconData,
|
||||
bool enableToLoadCustomConfig) : this(enableToLoadCustomConfig)
|
||||
{
|
||||
_virtualFileSystem = virtualFileSystem;
|
||||
_contentManager = contentManager;
|
||||
|
||||
if (gameIconData != null && gameIconData.Length > 0)
|
||||
{
|
||||
using (var ms = new MemoryStream(gameIconData))
|
||||
{
|
||||
_gameIcon = new Bitmap(ms);
|
||||
}
|
||||
}
|
||||
|
||||
_isGameRunning = gameRunning;
|
||||
_gamePath = gamePath;
|
||||
_gameTitle = gameName;
|
||||
_gameId = gameId;
|
||||
|
||||
if (enableToLoadCustomConfig) // During the game. If there is no user config, then load the global config window
|
||||
{
|
||||
string gameDir = Program.GetDirGameUserConfig(gameId, false, true);
|
||||
if (ConfigurationFileFormat.TryLoad(gameDir, out ConfigurationFileFormat configurationFileFormat))
|
||||
{
|
||||
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId);
|
||||
}
|
||||
|
||||
LoadCurrentConfiguration(); // Needed to load custom configuration
|
||||
}
|
||||
|
||||
if (Program.PreviewerDetached)
|
||||
{
|
||||
Task.Run(LoadTimeZones);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsViewModel(bool noLoadGlobalConfig = false)
|
||||
{
|
||||
GameDirectories = [];
|
||||
AutoloadDirectories = [];
|
||||
@@ -364,7 +422,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
if (Program.PreviewerDetached)
|
||||
{
|
||||
Task.Run(LoadAvailableGpus);
|
||||
LoadCurrentConfiguration();
|
||||
|
||||
if (!noLoadGlobalConfig)// Default is false, but loading custom config avoids double call
|
||||
{
|
||||
LoadCurrentConfiguration();
|
||||
}
|
||||
|
||||
DirtyHacks = new SettingsHacksViewModel(this);
|
||||
}
|
||||
@@ -475,29 +537,35 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
ConfigurationState config = ConfigurationState.Instance;
|
||||
|
||||
// User Interface
|
||||
EnableDiscordIntegration = config.EnableDiscordIntegration;
|
||||
CheckUpdatesOnStart = config.CheckUpdatesOnStart;
|
||||
ShowConfirmExit = config.ShowConfirmExit;
|
||||
RememberWindowState = config.RememberWindowState;
|
||||
ShowTitleBar = config.ShowTitleBar;
|
||||
HideCursor = (int)config.HideCursor.Value;
|
||||
UpdateCheckerType = (int)config.UpdateCheckerType.Value;
|
||||
FocusLostActionType = (int)config.FocusLostActionType.Value;
|
||||
|
||||
GameDirectories.Clear();
|
||||
GameDirectories.AddRange(config.UI.GameDirs.Value);
|
||||
|
||||
AutoloadDirectories.Clear();
|
||||
AutoloadDirectories.AddRange(config.UI.AutoloadDirs.Value);
|
||||
|
||||
BaseStyleIndex = config.UI.BaseStyle.Value switch
|
||||
//It is necessary that the data is used from the global configuration file
|
||||
if (string.IsNullOrEmpty(GameId))
|
||||
{
|
||||
"Auto" => 0,
|
||||
"Light" => 1,
|
||||
"Dark" => 2,
|
||||
_ => 0
|
||||
};
|
||||
// User Interface
|
||||
EnableDiscordIntegration = config.EnableDiscordIntegration;
|
||||
CheckUpdatesOnStart = config.CheckUpdatesOnStart;
|
||||
ShowConfirmExit = config.ShowConfirmExit;
|
||||
RememberWindowState = config.RememberWindowState;
|
||||
ShowTitleBar = config.ShowTitleBar;
|
||||
HideCursor = (int)config.HideCursor.Value;
|
||||
UpdateCheckerType = (int)config.UpdateCheckerType.Value;
|
||||
FocusLostActionType = (int)config.FocusLostActionType.Value;
|
||||
|
||||
GameDirectories.Clear();
|
||||
GameDirectories.AddRange(config.UI.GameDirs.Value);
|
||||
|
||||
AutoloadDirectories.Clear();
|
||||
AutoloadDirectories.AddRange(config.UI.AutoloadDirs.Value);
|
||||
|
||||
BaseStyleIndex = config.UI.BaseStyle.Value switch
|
||||
{
|
||||
"Auto" => 0,
|
||||
"Light" => 1,
|
||||
"Dark" => 2,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// Input
|
||||
EnableDockedMode = config.System.EnableDockedMode;
|
||||
@@ -518,7 +586,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
DateTime currentDateTime = currentHostDateTime.Add(systemDateTimeOffset);
|
||||
CurrentDate = currentDateTime.Date;
|
||||
CurrentTime = currentDateTime.TimeOfDay;
|
||||
|
||||
MatchSystemTime = config.System.MatchSystemTime;
|
||||
|
||||
EnableCustomVSyncInterval = config.Graphics.EnableCustomVSyncInterval;
|
||||
@@ -579,39 +646,44 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
LdnPassphrase = config.Multiplayer.LdnPassphrase;
|
||||
LdnServer = config.Multiplayer.LdnServer;
|
||||
}
|
||||
|
||||
|
||||
public void SaveSettings()
|
||||
{
|
||||
ConfigurationState config = ConfigurationState.Instance;
|
||||
bool userConfigFile = string.IsNullOrEmpty(GameId);
|
||||
|
||||
// User Interface
|
||||
config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
|
||||
config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
|
||||
config.ShowConfirmExit.Value = ShowConfirmExit;
|
||||
config.RememberWindowState.Value = RememberWindowState;
|
||||
config.ShowTitleBar.Value = ShowTitleBar;
|
||||
config.HideCursor.Value = (HideCursorMode)HideCursor;
|
||||
config.UpdateCheckerType.Value = (UpdaterType)UpdateCheckerType;
|
||||
config.FocusLostActionType.Value = (FocusLostType)FocusLostActionType;
|
||||
|
||||
if (GameDirectoryChanged)
|
||||
if (userConfigFile)
|
||||
{
|
||||
config.UI.GameDirs.Value = [..GameDirectories];
|
||||
// User Interface
|
||||
config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
|
||||
config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
|
||||
config.ShowConfirmExit.Value = ShowConfirmExit;
|
||||
config.RememberWindowState.Value = RememberWindowState;
|
||||
config.ShowTitleBar.Value = ShowTitleBar;
|
||||
config.HideCursor.Value = (HideCursorMode)HideCursor;
|
||||
config.UpdateCheckerType.Value = (UpdaterType)UpdateCheckerType;
|
||||
config.FocusLostActionType.Value = (FocusLostType)FocusLostActionType;
|
||||
|
||||
if (GameDirectoryChanged)
|
||||
{
|
||||
config.UI.GameDirs.Value = [.. GameDirectories];
|
||||
}
|
||||
|
||||
if (AutoloadDirectoryChanged)
|
||||
{
|
||||
config.UI.AutoloadDirs.Value = [.. AutoloadDirectories];
|
||||
}
|
||||
|
||||
config.UI.BaseStyle.Value = BaseStyleIndex switch
|
||||
{
|
||||
0 => "Auto",
|
||||
1 => "Light",
|
||||
2 => "Dark",
|
||||
_ => "Auto"
|
||||
};
|
||||
}
|
||||
|
||||
if (AutoloadDirectoryChanged)
|
||||
{
|
||||
config.UI.AutoloadDirs.Value = [..AutoloadDirectories];
|
||||
}
|
||||
|
||||
config.UI.BaseStyle.Value = BaseStyleIndex switch
|
||||
{
|
||||
0 => "Auto",
|
||||
1 => "Light",
|
||||
2 => "Dark",
|
||||
_ => "Auto"
|
||||
};
|
||||
|
||||
// Input
|
||||
config.System.EnableDockedMode.Value = EnableDockedMode;
|
||||
config.Hid.EnableKeyboard.Value = EnableKeyboard;
|
||||
@@ -708,7 +780,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
config.Hacks.EnableShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelayEnabled;
|
||||
config.Hacks.ShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelay;
|
||||
|
||||
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||
|
||||
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||
|
||||
|
||||
MainWindow.UpdateGraphicsConfig();
|
||||
RyujinxApp.MainWindow.ViewModel.VSyncModeSettingChanged();
|
||||
@@ -721,7 +795,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private static void RevertIfNotSaved()
|
||||
{
|
||||
Program.ReloadConfig();
|
||||
// maybe this is an unnecessary check(all options need to be tested)
|
||||
if (string.IsNullOrEmpty(Program.GlobalConfigurationPath))
|
||||
{
|
||||
Program.ReloadConfig();
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyButton()
|
||||
@@ -729,6 +807,26 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
public void DeleteConfigGame()
|
||||
{
|
||||
string gameDir = Program.GetDirGameUserConfig(GameId,false,false);
|
||||
|
||||
if (File.Exists(gameDir))
|
||||
{
|
||||
File.Delete(gameDir);
|
||||
}
|
||||
|
||||
RevertIfNotSaved();
|
||||
CloseWindow?.Invoke();
|
||||
}
|
||||
|
||||
public void SaveUserConfig()
|
||||
{
|
||||
SaveSettings();
|
||||
RevertIfNotSaved(); // Revert global configuration after saving user configuration
|
||||
CloseWindow?.Invoke();
|
||||
}
|
||||
|
||||
public void OkButton()
|
||||
{
|
||||
SaveSettings();
|
||||
|
||||
@@ -130,9 +130,26 @@ namespace Ryujinx.Ava.UI.Views.Main
|
||||
Window.SettingsWindow = new(Window.VirtualFileSystem, Window.ContentManager);
|
||||
|
||||
Rainbow.Enable();
|
||||
|
||||
await Window.SettingsWindow.ShowDialog(Window);
|
||||
|
||||
|
||||
if (ViewModel.SelectedApplication is null) // Checks if game data exists
|
||||
{
|
||||
await Window.SettingsWindow.ShowDialog(Window);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool userConfigExist = Program.FindGameConfig(Program.GetDirGameUserConfig(ViewModel.SelectedApplication.IdString, false, false));
|
||||
|
||||
if (!ViewModel.IsGameRunning || !userConfigExist)
|
||||
{
|
||||
await Window.SettingsWindow.ShowDialog(Window); // The game is not running, or if the user configuration does not exist
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is a custom configuration in the folder
|
||||
await new GameSpecificSettingsWindow(ViewModel, userConfigExist).ShowDialog((Window)ViewModel.TopLevel);
|
||||
}
|
||||
}
|
||||
|
||||
Rainbow.Disable();
|
||||
Rainbow.Reset();
|
||||
|
||||
|
||||
149
src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml
Normal file
149
src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml
Normal file
@@ -0,0 +1,149 @@
|
||||
<window:StyleableAppWindow
|
||||
x:Class="Ryujinx.Ava.UI.Windows.GameSpecificSettingsWindow"
|
||||
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"
|
||||
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
||||
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:SettingsInputView Name="InputPage" />
|
||||
<settings:SettingsSystemView Name="SystemPage" />
|
||||
<settings:SettingsCPUView Name="CpuPage" />
|
||||
<settings:SettingsGraphicsView Name="GraphicsPage" />
|
||||
<settings:SettingsAudioView Name="AudioPage" />
|
||||
<settings:SettingsNetworkView Name="NetworkPage" />
|
||||
<settings:SettingsLoggingView Name="LoggingPage" />
|
||||
<settings:SettingsHacksView Name="HacksPage" />
|
||||
</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
|
||||
Content="{ext:Locale SettingsTabInput}"
|
||||
Tag="InputPage"
|
||||
IconSource="Games" />
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabSystem}"
|
||||
Tag="SystemPage"
|
||||
IconSource="Settings" />
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabCpu}"
|
||||
Tag="CpuPage">
|
||||
<ui:NavigationViewItem.IconSource>
|
||||
<ui:FontIconSource
|
||||
FontFamily="avares://Ryujinx/Assets/Fonts#Segoe Fluent Icons"
|
||||
Glyph="{helpers:GlyphValueConverter Chip}" />
|
||||
</ui:NavigationViewItem.IconSource>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabGraphics}"
|
||||
Tag="GraphicsPage"
|
||||
IconSource="Image" />
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabAudio}"
|
||||
IconSource="Audio"
|
||||
Tag="AudioPage" />
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabNetwork}"
|
||||
Tag="NetworkPage"
|
||||
IconSource="Globe" />
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabLogging}"
|
||||
Tag="LoggingPage"
|
||||
IconSource="Document" />
|
||||
<ui:NavigationViewItem
|
||||
IsVisible="{Binding ShowDirtyHacks}"
|
||||
Content="Dirty Hacks"
|
||||
Tag="HacksPage"
|
||||
IconSource="Code" />
|
||||
</ui:NavigationView.MenuItems>
|
||||
</ui:NavigationView>
|
||||
|
||||
<ReversibleStackPanel
|
||||
Grid.Row="2"
|
||||
Margin="10"
|
||||
Spacing="10"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right"
|
||||
ReverseOrder="{x:Static helper:RunningPlatform.IsMacOS}">
|
||||
<Button
|
||||
Content="{ext:Locale SettingsButtonSave}"
|
||||
Command="{Binding SaveUserConfig}" />
|
||||
<Button
|
||||
HotKey="Escape"
|
||||
Content="{ext:Locale SettingsButtonClose}"
|
||||
Command="{Binding CancelButton}" />
|
||||
<Button
|
||||
IsVisible="{Binding IsGameRunning}"
|
||||
Content="{ext:Locale SettingsButtonApply}"
|
||||
Command="{Binding ApplyButton}" />
|
||||
<Button
|
||||
IsVisible="{Binding !IsGameRunning}"
|
||||
Content="{ext:Locale UserProfilesDelete}"
|
||||
Command="{Binding DeleteConfigGame}"
|
||||
Classes="red"/>
|
||||
</ReversibleStackPanel>
|
||||
</Grid>
|
||||
</window:StyleableAppWindow>
|
||||
117
src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml.cs
Normal file
117
src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
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 GameSpecificSettingsWindow : StyleableAppWindow
|
||||
{
|
||||
internal readonly SettingsViewModel ViewModel;
|
||||
|
||||
public GameSpecificSettingsWindow(MainWindowViewModel viewModel, bool findUserConfigDir = true)
|
||||
{
|
||||
Title = string.Format(LocaleManager.Instance[LocaleKeys.SettingsWithInfo], viewModel.SelectedApplication.Name, viewModel.SelectedApplication.IdString);
|
||||
|
||||
DataContext = ViewModel = new SettingsViewModel(
|
||||
viewModel.VirtualFileSystem,
|
||||
viewModel.ContentManager,
|
||||
viewModel.IsGameRunning,
|
||||
viewModel.SelectedApplication.Path,
|
||||
viewModel.SelectedApplication.Name,
|
||||
viewModel.SelectedApplication.IdString,
|
||||
viewModel.SelectedApplication.Icon,
|
||||
findUserConfigDir);
|
||||
|
||||
ViewModel.CloseWindow += Close;
|
||||
ViewModel.SaveSettingsEvent += SaveSettings;
|
||||
|
||||
InitializeComponent();
|
||||
Load();
|
||||
|
||||
#if DEBUG
|
||||
this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
public void SaveSettings()
|
||||
{
|
||||
InputPage.InputView?.SaveCurrentProfile();
|
||||
}
|
||||
|
||||
|
||||
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(InputPage):
|
||||
NavPanel.Content = InputPage;
|
||||
break;
|
||||
case nameof(SystemPage):
|
||||
SystemPage.ViewModel = ViewModel;
|
||||
NavPanel.Content = SystemPage;
|
||||
break;
|
||||
case nameof(CpuPage):
|
||||
NavPanel.Content = CpuPage;
|
||||
break;
|
||||
case nameof(GraphicsPage):
|
||||
NavPanel.Content = GraphicsPage;
|
||||
break;
|
||||
case nameof(AudioPage):
|
||||
NavPanel.Content = AudioPage;
|
||||
break;
|
||||
case nameof(NetworkPage):
|
||||
NetworkPage.ViewModel = ViewModel;
|
||||
NavPanel.Content = NetworkPage;
|
||||
break;
|
||||
case nameof(LoggingPage):
|
||||
NavPanel.Content = LoggingPage;
|
||||
break;
|
||||
case nameof(HacksPage):
|
||||
HacksPage.DataContext = ViewModel;
|
||||
NavPanel.Content = HacksPage;
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnClosing(WindowClosingEventArgs e)
|
||||
{
|
||||
InputPage.Dispose(); // You need to unload the gamepad settings, otherwise the controls will be blocked
|
||||
base.OnClosing(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -223,7 +223,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
_deferLoad = true;
|
||||
_launchPath = launchPathArg;
|
||||
_launchApplicationId = launchApplicationId;
|
||||
_startFullscreen = startFullscreenArg;
|
||||
_startFullscreen = startFullscreenArg;
|
||||
}
|
||||
|
||||
public void SwitchToGameControl(bool startFullscreen = false)
|
||||
@@ -374,6 +374,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
if (applicationData != null)
|
||||
{
|
||||
ViewModel.SelectedApplication = applicationData;
|
||||
await ViewModel.LoadApplication(applicationData, _startFullscreen);
|
||||
}
|
||||
else
|
||||
@@ -385,6 +386,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
else
|
||||
{
|
||||
applicationData = applications[0];
|
||||
ViewModel.SelectedApplication = applicationData;
|
||||
await ViewModel.LoadApplication(applicationData, _startFullscreen);
|
||||
}
|
||||
}
|
||||
@@ -658,6 +660,11 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
ReloadGameList();
|
||||
}
|
||||
|
||||
public void GameListUpdate()
|
||||
{
|
||||
ReloadGameList();
|
||||
}
|
||||
|
||||
public void ToggleFileType(string fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
public class ApplicationData
|
||||
{
|
||||
public bool Favorite { get; set; }
|
||||
public bool HasIndependentConfiguration { get; set; }
|
||||
public byte[] Icon { get; set; }
|
||||
public string Name { get; set; } = "Unknown";
|
||||
|
||||
|
||||
@@ -505,7 +505,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
if (data.Id != 0)
|
||||
{
|
||||
ApplicationMetadata appMetadata = LoadAndSaveMetaData(data.IdString, appMetadata =>
|
||||
{
|
||||
{
|
||||
appMetadata.Title = data.Name;
|
||||
|
||||
// Only do the migration if time_played has a value and timespan_played hasn't been updated yet.
|
||||
@@ -529,10 +529,11 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
data.Favorite = appMetadata.Favorite;
|
||||
data.TimePlayed = appMetadata.TimePlayed;
|
||||
data.LastPlayed = appMetadata.LastPlayed;
|
||||
data.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(data.IdBaseString, false, false)); // Just check user config
|
||||
}
|
||||
|
||||
data.FileExtension = Path.GetExtension(applicationPath).TrimStart('.').ToUpper();
|
||||
|
||||
@@ -6,11 +6,16 @@ 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 OverrideBackendThreadingAfterReboot { 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; }
|
||||
@@ -19,6 +24,7 @@ namespace Ryujinx.Ava.Utilities
|
||||
public static bool StartFullscreenArg { get; private set; }
|
||||
public static bool HideAvailableUpdates { get; private set; }
|
||||
|
||||
|
||||
public static void ParseArguments(string[] args)
|
||||
{
|
||||
List<string> arguments = [];
|
||||
@@ -28,6 +34,11 @@ namespace Ryujinx.Ava.Utilities
|
||||
{
|
||||
string arg = args[i];
|
||||
|
||||
if (arg.Contains("-") || arg.Contains("--"))
|
||||
{
|
||||
CountArguments++;
|
||||
}
|
||||
|
||||
switch (arg)
|
||||
{
|
||||
case "-r":
|
||||
@@ -85,6 +96,57 @@ namespace Ryujinx.Ava.Utilities
|
||||
|
||||
OverrideBackendThreading = args[++i];
|
||||
break;
|
||||
case "--bt":
|
||||
if (i + 1 >= args.Length)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
OverrideBackendThreadingAfterReboot = 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];
|
||||
|
||||
@@ -18,9 +18,15 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
{
|
||||
public partial class ConfigurationState
|
||||
{
|
||||
public void Load(ConfigurationFileFormat cff, string configurationFilePath)
|
||||
public void Load(ConfigurationFileFormat cff, string configurationFilePath, string titleId = "")
|
||||
{
|
||||
bool configurationFileUpdated = false;
|
||||
bool shouldLoadFromFile = true;
|
||||
|
||||
if (!string.IsNullOrEmpty(titleId))
|
||||
{
|
||||
shouldLoadFromFile = false;
|
||||
}
|
||||
|
||||
if (cff.Version is < 0 or > ConfigurationFileFormat.CurrentVersion)
|
||||
{
|
||||
@@ -43,16 +49,17 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
configurationFileUpdated = true;
|
||||
}
|
||||
|
||||
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
|
||||
CheckUpdatesOnStart.Value = cff.CheckUpdatesOnStart;
|
||||
UpdateCheckerType.Value = cff.UpdateCheckerType;
|
||||
FocusLostActionType.Value = cff.FocusLostActionType;
|
||||
ShowConfirmExit.Value = cff.ShowConfirmExit;
|
||||
RememberWindowState.Value = cff.RememberWindowState;
|
||||
ShowTitleBar.Value = cff.ShowTitleBar;
|
||||
EnableHardwareAcceleration.Value = cff.EnableHardwareAcceleration;
|
||||
HideCursor.Value = cff.HideCursor;
|
||||
|
||||
|
||||
EnableDiscordIntegration.Value = shouldLoadFromFile ? cff.EnableDiscordIntegration : EnableDiscordIntegration.Value; // Get from global config only
|
||||
CheckUpdatesOnStart.Value = shouldLoadFromFile ? cff.CheckUpdatesOnStart : CheckUpdatesOnStart.Value; // Get from global config only
|
||||
UpdateCheckerType.Value = shouldLoadFromFile ? cff.UpdateCheckerType : UpdateCheckerType.Value; // Get from global config only
|
||||
FocusLostActionType.Value = shouldLoadFromFile ? cff.FocusLostActionType : FocusLostActionType.Value; // Get from global config only
|
||||
ShowConfirmExit.Value = shouldLoadFromFile ? cff.ShowConfirmExit : ShowConfirmExit.Value; // Get from global config only
|
||||
RememberWindowState.Value = shouldLoadFromFile ? cff.RememberWindowState : RememberWindowState.Value; // Get from global config only
|
||||
ShowTitleBar.Value = shouldLoadFromFile ? cff.ShowTitleBar : ShowTitleBar.Value; // Get from global config only
|
||||
EnableHardwareAcceleration.Value = shouldLoadFromFile ? cff.EnableHardwareAcceleration : EnableHardwareAcceleration.Value; // Get from global config only
|
||||
HideCursor.Value = shouldLoadFromFile ? cff.HideCursor : HideCursor.Value; // Get from global config only
|
||||
|
||||
Logger.EnableFileLog.Value = cff.EnableFileLog;
|
||||
Logger.EnableDebug.Value = cff.LoggingEnableDebug;
|
||||
Logger.EnableStub.Value = cff.LoggingEnableStub;
|
||||
@@ -87,7 +94,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
System.Language.Value = cff.SystemLanguage;
|
||||
System.Region.Value = cff.SystemRegion;
|
||||
System.TimeZone.Value = cff.SystemTimeZone;
|
||||
System.SystemTimeOffset.Value = cff.SystemTimeOffset;
|
||||
System.SystemTimeOffset.Value = shouldLoadFromFile ? cff.SystemTimeOffset : System.SystemTimeOffset.Value; // Get from global config only
|
||||
System.EnableDockedMode.Value = cff.DockedMode;
|
||||
System.EnablePtc.Value = cff.EnablePtc;
|
||||
System.EnableLowPowerPtc.Value = cff.EnableLowPowerPtc;
|
||||
@@ -101,47 +108,48 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
System.IgnoreMissingServices.Value = cff.IgnoreMissingServices;
|
||||
System.IgnoreApplet.Value = cff.IgnoreApplet;
|
||||
System.UseHypervisor.Value = cff.UseHypervisor;
|
||||
|
||||
UI.GuiColumns.FavColumn.Value = cff.GuiColumns.FavColumn;
|
||||
UI.GuiColumns.IconColumn.Value = cff.GuiColumns.IconColumn;
|
||||
UI.GuiColumns.AppColumn.Value = cff.GuiColumns.AppColumn;
|
||||
UI.GuiColumns.DevColumn.Value = cff.GuiColumns.DevColumn;
|
||||
UI.GuiColumns.VersionColumn.Value = cff.GuiColumns.VersionColumn;
|
||||
UI.GuiColumns.TimePlayedColumn.Value = cff.GuiColumns.TimePlayedColumn;
|
||||
UI.GuiColumns.LastPlayedColumn.Value = cff.GuiColumns.LastPlayedColumn;
|
||||
UI.GuiColumns.FileExtColumn.Value = cff.GuiColumns.FileExtColumn;
|
||||
UI.GuiColumns.FileSizeColumn.Value = cff.GuiColumns.FileSizeColumn;
|
||||
UI.GuiColumns.PathColumn.Value = cff.GuiColumns.PathColumn;
|
||||
UI.ColumnSort.SortColumnId.Value = cff.ColumnSort.SortColumnId;
|
||||
UI.ColumnSort.SortAscending.Value = cff.ColumnSort.SortAscending;
|
||||
UI.GameDirs.Value = cff.GameDirs;
|
||||
UI.AutoloadDirs.Value = cff.AutoloadDirs ?? [];
|
||||
UI.ShownFileTypes.NSP.Value = cff.ShownFileTypes.NSP;
|
||||
UI.ShownFileTypes.PFS0.Value = cff.ShownFileTypes.PFS0;
|
||||
UI.ShownFileTypes.XCI.Value = cff.ShownFileTypes.XCI;
|
||||
UI.ShownFileTypes.NCA.Value = cff.ShownFileTypes.NCA;
|
||||
UI.ShownFileTypes.NRO.Value = cff.ShownFileTypes.NRO;
|
||||
UI.ShownFileTypes.NSO.Value = cff.ShownFileTypes.NSO;
|
||||
UI.LanguageCode.Value = cff.LanguageCode;
|
||||
UI.BaseStyle.Value = cff.BaseStyle;
|
||||
UI.GameListViewMode.Value = cff.GameListViewMode;
|
||||
UI.ShowNames.Value = cff.ShowNames;
|
||||
UI.IsAscendingOrder.Value = cff.IsAscendingOrder;
|
||||
UI.GridSize.Value = cff.GridSize;
|
||||
UI.ApplicationSort.Value = cff.ApplicationSort;
|
||||
UI.StartFullscreen.Value = cff.StartFullscreen;
|
||||
UI.StartNoUI.Value = cff.StartNoUI;
|
||||
UI.ShowConsole.Value = cff.ShowConsole;
|
||||
UI.WindowStartup.WindowSizeWidth.Value = cff.WindowStartup.WindowSizeWidth;
|
||||
UI.WindowStartup.WindowSizeHeight.Value = cff.WindowStartup.WindowSizeHeight;
|
||||
UI.WindowStartup.WindowPositionX.Value = cff.WindowStartup.WindowPositionX;
|
||||
UI.WindowStartup.WindowPositionY.Value = cff.WindowStartup.WindowPositionY;
|
||||
UI.WindowStartup.WindowMaximized.Value = cff.WindowStartup.WindowMaximized;
|
||||
|
||||
|
||||
UI.GuiColumns.FavColumn.Value = shouldLoadFromFile ? cff.GuiColumns.FavColumn : UI.GuiColumns.FavColumn.Value;
|
||||
UI.GuiColumns.IconColumn.Value = shouldLoadFromFile ? cff.GuiColumns.IconColumn : UI.GuiColumns.IconColumn.Value;
|
||||
UI.GuiColumns.AppColumn.Value = shouldLoadFromFile ? cff.GuiColumns.AppColumn : UI.GuiColumns.AppColumn.Value;
|
||||
UI.GuiColumns.DevColumn.Value = shouldLoadFromFile ? cff.GuiColumns.DevColumn : UI.GuiColumns.DevColumn.Value;
|
||||
UI.GuiColumns.VersionColumn.Value = shouldLoadFromFile ? cff.GuiColumns.VersionColumn : UI.GuiColumns.VersionColumn.Value;
|
||||
UI.GuiColumns.TimePlayedColumn.Value = shouldLoadFromFile ? cff.GuiColumns.TimePlayedColumn : UI.GuiColumns.TimePlayedColumn.Value;
|
||||
UI.GuiColumns.LastPlayedColumn.Value = shouldLoadFromFile ? cff.GuiColumns.LastPlayedColumn : UI.GuiColumns.LastPlayedColumn.Value;
|
||||
UI.GuiColumns.FileExtColumn.Value = shouldLoadFromFile ? cff.GuiColumns.FileExtColumn : UI.GuiColumns.FileExtColumn.Value;
|
||||
UI.GuiColumns.FileSizeColumn.Value = shouldLoadFromFile ? cff.GuiColumns.FileSizeColumn : UI.GuiColumns.FileSizeColumn.Value;
|
||||
UI.GuiColumns.PathColumn.Value = shouldLoadFromFile ? cff.GuiColumns.PathColumn : UI.GuiColumns.PathColumn.Value;
|
||||
UI.ColumnSort.SortColumnId.Value = shouldLoadFromFile ? cff.ColumnSort.SortColumnId : UI.ColumnSort.SortColumnId.Value;
|
||||
UI.ColumnSort.SortAscending.Value = shouldLoadFromFile ? cff.ColumnSort.SortAscending : UI.ColumnSort.SortAscending.Value;
|
||||
UI.GameDirs.Value = shouldLoadFromFile ? cff.GameDirs : UI.GameDirs.Value;
|
||||
UI.AutoloadDirs.Value = shouldLoadFromFile ? (cff.AutoloadDirs ?? []) : UI.AutoloadDirs.Value;
|
||||
UI.ShownFileTypes.NSP.Value = shouldLoadFromFile ? cff.ShownFileTypes.NSP : UI.ShownFileTypes.NSP.Value;
|
||||
UI.ShownFileTypes.PFS0.Value = shouldLoadFromFile ? cff.ShownFileTypes.PFS0 : UI.ShownFileTypes.PFS0.Value;
|
||||
UI.ShownFileTypes.XCI.Value = shouldLoadFromFile ? cff.ShownFileTypes.XCI : UI.ShownFileTypes.XCI.Value;
|
||||
UI.ShownFileTypes.NCA.Value = shouldLoadFromFile ? cff.ShownFileTypes.NCA : UI.ShownFileTypes.NCA.Value;
|
||||
UI.ShownFileTypes.NRO.Value = shouldLoadFromFile ? cff.ShownFileTypes.NRO : UI.ShownFileTypes.NRO.Value;
|
||||
UI.ShownFileTypes.NSO.Value = shouldLoadFromFile ? cff.ShownFileTypes.NSO : UI.ShownFileTypes.NSO.Value;
|
||||
UI.LanguageCode.Value = shouldLoadFromFile ? cff.LanguageCode : UI.LanguageCode.Value;
|
||||
UI.BaseStyle.Value = shouldLoadFromFile ? cff.BaseStyle : UI.BaseStyle.Value;
|
||||
UI.GameListViewMode.Value = shouldLoadFromFile ? cff.GameListViewMode : UI.GameListViewMode.Value;
|
||||
UI.ShowNames.Value = shouldLoadFromFile ? cff.ShowNames : UI.ShowNames.Value;
|
||||
UI.IsAscendingOrder.Value = shouldLoadFromFile ? cff.IsAscendingOrder : UI.IsAscendingOrder.Value;
|
||||
UI.GridSize.Value = shouldLoadFromFile ? cff.GridSize : UI.GridSize.Value;
|
||||
UI.ApplicationSort.Value = shouldLoadFromFile ? cff.ApplicationSort : UI.ApplicationSort.Value;
|
||||
UI.StartFullscreen.Value = shouldLoadFromFile ? cff.StartFullscreen : UI.StartFullscreen.Value;
|
||||
UI.StartNoUI.Value = shouldLoadFromFile ? cff.StartNoUI : UI.StartNoUI.Value;
|
||||
UI.ShowConsole.Value = shouldLoadFromFile ? cff.ShowConsole : UI.ShowConsole.Value;
|
||||
UI.WindowStartup.WindowSizeWidth.Value = shouldLoadFromFile ? cff.WindowStartup.WindowSizeWidth : UI.WindowStartup.WindowSizeWidth.Value;
|
||||
UI.WindowStartup.WindowSizeHeight.Value = shouldLoadFromFile ? cff.WindowStartup.WindowSizeHeight : UI.WindowStartup.WindowSizeHeight.Value;
|
||||
UI.WindowStartup.WindowPositionX.Value = shouldLoadFromFile ? cff.WindowStartup.WindowPositionX : UI.WindowStartup.WindowPositionX.Value;
|
||||
UI.WindowStartup.WindowPositionY.Value = shouldLoadFromFile ? cff.WindowStartup.WindowPositionY : UI.WindowStartup.WindowPositionY.Value;
|
||||
UI.WindowStartup.WindowMaximized.Value = shouldLoadFromFile ? cff.WindowStartup.WindowMaximized : UI.WindowStartup.WindowMaximized.Value;
|
||||
|
||||
|
||||
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
||||
Hid.EnableMouse.Value = cff.EnableMouse;
|
||||
Hid.DisableInputWhenOutOfFocus.Value = cff.DisableInputWhenOutOfFocus;
|
||||
Hid.Hotkeys.Value = cff.Hotkeys;
|
||||
Hid.DisableInputWhenOutOfFocus.Value = shouldLoadFromFile ? cff.DisableInputWhenOutOfFocus: Hid.DisableInputWhenOutOfFocus.Value; // Get from global config only
|
||||
Hid.Hotkeys.Value = shouldLoadFromFile ? cff.Hotkeys : Hid.Hotkeys.Value; // Get from global config only
|
||||
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
||||
Hid.RainbowSpeed.Value = cff.RainbowSpeed;
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user