UI: Allow overriding graphics backend + Move command line parser into a new class (#3707)

* Ava: Keep command line args when restarting

* UI: Move common UI functions to ProgramHelper

Add command line option to override the configured graphics backend

* Ava: Add CleanupUpdate task back

* Remove unused usings

* Revert combining common UI functions

Rename ProgramHelper to CommandLineState
Move command line parsing to CommandLineState

* Rename CommandLineProfile to Profile

* Fix assigning the wrong array to Arguments
This commit is contained in:
TSRBerry 2022-11-13 00:36:36 +01:00 committed by GitHub
parent 9daf029f35
commit eebc39228d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 137 additions and 111 deletions

View file

@ -10,6 +10,7 @@ using Ryujinx.Ava.Ui.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@ -64,8 +65,7 @@ namespace Ryujinx.Ava
if (result == UserResult.Yes) if (result == UserResult.Yes)
{ {
var path = Process.GetCurrentProcess().MainModule.FileName; var path = Process.GetCurrentProcess().MainModule.FileName;
var info = new ProcessStartInfo() { FileName = path, UseShellExecute = false }; var proc = Process.Start(path, CommandLineState.Arguments);
var proc = Process.Start(info);
desktop.Shutdown(); desktop.Shutdown();
Environment.Exit(0); Environment.Exit(0);
} }

View file

@ -13,6 +13,7 @@ using Ryujinx.Common.SystemInfo;
using Ryujinx.Modules; using Ryujinx.Modules;
using Ryujinx.Ui.Common; using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;
using System; using System;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -26,7 +27,6 @@ namespace Ryujinx.Ava
public static double ActualScaleFactor { get; set; } public static double ActualScaleFactor { get; set; }
public static string Version { get; private set; } public static string Version { get; private set; }
public static string ConfigurationPath { get; private set; } public static string ConfigurationPath { get; private set; }
public static string CommandLineProfile { get; set; }
public static bool PreviewerDetached { get; private set; } public static bool PreviewerDetached { get; private set; }
public static RenderTimer RenderTimer { get; private set; } public static RenderTimer RenderTimer { get; private set; }
@ -87,46 +87,8 @@ namespace Ryujinx.Ava
private static void Initialize(string[] args) private static void Initialize(string[] args)
{ {
// Parse Arguments. // Parse arguments
string launchPathArg = null; CommandLineState.ParseArguments(args);
string baseDirPathArg = null;
bool startFullscreenArg = false;
for (int i = 0; i < args.Length; ++i)
{
string arg = args[i];
if (arg == "-r" || arg == "--root-data-dir")
{
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
baseDirPathArg = args[++i];
}
else if (arg == "-p" || arg == "--profile")
{
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
CommandLineProfile = args[++i];
}
else if (arg == "-f" || arg == "--fullscreen")
{
startFullscreenArg = true;
}
else
{
launchPathArg = arg;
}
}
// Delete backup files after updating. // Delete backup files after updating.
Task.Run(Updater.CleanupUpdate); Task.Run(Updater.CleanupUpdate);
@ -138,7 +100,7 @@ namespace Ryujinx.Ava
AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => Exit(); AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => Exit();
// Setup base data directory. // Setup base data directory.
AppDataManager.Initialize(baseDirPathArg); AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
// Initialize the configuration. // Initialize the configuration.
ConfigurationState.Initialize(); ConfigurationState.Initialize();
@ -173,9 +135,9 @@ namespace Ryujinx.Ava
} }
} }
if (launchPathArg != null) if (CommandLineState.LaunchPathArg != null)
{ {
MainWindow.DeferLoadApplication(launchPathArg, startFullscreenArg); MainWindow.DeferLoadApplication(CommandLineState.LaunchPathArg, CommandLineState.StartFullscreenArg);
} }
} }
@ -215,6 +177,19 @@ namespace Ryujinx.Ava
Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location {ConfigurationPath}"); Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location {ConfigurationPath}");
} }
} }
// Check if graphics backend was overridden
if (CommandLineState.OverrideGraphicsBackend != null)
{
if (CommandLineState.OverrideGraphicsBackend.ToLower() == "opengl")
{
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl;
}
else if (CommandLineState.OverrideGraphicsBackend.ToLower() == "vulkan")
{
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.Vulkan;
}
}
} }
private static void PrintSystemInfo() private static void PrintSystemInfo()

View file

