Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Command Line Parameter to Override Mods #499

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/Ryujinx.Common/Configuration/AppDataManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public enum LaunchMode
public static string KeysDirPathUser { get; }

public static string LogsDirPath { get; private set; }
public static string[] OverrideMods { get; private set; }

public const string DefaultNandDir = "bis";
public const string DefaultSdcardDir = "sdcard";
Expand All @@ -47,8 +48,9 @@ static AppDataManager()
KeysDirPathUser = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch");
}

public static void Initialize(string baseDirPath)
public static void Initialize(string baseDirPath, string[] commandLineArgMods)
{
OverrideMods = commandLineArgMods;
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

if (appDataPath.Length == 0)
Expand Down
26 changes: 22 additions & 4 deletions src/Ryujinx.HLE/HOS/ModLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ public class ModLoader

private static readonly ModMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());

public readonly struct Mod<T> where T : FileSystemInfo
public struct Mod<T> 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)
{
Expand Down Expand Up @@ -169,15 +169,33 @@ private static void AddModsFromDirectory(ModCache mods, DirectoryInfo dir, ModMe
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.OverrideMods.Length == 0)
{
enabled = modData?.Enabled ?? true;
}
else
{
enabled = AppDataManager.OverrideMods.Contains(modData.Name);
}

mods.RomfsDirs.Add(mod = new Mod<DirectoryInfo>(dir.Name, modDir, enabled));
types.Append('R');
}
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.OverrideMods.Length == 0)
{
enabled = modData?.Enabled ?? true;
}
else
{
enabled = AppDataManager.OverrideMods.Contains(modData.Name);
}

mods.ExefsDirs.Add(mod = new Mod<DirectoryInfo>(dir.Name, modDir, enabled));
types.Append('E');
Expand Down
29 changes: 15 additions & 14 deletions src/Ryujinx/Headless/HeadlessRyujinx.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using CommandLine;
using Gommon;
using Ryujinx.Ava;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
Expand Down Expand Up @@ -84,23 +85,23 @@ public static void Entrypoint(string[] args)
.WithNotParsed(errors =>
{
Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:");

errors.ForEach(err => Logger.Error?.PrintMsg(LogClass.Application, $" - {err.Tag}"));
});
}

public static void ReloadConfig(string customConfigPath = null)
{
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);

string configurationPath = null;

// Now load the configuration as the other subsystems are now registered
if (customConfigPath != null && File.Exists(customConfigPath))
{
configurationPath = customConfigPath;
}
}
else if (File.Exists(localConfigurationPath))
{
configurationPath = localConfigurationPath;
Expand Down Expand Up @@ -147,11 +148,11 @@ static void Load(string[] originalArgs, Options option)
option.InheritMainConfig(originalArgs, ConfigurationState.Instance, out useLastUsedProfile);
}

AppDataManager.Initialize(option.BaseDataDir);
AppDataManager.Initialize(option.BaseDataDir, option.OverrideMods.Split(","));

if (useLastUsedProfile && AccountSaveDataManager.GetLastUsedUser().TryGet(out var profile))
option.UserProfile = profile.Name;

// Check if keys exists.
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
{
Expand All @@ -160,14 +161,14 @@ static void Load(string[] originalArgs, Options option)
Logger.Error?.Print(LogClass.Application, "Keys not found");
}
}

ReloadConfig();

if (option.InheritConfig)
{
option.InheritMainConfigInput(originalArgs, ConfigurationState.Instance);
}

_virtualFileSystem = VirtualFileSystem.CreateInstance();
_libHacHorizonManager = new LibHacHorizonManager();

Expand Down Expand Up @@ -230,17 +231,17 @@ static void Load(string[] originalArgs, Options option)
_enableMouse = option.EnableMouse;



LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
LoadPlayerConfiguration(option.InputProfile3Name, option.InputId3, PlayerIndex.Player3);
LoadPlayerConfiguration(option.InputProfile4Name, option.InputId4, PlayerIndex.Player4);
LoadPlayerConfiguration(option.InputProfile5Name, option.InputId5, PlayerIndex.Player5);
LoadPlayerConfiguration(option.InputProfile6Name, option.InputId6, PlayerIndex.Player6);
LoadPlayerConfiguration(option.InputProfile7Name, option.InputId7, PlayerIndex.Player7);
LoadPlayerConfiguration(option.InputProfile8Name, option.InputId8, PlayerIndex.Player8);
LoadPlayerConfiguration(option.InputProfileHandheldName, option.InputIdHandheld, PlayerIndex.Handheld);

