Compare commits

...

2 Commits

Author SHA1 Message Date
GreemDev
e4abc3a960 cleanup 2026-01-04 19:34:32 -06:00
GreemDev
8ccbf33327 Replace CommandLineState with a more user-friendly CLI experience. 2026-01-04 05:18:32 -06:00
13 changed files with 310 additions and 332 deletions

View File

@@ -44,7 +44,7 @@
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.126" />
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.44" />
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.44" />
<PackageVersion Include="Gommon" Version="2.8.0.1" />
<PackageVersion Include="Gommon" Version="2.8.0.4" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="Sep" Version="0.11.1" />
<PackageVersion Include="shaderc.net" Version="0.1.0" />
@@ -59,4 +59,4 @@
<PackageVersion Include="System.Management" Version="9.0.2" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
</ItemGroup>
</Project>
</Project>

View File

@@ -12,6 +12,8 @@ namespace Ryujinx.Common.Logging
{
public static class Logger
{
public static readonly TextWriter WriterProxy = new TextWriterProxy();
private static readonly Stopwatch _time;
private static readonly bool[] _enabledClasses;

View File

@@ -0,0 +1,21 @@
using System;
using System.IO;
using System.Text;
namespace Ryujinx.Common.Logging
{
internal class TextWriterProxy : TextWriter
{
public override Encoding Encoding => Console.OutputEncoding;
public override void Write(string value)
{
if (value is null) return;
foreach (var line in value.Split(Console.Out.NewLine))
{
Logger.Info?.PrintMsg(LogClass.Application, line);
}
}
}
}

View File

@@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Threading;
using CommandLine;
using DiscordRPC;
using Gommon;
using Projektanker.Icons.Avalonia;
@@ -78,28 +79,38 @@ namespace Ryujinx.Ava
}
}
bool noGuiArg = ConsumeCommandLineArgument(ref args, "--no-gui") || ConsumeCommandLineArgument(ref args, "nogui");
bool coreDumpArg = ConsumeCommandLineArgument(ref args, "--core-dumps");
PreviewerDetached = true;
if (ConsumeCommandLineArgument(ref args, "--no-gui")
|| ConsumeCommandLineArgument(ref args, "nogui"))
{
try
{
HeadlessRyujinx.Entrypoint(args);
return 0;
}
catch (Exception e)
{
Logger.Error?.PrintMsg(LogClass.Application, $"Exception occurred when running Headless Ryujinx: {e.Message}\n{e.StackTrace}");
return 1;
}
}
if (!Initialize(args, out RyujinxOptions options))
{
Logger.Flush();
return 1;
}
// TODO: Ryujinx causes core dumps on Linux when it exits "uncleanly", eg. through an unhandled exception.
// This is undesirable and causes very odd behavior during development (the process stops responding,
// the .NET debugger freezes or suddenly detaches, /tmp/ gets filled etc.), unless explicitly requested by the user.
// This needs to be investigated, but calling prctl() is better than modifying system-wide settings or leaving this be.
if (!coreDumpArg)
if (!options.CoreDumpsEnabled)
{
OsUtils.SetCoreDumpable(false);
}
PreviewerDetached = true;
if (noGuiArg)
{
HeadlessRyujinx.Entrypoint(args);
return 0;
}
Initialize(args);
LoggerAdapter.Register();
IconProvider.Current
@@ -137,13 +148,14 @@ namespace Ryujinx.Ava
return found;
}
private static void Initialize(string[] args)
private static Result Initialize(string[] args, out RyujinxOptions options)
{
// Ensure Discord presence timestamp begins at the absolute start of when Ryujinx is launched
DiscordIntegrationModule.EmulatorStartedAt = Timestamps.Now;
// Parse arguments
CommandLineState.ParseArguments(args);
Result res = RyujinxOptions.Read(args, out options);
if (!res) return res;
if (OperatingSystem.IsMacOS())
{
@@ -163,7 +175,7 @@ namespace Ryujinx.Ava
AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit();
// Setup base data directory.
AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
AppDataManager.Initialize(options.EmuDataBaseDirPath);
// Initialize the configuration.
ConfigurationState.Initialize();
@@ -196,10 +208,12 @@ namespace Ryujinx.Ava
}
}
if (CommandLineState.LaunchPathArg != null)
if (options.LaunchPath != null)
{
MainWindow.DeferLoadApplication(CommandLineState.LaunchPathArg, CommandLineState.LaunchApplicationId, CommandLineState.StartFullscreenArg);
MainWindow.DeferLoadApplication(options.LaunchPath, options.LaunchApplicationId, options.StartFullscreen);
}
return Result.Success;
}
public static string GetDirGameUserConfig(string gameId, bool changeFolderForGame = false)
@@ -222,7 +236,6 @@ namespace Ryujinx.Ava
public static void ReloadConfig(bool isRunGameWithCustomConfig = false)
{
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
@@ -273,74 +286,50 @@ namespace Ryujinx.Ava
UseHardwareAcceleration = ConfigurationState.Instance.EnableHardwareAcceleration;
// Check if graphics backend was overridden
if (CommandLineState.OverrideGraphicsBackend is not null)
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = CommandLineState.OverrideGraphicsBackend.ToLower() switch
{
"opengl" => GraphicsBackend.OpenGl,
"vulkan" => GraphicsBackend.Vulkan,
_ => ConfigurationState.Instance.Graphics.GraphicsBackend
};
if (RyujinxOptions.Shared.GraphicsBackendOverride is not null)
ConfigurationState.Instance.Graphics.GraphicsBackend.Value =
RyujinxOptions.Shared.GraphicsBackendOverride.Value;
// Check if backend threading was overridden
if (CommandLineState.OverrideBackendThreading is not null)
ConfigurationState.Instance.Graphics.BackendThreading.Value = CommandLineState.OverrideBackendThreading.ToLower() switch
{
"auto" => BackendThreading.Auto,
"off" => BackendThreading.Off,
"on" => BackendThreading.On,
_ => ConfigurationState.Instance.Graphics.BackendThreading
};
if (RyujinxOptions.Shared.BackendThreadingOverride is not null)
ConfigurationState.Instance.Graphics.BackendThreading.Value =
RyujinxOptions.Shared.BackendThreadingOverride.Value;
if (RyujinxOptions.Shared.BackendThreadingOverrideAfterReboot is not null)
BackendThreadingArg = RyujinxOptions.Shared.BackendThreadingOverrideAfterReboot.Value.ToString();
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;
if (RyujinxOptions.Shared.DockedModeOverride.HasValue)
ConfigurationState.Instance.System.EnableDockedMode.Value =
RyujinxOptions.Shared.DockedModeOverride.Value;
// Check if HideCursor was overridden.
if (CommandLineState.OverrideHideCursor is not null)
ConfigurationState.Instance.HideCursor.Value = CommandLineState.OverrideHideCursor.ToLower() switch
{
"never" => HideCursorMode.Never,
"onidle" => HideCursorMode.OnIdle,
"always" => HideCursorMode.Always,
_ => ConfigurationState.Instance.HideCursor,
};
if (RyujinxOptions.Shared.HideCursorOverride is not null)
ConfigurationState.Instance.HideCursor.Value = RyujinxOptions.Shared.HideCursorOverride.Value;
// 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;
}
if (RyujinxOptions.Shared.MemoryManagerModeOverride is not null)
ConfigurationState.Instance.System.MemoryManagerMode.Value = RyujinxOptions.Shared.MemoryManagerModeOverride.Value;
// Check if PPTC was overridden.
if (CommandLineState.OverridePPTC is not null)
if (Enum.TryParse(CommandLineState.OverridePPTC, true, out bool result))
if (RyujinxOptions.Shared.PptcOverride is not null)
if (Enum.TryParse(RyujinxOptions.Shared.PptcOverride, 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 Region result))
{
ConfigurationState.Instance.System.Region.Value = result;
}
if (RyujinxOptions.Shared.SystemRegionOverride is not null)
ConfigurationState.Instance.System.Region.Value = RyujinxOptions.Shared.SystemRegionOverride.Value;
//Check if language was overridden.
if (CommandLineState.OverrideSystemLanguage is not null)
if (Enum.TryParse(CommandLineState.OverrideSystemLanguage, true, out Language result))
{
ConfigurationState.Instance.System.Language.Value = result;
}
if (RyujinxOptions.Shared.SystemLanguageOverride is not null)
ConfigurationState.Instance.System.Language.Value = RyujinxOptions.Shared.SystemLanguageOverride.Value;
// Check if hardware-acceleration was overridden.
if (CommandLineState.OverrideHardwareAcceleration != null)
UseHardwareAcceleration = CommandLineState.OverrideHardwareAcceleration.Value;
if (RyujinxOptions.Shared.HardwareAccelerationOverride is not null)
UseHardwareAcceleration = RyujinxOptions.Shared.HardwareAccelerationOverride.Value;
}
internal static void PrintSystemInfo()