@ -21,14 +21,10 @@ using Ryujinx.HLE.HOS.Services.Time.TimeZone;
using Ryujinx.Input; using Ryujinx.Input;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Configuration.System; using Ryujinx.Ui.Common.Configuration.System;
using Silk.NET.Vulkan;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using TimeZone = Ryujinx.Ava.Ui.Models.TimeZone; using TimeZone = Ryujinx.Ava.Ui.Models.TimeZone;
namespace Ryujinx.Ava.Ui.ViewModels namespace Ryujinx.Ava.Ui.ViewModels

View file

@ -23,6 +23,7 @@ using Ryujinx.Modules;
using Ryujinx.Ui.App.Common; using Ryujinx.Ui.App.Common;
using Ryujinx.Ui.Common; using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using System; using System;
using System.ComponentModel; using System.ComponentModel;
@ -432,7 +433,7 @@ namespace Ryujinx.Ava.Ui.Windows
// Consider removing this at some point in the future when we don't need to worry about old saves. // Consider removing this at some point in the future when we don't need to worry about old saves.
VirtualFileSystem.FixExtraData(LibHacHorizonManager.RyujinxClient); VirtualFileSystem.FixExtraData(LibHacHorizonManager.RyujinxClient);
AccountManager = new AccountManager(LibHacHorizonManager.RyujinxClient, Program.CommandLineProfile); AccountManager = new AccountManager(LibHacHorizonManager.RyujinxClient, CommandLineState.Profile);
VirtualFileSystem.ReloadKeySet(); VirtualFileSystem.ReloadKeySet();

View file

@ -0,0 +1,81 @@
using Ryujinx.Common.Logging;
using System.Collections.Generic;
namespace Ryujinx.Ui.Common.Helper
{
public static class CommandLineState
{
public static string[] Arguments { get; private set; }
public static string OverrideGraphicsBackend { get; private set; }
public static string BaseDirPathArg { get; private set; }
public static string Profile { get; private set; }
public static string LaunchPathArg { get; private set; }
public static bool StartFullscreenArg { get; private set; }
public static void ParseArguments(string[] args)
{
List<string> arguments = new();
// Parse Arguments.
for (int i = 0; i < args.Length; ++i)
{
string arg = args[i];
switch (arg)
{
case "-r":
case "--root-data-dir":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
BaseDirPathArg = args[++i];
arguments.Add(arg);
arguments.Add(args[i]);
break;
case "-p":
case "--profile":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
Profile = args[++i];
arguments.Add(arg);
arguments.Add(args[i]);
break;
case "-f":
case "--fullscreen":
StartFullscreenArg = true;
arguments.Add(arg);
break;
case "-g":
case "--graphics-backend":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
OverrideGraphicsBackend = args[++i];
break;
default:
LaunchPathArg = arg;
break;
}
}
Arguments = arguments.ToArray();
}
}
}

View file

@ -2,9 +2,9 @@ using Gdk;
using Gtk; using Gtk;
using Ryujinx.Ui; using Ryujinx.Ui;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Reflection; using System.Reflection;
namespace Ryujinx.Modules namespace Ryujinx.Modules
@ -48,9 +48,8 @@ namespace Ryujinx.Modules
{ {
string ryuName = OperatingSystem.IsWindows() ? "Ryujinx.exe" : "Ryujinx"; string ryuName = OperatingSystem.IsWindows() ? "Ryujinx.exe" : "Ryujinx";
string ryuExe = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ryuName); string ryuExe = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ryuName);
var ryuArg = Environment.GetCommandLineArgs().AsEnumerable().Skip(1);
Process.Start(ryuExe, ryuArg); Process.Start(ryuExe, CommandLineState.Arguments);
Environment.Exit(0); Environment.Exit(0);
} }

View file

