Files
2026-10-16 23:33:13 -07:00

65 lines
3.3 KiB
C#

using System.Reflection;
using System.Runtime.Loader;
using Mono.Cecil;
using Mono.Cecil.Cil;
if (args.Length == 3 && args[0] == "--patch-loader")
{
if (Path.GetFullPath(args[1]).Equals(Path.GetFullPath(args[2]), StringComparison.OrdinalIgnoreCase))
throw new ArgumentException("Write a separate loader copy; do not overwrite the source.");
using var assembly = AssemblyDefinition.ReadAssembly(args[1]);
int changes = 0;
foreach (var type in assembly.MainModule.Types)
foreach (var method in type.Methods.Where(m => m.HasBody))
foreach (var instruction in method.Body.Instructions)
if (type.FullName == "BepInEx.Unity.IL2CPP.Il2CppInteropManager" &&
instruction.OpCode == OpCodes.Ldstr && (string)instruction.Operand == "global-metadata.dat")
{
instruction.Operand = "global-metadata.interop.dat";
Console.WriteLine($"Redirected metadata input in {method.Name}");
changes++;
}
if (changes != 1) throw new InvalidOperationException($"Expected one loader metadata reference, found {changes}.");
assembly.Write(args[2]);
Console.WriteLine($"Created loader copy with {changes} metadata path reference(s) changed.");
return;
}
if (args.Length is < 2 or > 5)
{
Console.Error.WriteLine("Usage: AugustInterop <BepInEx-core> <normalized-metadata> [GameAssembly.dll]");
Console.Error.WriteLine(" or: AugustInterop --patch-loader <original-loader.dll> <output-loader.dll>");
Environment.ExitCode = 1;
return;
}
var core = args[0];
AssemblyLoadContext.Default.Resolving += (_, name) =>
{
var path = Path.Combine(core, name.Name + ".dll");
return File.Exists(path) ? AssemblyLoadContext.Default.LoadFromAssemblyPath(path) : null;
};
var library = AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.Combine(core, "LibCpp2IL.dll"));
if (args.Length > 1)
{
var primitives = AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.Combine(core, "AssetRipper.Primitives.dll"));
var versionType = primitives.GetType("AssetRipper.Primitives.UnityVersion")!;
var version = versionType.GetMethod("Parse", new[] { typeof(string) })!.Invoke(null, new object[] { "2020.3.33f1" });
var type = library.GetType("LibCpp2IL.Metadata.Il2CppMetadata")!;
var metadata = type.GetMethod("ReadFrom")!.Invoke(null, new object[] { File.ReadAllBytes(args[1]), version });
Console.WriteLine("Metadata parsed successfully.");
foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public))
if (field.GetValue(metadata) is Array array) Console.WriteLine($"{field.Name}: {array.Length}");
if (args.Length > 2)
{
var registry = library.GetTypes().Single(t => t.Name == "LibCpp2IlBinaryRegistry");
registry.GetMethod("RegisterBuiltInBinarySupport")!.Invoke(null, null);
var main = library.GetType("LibCpp2IL.LibCpp2IlMain")!;
var result = main.GetMethod("LoadFromFile")!.Invoke(null, new[] { (object)args[2], Path.GetFullPath(args[1]), version });
Console.WriteLine($"Binary + metadata initialization: {result}");
if (args.Length > 3 && args[3] == "--literal-find" && args.Length > 4)
LiteralFinder.Run(main, metadata, args[2], args[4]);
else if (args.Length > 3) NativeInspect.Run(main, metadata, args[2], args[3], args.Length > 4 ? args[4] : "");
}
}