View File

@@ -181,7 +181,7 @@ namespace Ryujinx.Ava.Systems
if (shouldRestart)
{
List<string> arguments = CommandLineState.Arguments.ToList();
List<string> arguments = RyujinxOptions.Shared.InputArguments.ToList();
string executableDirectory = AppDomain.CurrentDomain.BaseDirectory;
// On macOS we perform the update at relaunch.
@@ -218,7 +218,7 @@ namespace Ryujinx.Ava.Systems
WorkingDirectory = executableDirectory,
};
foreach (string argument in CommandLineState.Arguments)
foreach (string argument in arguments)
{
processStart.ArgumentList.Add(argument);
}

View File

@@ -95,7 +95,7 @@ namespace Ryujinx.Ava
if (result == UserResult.Yes)
{
_ = Process.Start(Environment.ProcessPath!, CommandLineState.Arguments);
_ = Process.Start(Environment.ProcessPath!, RyujinxOptions.Shared.InputArguments);
desktop.Shutdown();
Environment.Exit(0);
}

View File

@@ -255,41 +255,27 @@ namespace Ryujinx.Ava.UI.ViewModels
return amiiboJson;
}
private async Task<AmiiboJson?> ReadLocalJsonFileAsync()
private AmiiboJson? ReadLocalJsonFile()
{
bool isValid = false;
AmiiboJson amiiboJson = new();
try
{
try
if (File.Exists(_amiiboJsonPath))
{
if (File.Exists(_amiiboJsonPath))
{
isValid = TryGetAmiiboJson(await File.ReadAllTextAsync(_amiiboJsonPath), out amiiboJson);
}
}
catch (Exception exception)
{
Logger.Warning?.Print(LogClass.Application, $"Unable to read data from '{_amiiboJsonPath}': {exception}");
isValid = false;
}
if (!isValid)
{
return null;
isValid = TryGetAmiiboJson(File.ReadAllText(_amiiboJsonPath), out amiiboJson);
}
}
catch (Exception exception)
{
if (!isValid)
{
Logger.Error?.Print(LogClass.Application, $"Couldn't get valid amiibo data: {exception}");
Logger.Warning?.Print(LogClass.Application, $"Unable to read data from '{_amiiboJsonPath}': {exception}");
isValid = false;
}
// Neither local file is not valid JSON, close window.
await ShowInfoDialog();
Close();
}
if (!isValid)
{
return null;
}
return amiiboJson;
@@ -299,8 +285,8 @@ namespace Ryujinx.Ava.UI.ViewModels
{
AmiiboJson? amiiboJson;
if (CommandLineState.OnlyLocalAmiibo)
amiiboJson = await ReadLocalJsonFileAsync();
if (RyujinxOptions.Shared.OnlyLocalAmiibo)
amiiboJson = ReadLocalJsonFile();
else
amiiboJson = await GetMostRecentAmiiboListOrDefaultJson();

View File

@@ -139,16 +139,11 @@ namespace Ryujinx.Ava.UI.Windows
Executor.ExecuteBackgroundAsync(async () =>
{
await ShowIntelMacWarningAsync();
if (CommandLineState.FirmwareToInstallPathArg.TryGet(out FilePath fwPath))
if (RyujinxOptions.Shared.FirmwareToInstallPath.TryGet(out FilePath fwPath))
{
if (fwPath is { ExistsAsFile: true, Extension: "xci" or "zip" } || fwPath.ExistsAsDirectory)
{
await Dispatcher.UIThread.InvokeAsync(() =>
ViewModel.HandleFirmwareInstallation(fwPath));
CommandLineState.FirmwareToInstallPathArg = default;
}
else
Logger.Notice.Print(LogClass.UI, "Invalid firmware type provided. Path must be a directory, or a .zip or .xci file.");
await Dispatcher.UIThread.InvokeAsync(() =>
ViewModel.HandleFirmwareInstallation(fwPath));
RyujinxOptions.Shared.FirmwareToInstallPath = default;
}
});
}
@@ -278,7 +273,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.
VirtualFileSystem.FixExtraData(LibHacHorizonManager.RyujinxClient);
AccountManager = new AccountManager(LibHacHorizonManager.RyujinxClient, CommandLineState.Profile);
AccountManager = new AccountManager(LibHacHorizonManager.RyujinxClient, RyujinxOptions.Shared.Profile);
VirtualFileSystem.ReloadKeySet();
@@ -406,7 +401,7 @@ namespace Ryujinx.Ava.UI.Windows
await Dispatcher.UIThread.InvokeAsync(async () => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys));
}
if (!Updater.CanUpdate() || CommandLineState.HideAvailableUpdates)
if (!Updater.CanUpdate() || RyujinxOptions.Shared.HideAvailableUpdates)
return;
switch (ConfigurationState.Instance.UpdateCheckerType.Value)

