diff --git a/BepInEx.Core/Utility.cs b/BepInEx.Core/Utility.cs
index 24569b4..a71f731 100644
--- a/BepInEx.Core/Utility.cs
+++ b/BepInEx.Core/Utility.cs
@@ -335,6 +335,20 @@ public static class Utility
return builder.ToString();
}
+ ///
+ /// Get a value of a command line argument
+ ///
+ /// Argument name
+ /// Next argument after the given argument name. If not found, returns null.
+ public static string GetCommandLineArgValue(string arg)
+ {
+ var args = Environment.GetCommandLineArgs();
+ for (var i = 1; i < args.Length; i++)
+ if (args[i] == arg && i + 1 < args.Length)
+ return args[i + 1];
+ return null;
+ }
+
///
/// Try to parse given string as an assembly name
///
diff --git a/BepInEx.IL2CPP/DoorstopEntrypoint.cs b/BepInEx.IL2CPP/DoorstopEntrypoint.cs
index 7d071b7..e05b1aa 100644
--- a/BepInEx.IL2CPP/DoorstopEntrypoint.cs
+++ b/BepInEx.IL2CPP/DoorstopEntrypoint.cs
@@ -23,12 +23,9 @@ internal static class UnityPreloaderRunner
// Cecil 0.11 requires one to manually set up list of trusted assemblies for assembly resolving
AppDomain.CurrentDomain.AddCecilPlatformAssemblies(Paths.ManagedPath);
- Preloader.IL2CPPUnhollowedPath = Path.Combine(Paths.BepInExRootPath, "unhollowed");
-
AppDomain.CurrentDomain.AssemblyResolve += LocalResolve;
AppDomain.CurrentDomain.AssemblyResolve -= DoorstopEntrypoint.ResolveCurrentDirectory;
-
Preloader.Run();
}
diff --git a/BepInEx.IL2CPP/Preloader.cs b/BepInEx.IL2CPP/Preloader.cs
index b01a69b..b551802 100644
--- a/BepInEx.IL2CPP/Preloader.cs
+++ b/BepInEx.IL2CPP/Preloader.cs
@@ -23,7 +23,7 @@ public static class Preloader
#endregion
- public static string IL2CPPUnhollowedPath { get; internal set; }
+ public static string IL2CPPUnhollowedPath => ProxyAssemblyGenerator.IL2CPPUnhollowedPath;
private static PreloaderConsoleListener PreloaderLog { get; set; }
diff --git a/BepInEx.IL2CPP/ProxyAssemblyGenerator.cs b/BepInEx.IL2CPP/ProxyAssemblyGenerator.cs
index fbc0c77..3fa749b 100644
--- a/BepInEx.IL2CPP/ProxyAssemblyGenerator.cs
+++ b/BepInEx.IL2CPP/ProxyAssemblyGenerator.cs
@@ -54,13 +54,40 @@ internal static class ProxyAssemblyGenerator
false,
"If enabled, BepInEx will save dummy assemblies generated by an il2cpp dumper into BepInEx/dummy.");
+ private static readonly ConfigEntry UnhollowedAssembliesPath = ConfigFile.CoreConfig.Bind(
+ "IL2CPP", "UnhollowedAssembliesPath",
+ "{BepInEx}",
+ new StringBuilder()
+ .AppendLine("The path to the folder where unhollowed assemblies are stored.")
+ .AppendLine("Supports the following placeholders:")
+ .AppendLine("{BepInEx} - Path to the BepInEx folder.")
+ .AppendLine("{ProcessName} - Name of the current process")
+ .ToString());
+
private static ManualLogSource Il2cppDumperLogger;
+ private static string unhollowedBasePath;
+
public static string GameAssemblyPath => Path.Combine(Paths.GameRootPath, "GameAssembly.dll");
private static string HashPath => Path.Combine(Preloader.IL2CPPUnhollowedPath, "assembly-hash.txt");
- private static string UnityBaseLibsDirectory => Path.Combine(Paths.BepInExRootPath, "unity-libs");
+ private static string UnhollowedBasePath
+ {
+ get
+ {
+ if (unhollowedBasePath != null)
+ return unhollowedBasePath;
+ var path = Utility.GetCommandLineArgValue("--unhollowed-path") ?? UnhollowedAssembliesPath.Value;
+ unhollowedBasePath = path.Replace("{BepInEx}", Paths.BepInExRootPath)
+ .Replace("{ProcessName}", Paths.ProcessName);
+ return unhollowedBasePath;
+ }
+ }
+
+ private static string UnityBaseLibsDirectory => Path.Combine(UnhollowedBasePath, "unity-libs");
+
+ internal static string IL2CPPUnhollowedPath => Path.Combine(UnhollowedBasePath, "unhollowed");
private static string ComputeHash()
{
@@ -149,8 +176,7 @@ internal static class ProxyAssemblyGenerator
typeof(AppDomainRunner).Assembly.FullName,
typeof(AppDomainRunner).FullName);
- runner.Setup(Paths.ExecutablePath, Preloader.IL2CPPUnhollowedPath, Paths.BepInExRootPath,
- Paths.ManagedPath);
+ runner.Setup(Paths.ExecutablePath, Paths.BepInExRootPath, Paths.ManagedPath);
var ok = runner.GenerateAssemblies(new AppDomainListener(), Preloader.UnityVersion.ToString(3),
ConfigIl2CppDumperType.Value);
@@ -214,10 +240,9 @@ internal static class ProxyAssemblyGenerator
[Serializable]
private class AppDomainRunner : MarshalByRefObject
{
- public void Setup(string executablePath, string unhollowedPath, string bepinPath, string managedPath)
+ public void Setup(string executablePath, string bepinPath, string managedPath)
{
Paths.SetExecutablePath(executablePath, bepinPath, managedPath);
- Preloader.IL2CPPUnhollowedPath = unhollowedPath;
AppDomain.CurrentDomain.AddCecilPlatformAssemblies(Paths.ManagedPath);
AppDomain.CurrentDomain.AddCecilPlatformAssemblies(UnityBaseLibsDirectory);
}
@@ -314,7 +339,11 @@ internal static class ProxyAssemblyGenerator
sourceAssemblies = Cpp2IlApi.MakeDummyDLLs();
- Cpp2IlApi.RunAttributeRestorationForAllAssemblies(null, parallel: LibCpp2IlMain.MetadataVersion >= 29 || LibCpp2IlMain.Binary!.InstructionSet is InstructionSet.X86_32 or InstructionSet.X86_64);
+ Cpp2IlApi.RunAttributeRestorationForAllAssemblies(null,
+ parallel: LibCpp2IlMain.MetadataVersion >= 29 ||
+ LibCpp2IlMain.Binary!.InstructionSet is
+ InstructionSet.X86_32
+ or InstructionSet.X86_64);
Cpp2IlApi.DisposeAndCleanupAll();
}