if (_inputConfiguration.Count == 0)
{
return;
Expand Down Expand Up @@ -304,15 +305,15 @@ static void Load(string[] originalArgs, Options option)
_inputManager.Dispose();

return;

void LoadPlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
{
if (index == PlayerIndex.Handheld && _inputConfiguration.Count > 0)
{
Logger.Info?.Print(LogClass.Configuration, "Skipping handheld configuration as there are already other players configured.");
return;
}

InputConfig inputConfig = option.InheritedInputConfigs[index] ?? HandlePlayerConfiguration(inputProfileName, inputId, index);

if (inputConfig != null)
Expand Down
78 changes: 42 additions & 36 deletions src/Ryujinx/Headless/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void InheritMainConfig(string[] originalArgs, ConfigurationState configur

if (NeedsOverride(nameof(EnableKeyboard)))
EnableKeyboard = configurationState.Hid.EnableKeyboard;

if (NeedsOverride(nameof(EnableMouse)))
EnableMouse = configurationState.Hid.EnableMouse;

Expand All @@ -39,40 +39,40 @@ public void InheritMainConfig(string[] originalArgs, ConfigurationState configur

if (NeedsOverride(nameof(DisableFsIntegrityChecks)))
DisableFsIntegrityChecks = configurationState.System.EnableFsIntegrityChecks;

if (NeedsOverride(nameof(FsGlobalAccessLogMode)))
FsGlobalAccessLogMode = configurationState.System.FsGlobalAccessLogMode;

if (NeedsOverride(nameof(VSyncMode)))
VSyncMode = configurationState.Graphics.VSyncMode;

if (NeedsOverride(nameof(CustomVSyncInterval)))
CustomVSyncInterval = configurationState.Graphics.CustomVSyncInterval;

if (NeedsOverride(nameof(DisableShaderCache)))
DisableShaderCache = !configurationState.Graphics.EnableShaderCache;

if (NeedsOverride(nameof(EnableTextureRecompression)))
EnableTextureRecompression = configurationState.Graphics.EnableTextureRecompression;

if (NeedsOverride(nameof(DisableDockedMode)))
DisableDockedMode = !configurationState.System.EnableDockedMode;

if (NeedsOverride(nameof(SystemLanguage)))
SystemLanguage = (SystemLanguage)(int)configurationState.System.Language.Value;

if (NeedsOverride(nameof(SystemRegion)))
SystemRegion = (RegionCode)(int)configurationState.System.Region.Value;

if (NeedsOverride(nameof(SystemTimeZone)))
SystemTimeZone = configurationState.System.TimeZone;

if (NeedsOverride(nameof(SystemTimeOffset)))
SystemTimeOffset = configurationState.System.SystemTimeOffset;

if (NeedsOverride(nameof(MemoryManagerMode)))
MemoryManagerMode = configurationState.System.MemoryManagerMode;

if (NeedsOverride(nameof(AudioVolume)))
AudioVolume = configurationState.System.AudioVolume;

Expand All @@ -81,28 +81,28 @@ public void InheritMainConfig(string[] originalArgs, ConfigurationState configur

if (NeedsOverride(nameof(MultiplayerLanInterfaceId)))
MultiplayerLanInterfaceId = configurationState.Multiplayer.LanInterfaceId;

if (NeedsOverride(nameof(DisableFileLog)))
DisableFileLog = !configurationState.Logger.EnableFileLog;

if (NeedsOverride(nameof(LoggingEnableDebug)))
LoggingEnableDebug = configurationState.Logger.EnableDebug;

if (NeedsOverride(nameof(LoggingDisableStub)))
LoggingDisableStub = !configurationState.Logger.EnableStub;

if (NeedsOverride(nameof(LoggingDisableInfo)))
LoggingDisableInfo = !configurationState.Logger.EnableInfo;

if (NeedsOverride(nameof(LoggingDisableWarning)))
LoggingDisableWarning = !configurationState.Logger.EnableWarn;

if (NeedsOverride(nameof(LoggingDisableError)))
LoggingDisableError = !configurationState.Logger.EnableError;

if (NeedsOverride(nameof(LoggingEnableTrace)))
LoggingEnableTrace = configurationState.Logger.EnableTrace;

if (NeedsOverride(nameof(LoggingDisableGuest)))
LoggingDisableGuest = !configurationState.Logger.EnableGuest;

Expand All @@ -114,45 +114,45 @@ public void InheritMainConfig(string[] originalArgs, ConfigurationState configur

if (NeedsOverride(nameof(ResScale)))
ResScale = configurationState.Graphics.ResScale;

if (NeedsOverride(nameof(MaxAnisotropy)))
MaxAnisotropy = configurationState.Graphics.MaxAnisotropy;

if (NeedsOverride(nameof(AspectRatio)))
AspectRatio = configurationState.Graphics.AspectRatio;

if (NeedsOverride(nameof(BackendThreading)))
BackendThreading = configurationState.Graphics.BackendThreading;

if (NeedsOverride(nameof(DisableMacroHLE)))
DisableMacroHLE = !configurationState.Graphics.EnableMacroHLE;

if (NeedsOverride(nameof(GraphicsShadersDumpPath)))
GraphicsShadersDumpPath = configurationState.Graphics.ShadersDumpPath;

if (NeedsOverride(nameof(GraphicsBackend)))
GraphicsBackend = configurationState.Graphics.GraphicsBackend;

if (NeedsOverride(nameof(AntiAliasing)))
AntiAliasing = configurationState.Graphics.AntiAliasing;

if (NeedsOverride(nameof(ScalingFilter)))
ScalingFilter = configurationState.Graphics.ScalingFilter;

if (NeedsOverride(nameof(ScalingFilterLevel)))
ScalingFilterLevel = configurationState.Graphics.ScalingFilterLevel;

if (NeedsOverride(nameof(DramSize)))
DramSize = configurationState.System.DramSize;

if (NeedsOverride(nameof(IgnoreMissingServices)))
IgnoreMissingServices = configurationState.System.IgnoreMissingServices;

if (NeedsOverride(nameof(IgnoreControllerApplet)))
IgnoreControllerApplet = configurationState.IgnoreApplet;

return;

bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
}

Expand All @@ -179,15 +179,15 @@ public void InheritMainConfigInput(string[] originalArgs, ConfigurationState con
}

return;

bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
}

private static string OptionName(string propertyName) =>
typeof(Options)!.GetProperty(propertyName)!.GetCustomAttribute<OptionAttribute>()!.LongName;

// General

[Option("use-main-config", Required = false, Default = false, HelpText = "Use the settings from what was configured via the UI.")]
public bool InheritConfig { get; set; }

Expand Down Expand Up @@ -410,7 +410,7 @@ private static string OptionName(string propertyName) =>

[Option("ignore-missing-services", Required = false, Default = false, HelpText = "Enable ignoring missing services.")]
public bool IgnoreMissingServices { get; set; }

[Option("ignore-controller-applet", Required = false, Default = false, HelpText = "Enable ignoring the controller applet when your game loses connection to your controller.")]
public bool IgnoreControllerApplet { get; set; }

Expand All @@ -420,5 +420,11 @@ private static string OptionName(string propertyName) =>
public string InputPath { get; set; }

public SafeDictionary<PlayerIndex, InputConfig> InheritedInputConfigs = new();

// Mod

[Option('m', "mod", Required = false, Default = "", HelpText = "Overrides enabled mods with user input (Format: \"mod1\",\"mod2\").")]
public string OverrideMods { get; set; }

}
}
2 changes: 1 addition & 1 deletion src/Ryujinx/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private static void Initialize(string[] args)
AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit();

// Setup base data directory.
AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
AppDataManager.Initialize(CommandLineState.BaseDirPathArg, CommandLineState.OverrideMods);

// Initialize the configuration.
ConfigurationState.Initialize();
Expand Down
Loading
Loading