View File

@@ -1,221 +0,0 @@
using Gommon;
using Ryujinx.Common.Logging;
using System.Collections.Generic;
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 RenderDocCaptureTitleFormat { get; private set; } =
"{EmuVersion}\n{GuestName} {GuestVersion} {GuestTitleId} {GuestArch}";
public static Optional<FilePath> FirmwareToInstallPathArg { get; set; }
public static string Profile { get; private set; }
public static string LaunchPathArg { get; private set; }
public static string LaunchApplicationId { get; private set; }
public static bool StartFullscreenArg { get; private set; }
public static bool HideAvailableUpdates { get; private set; }
public static bool OnlyLocalAmiibo { get; private set; }
public static void ParseArguments(string[] args)
{
List<string> arguments = [];
// Parse Arguments.
for (int i = 0; i < args.Length; ++i)
{
string arg = args[i];
if (arg.Contains('-') || arg.Contains("--"))
{
CountArguments++;
}
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 "-rdct":
case "--rd-capture-title-format":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
RenderDocCaptureTitleFormat = args[++i];
arguments.Add(arg);
arguments.Add(args[i]);
break;
case "--install-firmware":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
FirmwareToInstallPathArg = new FilePath(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;
case "--backend-threading":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
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 "-la":
case "--local-only-amiibo":
OnlyLocalAmiibo = true;
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];
break;
case "--docked-mode":
OverrideDockedMode = true;
break;
case "--handheld-mode":
OverrideDockedMode = false;
break;
case "--hide-cursor":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
OverrideHideCursor = args[++i];
break;
case "--hide-updates":
HideAvailableUpdates = true;
break;
case "--software-gui":
OverrideHardwareAcceleration = false;
break;
default:
LaunchPathArg = arg;
break;
}
}
Arguments = arguments.ToArray();
}
}
}

