From ae364d1436e4428bfcd6d102cf3bf1b1127ddc21 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 6 Jan 2025 02:30:33 +0100 Subject: [PATCH] added command line argument to specify which mods the game should start with, not implemented in headless --- .../Configuration/AppDataManager.cs | 4 ++- src/Ryujinx.HLE/HOS/ModLoader.cs | 26 +++++++++++--- src/Ryujinx/Headless/HeadlessRyujinx.cs | 2 +- src/Ryujinx/Program.cs | 2 +- src/Ryujinx/Utilities/CommandLineState.cs | 36 +++++++++++++++++++ 5 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/Ryujinx.Common/Configuration/AppDataManager.cs b/src/Ryujinx.Common/Configuration/AppDataManager.cs index ca8e389ba..08ce0c5f8 100644 --- a/src/Ryujinx.Common/Configuration/AppDataManager.cs +++ b/src/Ryujinx.Common/Configuration/AppDataManager.cs @@ -32,6 +32,7 @@ namespace Ryujinx.Common.Configuration public static string KeysDirPathUser { get; } public static string LogsDirPath { get; private set; } + public static string[] CommandLineArgMods { get; private set; } public const string DefaultNandDir = "bis"; public const string DefaultSdcardDir = "sdcard"; @@ -47,8 +48,9 @@ namespace Ryujinx.Common.Configuration KeysDirPathUser = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch"); } - public static void Initialize(string baseDirPath) + public static void Initialize(string baseDirPath, string[] commandLineArgMods) { + CommandLineArgMods = commandLineArgMods; string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); if (appDataPath.Length == 0) diff --git a/src/Ryujinx.HLE/HOS/ModLoader.cs b/src/Ryujinx.HLE/HOS/ModLoader.cs index 4bd695ae5..ee1c21db3 100644 --- a/src/Ryujinx.HLE/HOS/ModLoader.cs +++ b/src/Ryujinx.HLE/HOS/ModLoader.cs @@ -41,11 +41,11 @@ namespace Ryujinx.HLE.HOS private static readonly ModMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); - public readonly struct Mod where T : FileSystemInfo + public struct Mod where T : FileSystemInfo { public readonly string Name; public readonly T Path; - public readonly bool Enabled; + public bool Enabled; public Mod(string name, T path, bool enabled) { @@ -169,7 +169,16 @@ namespace Ryujinx.HLE.HOS if (StrEquals(RomfsDir, modDir.Name)) { var modData = modMetadata.Mods.FirstOrDefault(x => modDir.FullName.Contains(x.Path)); - var enabled = modData?.Enabled ?? true; + + bool enabled; + if (AppDataManager.CommandLineArgMods.Length == 0) + { + enabled = modData?.Enabled ?? true; + } + else + { + enabled = AppDataManager.CommandLineArgMods.Contains(modData.Name); + } mods.RomfsDirs.Add(mod = new Mod(dir.Name, modDir, enabled)); types.Append('R'); @@ -177,7 +186,16 @@ namespace Ryujinx.HLE.HOS else if (StrEquals(ExefsDir, modDir.Name)) { var modData = modMetadata.Mods.FirstOrDefault(x => modDir.FullName.Contains(x.Path)); - var enabled = modData?.Enabled ?? true; + + bool enabled; + if (AppDataManager.CommandLineArgMods.Length == 0) + { + enabled = modData?.Enabled ?? true; + } + else + { + enabled = AppDataManager.CommandLineArgMods.Contains(modData.Name); + } mods.ExefsDirs.Add(mod = new Mod(dir.Name, modDir, enabled)); types.Append('E'); diff --git a/src/Ryujinx/Headless/HeadlessRyujinx.cs b/src/Ryujinx/Headless/HeadlessRyujinx.cs index 5730254f7..243ab547a 100644 --- a/src/Ryujinx/Headless/HeadlessRyujinx.cs +++ b/src/Ryujinx/Headless/HeadlessRyujinx.cs @@ -147,7 +147,7 @@ namespace Ryujinx.Headless option.InheritMainConfig(originalArgs, ConfigurationState.Instance, out useLastUsedProfile); } - AppDataManager.Initialize(option.BaseDataDir); + AppDataManager.Initialize(option.BaseDataDir, []); if (useLastUsedProfile && AccountSaveDataManager.GetLastUsedUser().TryGet(out var profile)) option.UserProfile = profile.Name; diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 6f0f3e12e..279a469fa 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -114,7 +114,7 @@ namespace Ryujinx.Ava AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit(); // Setup base data directory. - AppDataManager.Initialize(CommandLineState.BaseDirPathArg); + AppDataManager.Initialize(CommandLineState.BaseDirPathArg, CommandLineState.Mods); // Initialize the configuration. ConfigurationState.Initialize(); diff --git a/src/Ryujinx/Utilities/CommandLineState.cs b/src/Ryujinx/Utilities/CommandLineState.cs index 6fb8e92d6..5905f6081 100644 --- a/src/Ryujinx/Utilities/CommandLineState.cs +++ b/src/Ryujinx/Utilities/CommandLineState.cs @@ -6,6 +6,7 @@ namespace Ryujinx.Ava.Utilities public static class CommandLineState { public static string[] Arguments { get; private set; } + public static string[] Mods { get; private set; } public static bool? OverrideDockedMode { get; private set; } public static bool? OverrideHardwareAcceleration { get; private set; } @@ -21,6 +22,7 @@ namespace Ryujinx.Ava.Utilities public static void ParseArguments(string[] args) { List arguments = new(); + List mods = new(); // Parse Arguments. for (int i = 0; i < args.Length; ++i) @@ -78,6 +80,39 @@ namespace Ryujinx.Ava.Utilities case "--application-id": LaunchApplicationId = args[++i]; break; + case "-m": + case "--mod": + int numMods; + if (i + 1 >= args.Length) + { + Logger.Error?.Print(LogClass.Application, $"Argument '{arg}' expects a number of mods as next argument"); + + continue; + } + if (!int.TryParse(args[++i], out numMods)) + { + i--; + Logger.Error?.Print(LogClass.Application, $"Expected number of mods, got '{arg}'"); + + continue; + } + + if (i + numMods >= args.Length) + { + Logger.Error?.Print(LogClass.Application, $"The number of expected mods exceeds the number of command line arguments left"); + + continue; + } + + for (int j = i + 1; j <= i + numMods; j++) + { + mods.Add(args[j]); + + Logger.Info?.Print(LogClass.Application, $"Enabled mod '{args[j]}' through cli"); + } + + i += numMods; + break; case "--docked-mode": OverrideDockedMode = true; break; @@ -107,6 +142,7 @@ namespace Ryujinx.Ava.Utilities } Arguments = arguments.ToArray(); + Mods = mods.ToArray(); } } }