@ -6,10 +6,11 @@ using Ryujinx.Common.GraphicsDriver;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.System; using Ryujinx.Common.System;
using Ryujinx.Common.SystemInfo; using Ryujinx.Common.SystemInfo;
using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Modules; using Ryujinx.Modules;
using Ryujinx.Ui; using Ryujinx.Ui;
using Ryujinx.Ui.Common; using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;
using Ryujinx.Ui.Widgets; using Ryujinx.Ui.Widgets;
using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Jpeg;
using System; using System;
@ -28,8 +29,6 @@ namespace Ryujinx
public static string ConfigurationPath { get; set; } public static string ConfigurationPath { get; set; }
public static string CommandLineProfile { get; set; }
[DllImport("libX11")] [DllImport("libX11")]
private extern static int XInitThreads(); private extern static int XInitThreads();
@ -47,46 +46,13 @@ namespace Ryujinx
MessageBoxA(IntPtr.Zero, "You are running an outdated version of Windows.\n\nStarting on June 1st 2022, Ryujinx will only support Windows 10 1803 and newer.\n", $"Ryujinx {Version}", MB_ICONWARNING); MessageBoxA(IntPtr.Zero, "You are running an outdated version of Windows.\n\nStarting on June 1st 2022, Ryujinx will only support Windows 10 1803 and newer.\n", $"Ryujinx {Version}", MB_ICONWARNING);
} }
// Parse Arguments. // Parse arguments
string launchPathArg = null; CommandLineState.ParseArguments(args);
string baseDirPathArg = null;
bool startFullscreenArg = false;
for (int i = 0; i < args.Length; ++i) // Hook unhandled exception and process exit events.
{ GLib.ExceptionManager.UnhandledException += (GLib.UnhandledExceptionArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
string arg = args[i]; AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => Exit();
if (arg == "-r" || arg == "--root-data-dir")
{
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
baseDirPathArg = args[++i];
}
else if (arg == "-p" || arg == "--profile")
{
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
CommandLineProfile = args[++i];
}
else if (arg == "-f" || arg == "--fullscreen")
{
startFullscreenArg = true;
}
else if (launchPathArg == null)
{
launchPathArg = arg;
}
}
// Make process DPI aware for proper window sizing on high-res screens. // Make process DPI aware for proper window sizing on high-res screens.
ForceDpiAware.Windows(); ForceDpiAware.Windows();
@ -95,8 +61,6 @@ namespace Ryujinx
// Delete backup files after updating. // Delete backup files after updating.
Task.Run(Updater.CleanupUpdate); Task.Run(Updater.CleanupUpdate);
Console.Title = $"Ryujinx Console {Version}";
// NOTE: GTK3 doesn't init X11 in a multi threaded way. // NOTE: GTK3 doesn't init X11 in a multi threaded way.
// This ends up causing race condition and abort of XCB when a context is created by SPB (even if SPB do call XInitThreads). // This ends up causing race condition and abort of XCB when a context is created by SPB (even if SPB do call XInitThreads).
if (OperatingSystem.IsLinux()) if (OperatingSystem.IsLinux())
@ -107,13 +71,8 @@ namespace Ryujinx
string systemPath = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine); string systemPath = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
Environment.SetEnvironmentVariable("Path", $"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")};{systemPath}"); Environment.SetEnvironmentVariable("Path", $"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")};{systemPath}");
// Hook unhandled exception and process exit events.
GLib.ExceptionManager.UnhandledException += (GLib.UnhandledExceptionArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => Exit();
// Setup base data directory. // Setup base data directory.
AppDataManager.Initialize(baseDirPathArg); AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
// Initialize the configuration. // Initialize the configuration.
ConfigurationState.Initialize(); ConfigurationState.Initialize();
@ -173,6 +132,21 @@ namespace Ryujinx
} }
} }
// Check if graphics backend was overridden
if (CommandLineState.OverrideGraphicsBackend != null)
{
if (CommandLineState.OverrideGraphicsBackend.ToLower() == "opengl")
{
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl;
showVulkanPrompt = false;
}
else if (CommandLineState.OverrideGraphicsBackend.ToLower() == "vulkan")
{
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.Vulkan;
showVulkanPrompt = false;
}
}
// Logging system information. // Logging system information.
PrintSystemInfo(); PrintSystemInfo();
@ -195,9 +169,9 @@ namespace Ryujinx
MainWindow mainWindow = new MainWindow(); MainWindow mainWindow = new MainWindow();
mainWindow.Show(); mainWindow.Show();
if (launchPathArg != null) if (CommandLineState.LaunchPathArg != null)
{ {
mainWindow.LoadApplication(launchPathArg, startFullscreenArg); mainWindow.LoadApplication(CommandLineState.LaunchPathArg, CommandLineState.StartFullscreenArg);
} }
if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false)) if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false))

View file

@ -179,7 +179,7 @@ namespace Ryujinx.Ui
VirtualFileSystem.FixExtraData(_libHacHorizonManager.RyujinxClient); VirtualFileSystem.FixExtraData(_libHacHorizonManager.RyujinxClient);
_contentManager = new ContentManager(_virtualFileSystem); _contentManager = new ContentManager(_virtualFileSystem);
_accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, Program.CommandLineProfile); _accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, CommandLineState.Profile);
_userChannelPersistence = new UserChannelPersistence(); _userChannelPersistence = new UserChannelPersistence();
// Instantiate GUI objects. // Instantiate GUI objects.