View File

@@ -0,0 +1,58 @@
using CommandLine;
using Gommon;
using Ryujinx.Common.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using Error = Gommon.Error;
namespace Ryujinx.Ava.Utilities
{
public partial class RyujinxOptions
{
public static RyujinxOptions Shared { get; private set; }
// ReSharper disable once UnusedMethodReturnValue.Global
public static Result Read(string[] args, out RyujinxOptions options)
{
options = null;
args = PatchLegacyArgumentNames(args);
ParserResult<RyujinxOptions> parseResult =
Parser.ParseArguments<RyujinxOptions>(args);
if (parseResult is NotParsed<RyujinxOptions>)
return Result.Fail;
options = Shared = parseResult.Value;
return parseResult.Value.Init(args);
}
private static readonly Lazy<Parser> _parser = new(() => new Parser(settings =>
{
settings.HelpWriter = Logger.WriterProxy;
settings.CaseInsensitiveEnumValues = true;
settings.CaseSensitive = false;
settings.MaximumDisplayWidth -= (int)(settings.MaximumDisplayWidth * 0.175);
}));
public static Parser Parser => _parser.Value;
private static readonly Dictionary<string, string> _legacyArgs = new()
{
{ "-rdct", "--rd-capture-title-format" },
{ "-la", "--local-only-amiibo" }
};
public static string[] PatchLegacyArgumentNames(string[] args)
{
for (int i = 0; i < args.Length; i++)
args[i] = Patch(args[i]);
return args;
string Patch(string arg) => _legacyArgs.TryGetValue(arg, out string newArgName) ? newArgName : arg;
}
}
}

