Compare commits
16 Commits
eb9d6ea3ab
...
218498a7d2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
218498a7d2 | ||
|
|
7f7055a037 | ||
|
|
30fef8e96e | ||
|
|
9cb5f5689b | ||
|
|
af13f4bb3b | ||
|
|
03692e6072 | ||
|
|
a205ec374b | ||
|
|
aab9b58542 | ||
|
|
daa648dc40 | ||
|
|
1024aa8757 | ||
|
|
6f4930d547 | ||
|
|
1ca5407c22 | ||
|
|
13388e972a | ||
|
|
1eb78872d8 | ||
|
|
fe9fe2a10f | ||
|
|
0399af0ff9 |
@@ -2480,6 +2480,7 @@
|
||||
010081C0191D8000,"Rune Factory 3 Special",,playable,2023-10-15 08:32:49
|
||||
010051D00E3A4000,"Rune Factory 4 Special",32-bit;crash;nvdec,ingame,2023-05-06 08:49:17
|
||||
010014D01216E000,"Rune Factory 5 (JP)",gpu,ingame,2021-06-01 12:00:36
|
||||
010071E0145F8000,"Rustler",,playable,2025-02-10 20:17:12
|
||||
0100E21013908000,"RWBY: Grimm Eclipse - Definitive Edition",online-broken,playable,2022-11-03 10:44:01
|
||||
010012C0060F0000,"RXN -Raijin-",nvdec,playable,2021-01-10 16:05:43
|
||||
0100B8B012ECA000,"S.N.I.P.E.R. - Hunter Scope",,playable,2021-04-19 15:58:09
|
||||
|
||||
|
@@ -219,6 +219,7 @@ namespace Ryujinx.Common
|
||||
//Misc Games
|
||||
"010056e00853a000", // A Hat in Time
|
||||
"0100fd1014726000", // Baldurs Gate: Dark Alliance
|
||||
"01008c2019598000", // Bluey: The Video Game
|
||||
"0100c6800b934000", // Brawlhalla
|
||||
"0100dbf01000a000", // Burnout Paradise Remastered
|
||||
"0100744001588000", // Cars 3: Driven to Win
|
||||
|
||||
@@ -3425,26 +3425,101 @@
|
||||
{
|
||||
"ID": "SettingsTabGeneralCheckUpdatesOnLaunch",
|
||||
"Translations": {
|
||||
"ar_SA": "التحقق من وجود تحديثات عند التشغيل",
|
||||
"de_DE": "Beim Start nach Updates suchen",
|
||||
"el_GR": "Έλεγχος για Ενημερώσεις στην Εκκίνηση",
|
||||
"en_US": "Check for Updates on Launch",
|
||||
"es_ES": "Buscar actualizaciones al iniciar",
|
||||
"fr_FR": "Vérifier les mises à jour au démarrage",
|
||||
"he_IL": "בדוק אם קיימים עדכונים בהפעלה",
|
||||
"it_IT": "Controlla aggiornamenti all'avvio",
|
||||
"ja_JP": "起動時にアップデートを確認する",
|
||||
"ko_KR": "시작 시, 업데이트 확인",
|
||||
"no_NO": "Se etter oppdateringer ved oppstart",
|
||||
"pl_PL": "Sprawdzaj aktualizacje przy uruchomieniu",
|
||||
"pt_BR": "Verificar se há atualizações ao iniciar",
|
||||
"ru_RU": "Проверять наличие обновлений при запуске",
|
||||
"sv_SE": "Leta efter uppdatering vid uppstart",
|
||||
"th_TH": "ตรวจหาการอัปเดตเมื่อเปิดโปรแกรม",
|
||||
"tr_TR": "Her Açılışta Güncellemeleri Denetle",
|
||||
"uk_UA": "Перевіряти наявність оновлень під час запуску",
|
||||
"zh_CN": "启动时检查更新",
|
||||
"zh_TW": "啟動時檢查更新"
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Check for Updates:",
|
||||
"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": "SettingsTabGeneralCheckUpdatesOnLaunchOff",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Off",
|
||||
"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": "SettingsTabGeneralCheckUpdatesOnLaunchPromptAtStartup",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Prompt",
|
||||
"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": "SettingsTabGeneralCheckUpdatesOnLaunchBackground",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Background",
|
||||
"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": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -12497,6 +12572,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": {
|
||||
@@ -17747,6 +17847,31 @@
|
||||
"zh_TW": "更新已停用!"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "UpdaterBackgroundStatusBarButtonText",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Update Available!",
|
||||
"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": "ControllerSettingsRotate90",
|
||||
"Translations": {
|
||||
@@ -19322,6 +19447,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": {
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Ryujinx.Ava
|
||||
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);
|
||||
@@ -250,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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using DynamicData;
|
||||
using DynamicData.Binding;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
@@ -104,6 +105,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
[ObservableProperty] private bool _isSubMenuOpen;
|
||||
[ObservableProperty] private ApplicationContextMenu _listAppContextMenu;
|
||||
[ObservableProperty] private ApplicationContextMenu _gridAppContextMenu;
|
||||
[ObservableProperty] private bool _updateAvailable;
|
||||
|
||||
public static AsyncRelayCommand UpdateCommand { get; } = Commands.Create(async () =>
|
||||
{
|
||||
if (Updater.CanUpdate(true))
|
||||
await Updater.BeginUpdateAsync(true);
|
||||
});
|
||||
|
||||
private bool _showLoadProgress;
|
||||
private bool _isGameRunning;
|
||||
@@ -1523,10 +1531,16 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public void InitializeUserConfig(ApplicationData application)
|
||||
public bool InitializeUserConfig(ApplicationData application)
|
||||
{
|
||||
// Code where conditions will be met before loading the user configuration
|
||||
// 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;
|
||||
@@ -1537,19 +1551,29 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
|
||||
// Code where conditions will be executed after loading user configuration
|
||||
if (ConfigurationState.Instance.Graphics.BackendThreading != backendThreadingValue)
|
||||
if (ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() != BackendThreadingInit)
|
||||
{
|
||||
/*
|
||||
* The function to restart the emulator together with the selected game
|
||||
Task.Run(async () => await Rebooter.RebootAppWithGame(application.Path));
|
||||
*/
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
InitializeUserConfig(application);
|
||||
if (InitializeUserConfig(application))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (AppHost != null)
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities.Configuration;
|
||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Multiplayer;
|
||||
using Ryujinx.Common.GraphicsDriver;
|
||||
@@ -71,45 +72,16 @@ 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 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 bool IsGameRunning => _isGameRunning;
|
||||
public Bitmap GameIcon => _gameIcon;
|
||||
public string GamePath => _gamePath;
|
||||
public string GameTitle => _gameTitle;
|
||||
public string GameId => _gameId;
|
||||
|
||||
public int ResolutionScale
|
||||
{
|
||||
@@ -164,6 +136,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public bool RememberWindowState { get; set; }
|
||||
public bool ShowTitleBar { get; set; }
|
||||
public int HideCursor { get; set; }
|
||||
public int UpdateCheckerType { get; set; }
|
||||
public bool EnableDockedMode { get; set; }
|
||||
public bool EnableKeyboard { get; set; }
|
||||
public bool EnableMouse { get; set; }
|
||||
@@ -386,8 +359,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsViewModel(VirtualFileSystem virtualFileSystem,
|
||||
public SettingsViewModel(
|
||||
VirtualFileSystem virtualFileSystem,
|
||||
ContentManager contentManager,
|
||||
bool gameRunning,
|
||||
string gamePath,
|
||||
string gameName,
|
||||
string gameId,
|
||||
@@ -401,12 +376,14 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
using (var ms = new MemoryStream(gameIconData))
|
||||
{
|
||||
GameIcon = new Bitmap(ms);
|
||||
_gameIcon = new Bitmap(ms);
|
||||
}
|
||||
}
|
||||
|
||||
GameTitle = gameName;
|
||||
GameId = gameId;
|
||||
_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
|
||||
{
|
||||
@@ -557,6 +534,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
ConfigurationState config = ConfigurationState.Instance;
|
||||
|
||||
|
||||
//It is necessary that the data is used from the global configuration file
|
||||
if (string.IsNullOrEmpty(GameId))
|
||||
{
|
||||
@@ -567,7 +545,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
RememberWindowState = config.RememberWindowState;
|
||||
ShowTitleBar = config.ShowTitleBar;
|
||||
HideCursor = (int)config.HideCursor.Value;
|
||||
|
||||
UpdateCheckerType = (int)config.UpdateCheckerType.Value;
|
||||
|
||||
GameDirectories.Clear();
|
||||
GameDirectories.AddRange(config.UI.GameDirs.Value);
|
||||
|
||||
@@ -668,6 +647,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
ConfigurationState config = ConfigurationState.Instance;
|
||||
bool userConfigFile = string.IsNullOrEmpty(GameId);
|
||||
|
||||
|
||||
if (userConfigFile)
|
||||
{
|
||||
// User Interface
|
||||
@@ -677,6 +657,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
config.RememberWindowState.Value = RememberWindowState;
|
||||
config.ShowTitleBar.Value = ShowTitleBar;
|
||||
config.HideCursor.Value = (HideCursorMode)HideCursor;
|
||||
config.UpdateCheckerType.Value = (UpdaterType)UpdateCheckerType;
|
||||
|
||||
if (GameDirectoryChanged)
|
||||
{
|
||||
|
||||
@@ -51,12 +51,8 @@ namespace Ryujinx.Ava.UI.Views.Main
|
||||
XciTrimmerMenuItem.Command = Commands.Create(XCITrimmerWindow.Show);
|
||||
AboutWindowMenuItem.Command = Commands.Create(AboutWindow.Show);
|
||||
CompatibilityListMenuItem.Command = Commands.Create(() => CompatibilityList.Show());
|
||||
|
||||
UpdateMenuItem.Command = Commands.Create(async () =>
|
||||
{
|
||||
if (Updater.CanUpdate(true))
|
||||
await Updater.BeginUpdateAsync(true);
|
||||
});
|
||||
|
||||
UpdateMenuItem.Command = MainWindowViewModel.UpdateCommand;
|
||||
|
||||
FaqMenuItem.Command =
|
||||
SetupGuideMenuItem.Command =
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
Background="{DynamicResource ThemeContentBackgroundColor}"
|
||||
DockPanel.Dock="Bottom"
|
||||
IsVisible="{Binding ShowMenuAndStatusBar}"
|
||||
ColumnDefinitions="Auto,Auto,*,Auto,Auto">
|
||||
ColumnDefinitions="Auto,Auto,*,Auto,Auto,Auto">
|
||||
<StackPanel
|
||||
Grid.Column="0"
|
||||
Margin="5"
|
||||
@@ -280,9 +280,31 @@
|
||||
Text="{Binding GpuNameText}"
|
||||
TextAlignment="Start" />
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
<StackPanel
|
||||
Grid.Column="4"
|
||||
Margin="0,0,5,0"
|
||||
Orientation="Horizontal">
|
||||
<StackPanel.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="EnableNonGameRunningControls" />
|
||||
<Binding Path="UpdateAvailable" />
|
||||
</MultiBinding>
|
||||
</StackPanel.IsVisible>
|
||||
<Button Margin="0, 0, 5, 0"
|
||||
Command="{Binding UpdateCommand}"
|
||||
Background="{DynamicResource SystemAccentColor}">
|
||||
<TextBlock
|
||||
Margin="-5"
|
||||
Foreground="Black"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{ext:Locale UpdaterBackgroundStatusBarButtonText}" />
|
||||
</Button>
|
||||
<controls:MiniVerticalSeparator Margin="5,0,0,0"/>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="5"
|
||||
Margin="0,0,5,0"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding ShowFirmwareStatus}"
|
||||
Orientation="Horizontal">
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
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"
|
||||
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
||||
mc:Ignorable="d"
|
||||
x:DataType="viewModels:SettingsViewModel">
|
||||
<Design.DataContext>
|
||||
@@ -30,18 +31,33 @@
|
||||
ToolTip.Tip="{ext:Locale ToggleDiscordTooltip}"
|
||||
Text="{ext:Locale SettingsTabGeneralEnableDiscordRichPresence}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding CheckUpdatesOnStart}">
|
||||
<TextBlock Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunch}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding ShowConfirmExit}">
|
||||
<TextBlock Text="{ext:Locale SettingsTabGeneralShowConfirmExitDialog}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding RememberWindowState}">
|
||||
<TextBlock Text="{ext:Locale SettingsTabGeneralRememberWindowState}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding ShowTitleBar}" Name="ShowTitleBarBox">
|
||||
<CheckBox IsChecked="{Binding ShowTitleBar}" IsVisible="{x:Static helper:RunningPlatform.IsWindows}">
|
||||
<TextBlock Text="{ext:Locale SettingsTabGeneralShowTitleBar}" />
|
||||
</CheckBox>
|
||||
<StackPanel Margin="0, 15, 0, 0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunch}"
|
||||
Width="150" />
|
||||
<ComboBox SelectedIndex="{Binding UpdateCheckerType}"
|
||||
HorizontalContentAlignment="Left"
|
||||
MinWidth="100">
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunchOff}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunchPromptAtStartup}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabGeneralCheckUpdatesOnLaunchBackground}" />
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="0, 15, 0, 0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
Text="{ext:Locale SettingsTabGeneralHideCursor}"
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
||||
public SettingsUiView()
|
||||
{
|
||||
InitializeComponent();
|
||||
ShowTitleBarBox.IsVisible = OperatingSystem.IsWindows();
|
||||
AddGameDirButton.Command =
|
||||
Commands.Create(() => AddDirButton(GameDirPathBox, ViewModel.GameDirectories, true));
|
||||
AddAutoloadDirButton.Command =
|
||||
|
||||
@@ -19,6 +19,7 @@ using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.Ava.Utilities.Configuration;
|
||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Helper;
|
||||
using Ryujinx.Common.Logging;
|
||||
@@ -400,10 +401,21 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
await Dispatcher.UIThread.InvokeAsync(async () => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys));
|
||||
}
|
||||
|
||||
if (ConfigurationState.Instance.CheckUpdatesOnStart && !CommandLineState.HideAvailableUpdates && Updater.CanUpdate())
|
||||
if (!Updater.CanUpdate() || CommandLineState.HideAvailableUpdates)
|
||||
return;
|
||||
|
||||
switch (ConfigurationState.Instance.UpdateCheckerType.Value)
|
||||
{
|
||||
await Updater.BeginUpdateAsync()
|
||||
.Catch(task => Logger.Error?.Print(LogClass.Application, $"Updater Error: {task.Exception}"));
|
||||
case UpdaterType.PromptAtStartup:
|
||||
await Updater.BeginUpdateAsync()
|
||||
.Catch(task => Logger.Error?.Print(LogClass.Application, $"Updater Error: {task.Exception}"));
|
||||
break;
|
||||
case UpdaterType.CheckInBackground:
|
||||
if ((await Updater.CheckVersionAsync()).TryGet(out (Version Current, Version Incoming) versions))
|
||||
{
|
||||
Dispatcher.UIThread.Post(() => RyujinxApp.MainWindow.ViewModel.UpdateAvailable = versions.Current < versions.Incoming);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +136,11 @@
|
||||
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"/>
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
DataContext = ViewModel = new SettingsViewModel(
|
||||
viewModel.VirtualFileSystem,
|
||||
viewModel.ContentManager,
|
||||
viewModel.IsGameRunning,
|
||||
viewModel.SelectedApplication.Path,
|
||||
viewModel.SelectedApplication.Name,
|
||||
viewModel.SelectedApplication.IdString,
|
||||
@@ -46,7 +47,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
InitializeComponent();
|
||||
Load();
|
||||
|
||||
|
||||
#if DEBUG
|
||||
this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt));
|
||||
#endif
|
||||
|
||||
@@ -43,7 +43,18 @@ namespace Ryujinx.Ava
|
||||
private const int ConnectionCount = 4;
|
||||
|
||||
private static string _buildVer;
|
||||
private static string _platformExt;
|
||||
|
||||
private static readonly string _platformExt =
|
||||
RunningPlatform.IsMacOS
|
||||
? "macos_universal.app.tar.gz"
|
||||
: RunningPlatform.IsWindows
|
||||
? "win_x64.zip"
|
||||
: RunningPlatform.IsX64Linux
|
||||
? "linux_x64.tar.gz"
|
||||
: RunningPlatform.IsArmLinux
|
||||
? "linux_arm64.tar.gz"
|
||||
: throw new PlatformNotSupportedException();
|
||||
|
||||
private static string _buildUrl;
|
||||
private static long _buildSize;
|
||||
private static bool _updateSuccessful;
|
||||
@@ -51,30 +62,8 @@ namespace Ryujinx.Ava
|
||||
|
||||
private static readonly string[] _windowsDependencyDirs = [];
|
||||
|
||||
public static async Task BeginUpdateAsync(bool showVersionUpToDate = false)
|
||||
public static async Task<Optional<(Version Current, Version Incoming)>> CheckVersionAsync(bool showVersionUpToDate = false)
|
||||
{
|
||||
if (_running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
|
||||
// Detect current platform
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
_platformExt = "macos_universal.app.tar.gz";
|
||||
}
|
||||
else if (OperatingSystem.IsWindows())
|
||||
{
|
||||
_platformExt = "win_x64.zip";
|
||||
}
|
||||
else if (OperatingSystem.IsLinux())
|
||||
{
|
||||
string arch = RuntimeInformation.OSArchitecture == Architecture.Arm64 ? "arm64" : "x64";
|
||||
_platformExt = $"linux_{arch}.tar.gz";
|
||||
}
|
||||
|
||||
if (!Version.TryParse(Program.Version, out Version currentVersion))
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to convert the current {RyujinxApp.FullAppName} version!");
|
||||
@@ -85,7 +74,7 @@ namespace Ryujinx.Ava
|
||||
|
||||
_running = false;
|
||||
|
||||
return;
|
||||
return default;
|
||||
}
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, "Checking for updates.");
|
||||
@@ -123,7 +112,7 @@ namespace Ryujinx.Ava
|
||||
|
||||
_running = false;
|
||||
|
||||
return;
|
||||
return default;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -149,7 +138,7 @@ namespace Ryujinx.Ava
|
||||
|
||||
_running = false;
|
||||
|
||||
return;
|
||||
return default;
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
@@ -161,7 +150,7 @@ namespace Ryujinx.Ava
|
||||
|
||||
_running = false;
|
||||
|
||||
return;
|
||||
return default;
|
||||
}
|
||||
|
||||
if (!Version.TryParse(_buildVer, out Version newVersion))
|
||||
@@ -174,9 +163,27 @@ namespace Ryujinx.Ava
|
||||
|
||||
_running = false;
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
return (currentVersion, newVersion);
|
||||
}
|
||||
|
||||
public static async Task BeginUpdateAsync(bool showVersionUpToDate = false)
|
||||
{
|
||||
if (_running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
|
||||
Optional<(Version, Version)> versionTuple = await CheckVersionAsync(showVersionUpToDate);
|
||||
|
||||
if (_running is false || !versionTuple.HasValue) return;
|
||||
|
||||
(Version currentVersion, Version newVersion) = versionTuple.Value;
|
||||
|
||||
if (newVersion <= currentVersion)
|
||||
{
|
||||
if (showVersionUpToDate)
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Ryujinx.Ava.Utilities
|
||||
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; }
|
||||
@@ -99,6 +100,16 @@ 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)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
/// <summary>
|
||||
/// The current version of the file format
|
||||
/// </summary>
|
||||
public const int CurrentVersion = 64;
|
||||
public const int CurrentVersion = 65;
|
||||
|
||||
/// <summary>
|
||||
/// Version of the configuration file format
|
||||
@@ -163,9 +163,14 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
public bool EnableDiscordIntegration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks for updates when Ryujinx starts when enabled
|
||||
/// DEPRECATED: Checks for updates when Ryujinx starts when enabled
|
||||
/// </summary>
|
||||
public bool CheckUpdatesOnStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification.
|
||||
/// </summary>
|
||||
public UpdaterType UpdateCheckerType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Show "Confirm Exit" Dialog
|
||||
|
||||
@@ -49,14 +49,16 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
configurationFileUpdated = true;
|
||||
}
|
||||
|
||||
|
||||
EnableDiscordIntegration.Value = LoadSetting ? cff.EnableDiscordIntegration : EnableDiscordIntegration.Value; // Get from global config only
|
||||
CheckUpdatesOnStart.Value = LoadSetting ? cff.CheckUpdatesOnStart : CheckUpdatesOnStart.Value; // Get from global config only
|
||||
UpdateCheckerType.Value = LoadSetting ? cff.UpdateCheckerType : UpdateCheckerType.Value; // Get from global config only
|
||||
ShowConfirmExit.Value = LoadSetting ? cff.ShowConfirmExit : ShowConfirmExit.Value; // Get from global config only
|
||||
RememberWindowState.Value = LoadSetting ? cff.RememberWindowState : RememberWindowState.Value; // Get from global config only
|
||||
ShowTitleBar.Value = LoadSetting ? cff.ShowTitleBar : ShowTitleBar.Value; // Get from global config only
|
||||
EnableHardwareAcceleration.Value = LoadSetting ? cff.EnableHardwareAcceleration : EnableHardwareAcceleration.Value; // Get from global config only
|
||||
HideCursor.Value = LoadSetting ? cff.HideCursor : HideCursor.Value; // Get from global config only
|
||||
|
||||
|
||||
Logger.EnableFileLog.Value = cff.EnableFileLog;
|
||||
Logger.EnableDebug.Value = cff.LoggingEnableDebug;
|
||||
Logger.EnableStub.Value = cff.LoggingEnableStub;
|
||||
@@ -438,7 +440,8 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
}),
|
||||
(62, static cff => cff.RainbowSpeed = 1f),
|
||||
(63, static cff => cff.MatchSystemTime = false),
|
||||
(64, static cff => cff.LoggingEnableAvalonia = false)
|
||||
(64, static cff => cff.LoggingEnableAvalonia = false),
|
||||
(65, static cff => cff.UpdateCheckerType = cff.CheckUpdatesOnStart ? UpdaterType.PromptAtStartup : UpdaterType.Off)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using ARMeilleure;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
@@ -767,6 +768,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
/// Checks for updates when Ryujinx starts when enabled
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> CheckUpdatesOnStart { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification.
|
||||
/// </summary>
|
||||
public ReactiveObject<UpdaterType> UpdateCheckerType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Show "Confirm Exit" Dialog
|
||||
@@ -804,6 +810,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
Hacks = new HacksSection();
|
||||
EnableDiscordIntegration = new ReactiveObject<bool>();
|
||||
CheckUpdatesOnStart = new ReactiveObject<bool>();
|
||||
UpdateCheckerType = new ReactiveObject<UpdaterType>();
|
||||
ShowConfirmExit = new ReactiveObject<bool>();
|
||||
RememberWindowState = new ReactiveObject<bool>();
|
||||
ShowTitleBar = new ReactiveObject<bool>();
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
DockedMode = System.EnableDockedMode,
|
||||
EnableDiscordIntegration = EnableDiscordIntegration,
|
||||
CheckUpdatesOnStart = CheckUpdatesOnStart,
|
||||
UpdateCheckerType = UpdateCheckerType,
|
||||
ShowConfirmExit = ShowConfirmExit,
|
||||
RememberWindowState = RememberWindowState,
|
||||
ShowTitleBar = ShowTitleBar,
|
||||
@@ -175,7 +176,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
System.SystemTimeOffset.Value = 0;
|
||||
System.EnableDockedMode.Value = true;
|
||||
EnableDiscordIntegration.Value = true;
|
||||
CheckUpdatesOnStart.Value = true;
|
||||
UpdateCheckerType.Value = UpdaterType.PromptAtStartup;
|
||||
ShowConfirmExit.Value = true;
|
||||
RememberWindowState.Value = true;
|
||||
ShowTitleBar.Value = !OperatingSystem.IsWindows();
|
||||
|
||||
13
src/Ryujinx/Utilities/Configuration/UI/UpdaterType.cs
Normal file
13
src/Ryujinx/Utilities/Configuration/UI/UpdaterType.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Ryujinx.Ava.Utilities.Configuration.UI
|
||||
{
|
||||
[JsonConverter(typeof(TypedStringEnumConverter<UpdaterType>))]
|
||||
public enum UpdaterType
|
||||
{
|
||||
Off,
|
||||
PromptAtStartup,
|
||||
CheckInBackground
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user