View File

@@ -0,0 +1,148 @@
using Avalonia.Controls;
using CommandLine;
using Gommon;
using Ryujinx.Ava.Systems.Configuration.System;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
namespace Ryujinx.Ava.Utilities
{
public partial class RyujinxOptions
{
public string[] InputArguments { get; private set; }
public bool? DockedModeOverride { get; private set; }
public bool? HardwareAccelerationOverride { get; private set; }
public Optional<FilePath> FirmwareToInstallPath { get; set; }
// Ideally I'd use an enum parse, like --docked-mode=Handheld,
// but I want to maintain backwards compatibility with shortcuts made a long time ago, as best we can.
public Result Init(string[] args)
{
InputArguments = args;
{
// Docked Mode Override
if (DockedMode && HandheldMode)
{
return Result.MessageFailure(
"Cannot be in both docked and handheld mode at the same time; choose only one.");
}
if (DockedMode) DockedModeOverride = true;
if (HandheldMode) DockedModeOverride = false;
}
{
// Hardware Acceleration Override
if (SoftwareGui)
{
HardwareAccelerationOverride = false;
}
}
FirmwareToInstallPath = Optional.Of(FirmwareToInstallPathRaw)
.Convert(x => new FilePath(x))
.OnlyIf(fp =>
{
bool result = fp is { ExistsAsFile: true, Extension: "xci" or "zip" } || fp.ExistsAsDirectory;
if (!result)
{
Logger.Notice.PrintMsg(LogClass.UI,
"Invalid firmware type provided. Path must be a directory, or a .zip or .xci file.");
}
return result;
});
return Result.Success;
}
[Option("docked-mode", Required = false, Default = false,
HelpText = "Launch the game in Docked mode. Causes an error if used in tandem with --handheld-mode.")]
public bool DockedMode { get; set; }
[Option("handheld-mode", Required = false, Default = false,
HelpText = "Launch the game in Handheld mode. Causes an error if used in tandem with --docked-mode.")]
public bool HandheldMode { get; set; }
[Option("software-gui", Required = false, Default = false,
HelpText = "Disables hardware-accelerated rendering for Avalonia. Required for launching with RenderDoc.")]
public bool SoftwareGui { get; set; }
[Option('g', "graphics-backend", Required = false, Default = null,
HelpText = "Select the Graphics backend to use when launching.")]
public GraphicsBackend? GraphicsBackendOverride { get; set; }
[Option("backend-threading", Required = false, Default = null,
HelpText = "Select the Graphics backend threading option to use when launching.")]
public BackendThreading? BackendThreadingOverride { get; set; }
[Option("bt", Required = false, Default = null, Hidden = true)]
public BackendThreading? BackendThreadingOverrideAfterReboot { get; set; }
[Option("pptc", Required = false, Default = null,
HelpText = "Enable/disable PPTC regardless of your settings when launching.")]
public string PptcOverride { get; set; }
[Option('m', "memory-manager-mode", Required = false, Default = null,
HelpText = "Select the memory manager mode to use when launching.")]
public MemoryManagerMode? MemoryManagerModeOverride { get; set; }
[Option("system-region", Required = false, Default = null,
HelpText = "Select the Region to use for the emulated Switch when launching.")]
public Region? SystemRegionOverride { get; set; }
[Option("system-language", Required = false, Default = null,
HelpText = "Select the Language to use for the emulated Switch when launching.")]
public Language? SystemLanguageOverride { get; set; }
[Option("hide-cursor", Required = false, Default = null,
HelpText = "Select the cursor hiding strategy to use when launching.")]
public HideCursorMode? HideCursorOverride { get; set; }
[Option('r', "root-data-dir", Required = false, Default = null,
HelpText = "Select the folder to use for all of your Ryujinx save data, configs, etc.")]
public string EmuDataBaseDirPath { get; set; }
[Option("rd-capture-title-format", Required = false,
HelpText =
"Set the format string used for RenderDoc Capture titles when using the Start/Stop Capture buttons in Ryujinx.",
Default = "{EmuVersion}\n{GuestName} {GuestVersion} {GuestTitleId} {GuestArch}")]
public string RenderDocCaptureTitleFormat { get; set; }
[Option("install-firmware", Required = false, Default = null,
HelpText =
"Specify a file path containing Switch firmware to install immediately after starting. Must be a directory or a .zip or .xci file.")]
public string FirmwareToInstallPathRaw { get; set; }
[Option('p', "profile", Required = false, Default = null,
HelpText = "The profile name to open the application with. Defaults to your last used profile.")]
public string Profile { get; set; }
[Option('i', "application-id", Required = false, Default = null,
HelpText = "Specify which application ID out of the specified content archive path to launch.")]
public string LaunchApplicationId { get; set; }
[Option('f', "fullscreen", Required = false, Default = false,
HelpText = "Start the emulator in fullscreen mode.")]
public bool StartFullscreen { get; set; }
[Option("hide-updates", Required = false, Default = false, HelpText = "Hides update prompt/notification.")]
public bool HideAvailableUpdates { get; set; }
[Option("local-only-amiibo", Required = false, Default = false,
HelpText = "Only use the local Amiibo cache; do not update it even if there is an update.")]
public bool OnlyLocalAmiibo { get; set; }
[Option("core-dumps", Required = false, Default = false,
HelpText = "Enable coredumps on Linux platforms. They are disabled by default.")]
public bool CoreDumpsEnabled { get; set; }
[Value(0, Default = null, Required = false,
HelpText =
"The Nintendo Switch application content archive to launch immediately after starting, if desired.")]
public string LaunchPath { get; set; }
}
}

View File

@@ -126,10 +126,10 @@ namespace Ryujinx.Ava.Utilities
// args are first defined as a list, for easier adjustments in the future
List<string> argsList = [];
if (!string.IsNullOrEmpty(CommandLineState.BaseDirPathArg))
if (!string.IsNullOrEmpty(RyujinxOptions.Shared.EmuDataBaseDirPath))
{
argsList.Add("--root-data-dir");
argsList.Add($"\"{CommandLineState.BaseDirPathArg}\"");
argsList.Add($"\"{RyujinxOptions.Shared.EmuDataBaseDirPath}\"");
}
if (!string.IsNullOrEmpty(config))

View File

@@ -34,7 +34,7 @@ namespace Ryujinx.Ava.Utilities
string titleIdSection = $"({activeProcess.ProgramIdText.ToUpper()})";
string titleArchSection = activeProcess.Is64Bit ? "(64-bit)" : "(32-bit)";
return CommandLineState.RenderDocCaptureTitleFormat
return RyujinxOptions.Shared.RenderDocCaptureTitleFormat
.ReplaceIgnoreCase("{EmuVersion}", applicationVersion)
.ReplaceIgnoreCase("{GuestName}", titleNameSection)
.ReplaceIgnoreCase("{GuestVersion}", titleVersionSection)