123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using Mono.Cecil;
- using Mono.Cecil.Cil;
- namespace COM3D2.CacheEditMenu.Patcher
- {
- public static class Patcher
- {
- public static readonly string[] TargetAssemblyNames = { "Assembly-CSharp.dll" };
- public static readonly string SybarisPath = Path.GetDirectoryName(typeof(Patcher).Assembly.Location);
- private static void PatchHelper(MethodDefinition target, MethodReference prefix, MethodReference postix, params int[] ldargs)
- {
- var il = target.Body.GetILProcessor();
- var resultVar = target.ReturnType.FullName != "System.Void" ? new VariableDefinition(target.Module.ImportReference(target.ReturnType)) : null;
- if(resultVar != null)
- target.Body.Variables.Add(resultVar);
-
- var ins = target.Body.Instructions[0];
- if(resultVar != null)
- il.InsertBefore(ins, il.Create(OpCodes.Ldloca, resultVar));
- foreach (var ldarg in ldargs)
- il.InsertBefore(ins, il.Create(OpCodes.Ldarg, ldarg));
- il.InsertBefore(ins, il.Create(OpCodes.Call, target.Module.ImportReference(prefix)));
- il.InsertBefore(ins, il.Create(OpCodes.Brtrue, ins));
- if(resultVar != null)
- il.InsertBefore(ins, il.Create(OpCodes.Ldloc, resultVar));
- il.InsertBefore(ins, il.Create(OpCodes.Ret));
- if (postix == null)
- return;
- ins = il.Create(OpCodes.Nop);
- foreach (var bodyInstruction in target.Body.Instructions.Where(bodyInstruction => bodyInstruction.OpCode == OpCodes.Ret).Skip(1))
- {
- bodyInstruction.OpCode = OpCodes.Br;
- bodyInstruction.Operand = ins;
- }
- il.Append(ins);
- ins = il.Create(OpCodes.Ret);
- il.Append(ins);
- foreach (var ldarg in ldargs)
- il.InsertBefore(ins, il.Create(OpCodes.Ldarg, ldarg));
- il.InsertBefore(ins, il.Create(OpCodes.Call, target.Module.ImportReference(postix)));
- }
- public static void Patch(AssemblyDefinition ad)
- {
- var hookAd = AssemblyDefinition.ReadAssembly(
- typeof(Patcher).Assembly.GetManifestResourceStream(
- "COM3D2.CacheEditMenu.Patcher.COM3D2.CacheEditMenu.dll"));
- var sceneEdit = ad.MainModule.GetType("SceneEdit");
- var getMenuItemSetUp = sceneEdit.Methods.FirstOrDefault(m => m.Name == "GetMenuItemSetUP");
- var initMenuItemScript = sceneEdit.Methods.FirstOrDefault(m => m.Name == "InitMenuItemScript");
- // var importCm = ad.MainModule.GetType("ImportCM");
- // var createTexture = importCm.Methods.FirstOrDefault(m => m.Name == "CreateTexture" && m.Parameters.Count == 1);
- var hookType = hookAd.MainModule.GetType("COM3D2.CacheEditMenu.Hooks");
- var getMenuItemSetUpPrefix = hookType.Methods.FirstOrDefault(m => m.Name == "Prefix");
- var getMenuItemSetUpPostfix = hookType.Methods.FirstOrDefault(m => m.Name == "Postfix");
- var createTexturePrefix = hookType.Methods.FirstOrDefault(m => m.Name == "CreateTexturePrefix");
- PatchHelper(getMenuItemSetUp, getMenuItemSetUpPrefix, getMenuItemSetUpPostfix, 0, 1);
- var il = initMenuItemScript.Body.GetILProcessor();
- foreach (var ins in il.Body.Instructions.ToList())
- {
- if (ins.OpCode == OpCodes.Call &&
- ((MethodReference)ins.Operand).Name == "CreateTexture")
- il.InsertBefore(ins, il.Create(OpCodes.Call, ad.MainModule.ImportReference(createTexturePrefix)));
- }
- var buffer = new byte[4096];
- using(var s = typeof(Patcher).Assembly.GetManifestResourceStream(
- "COM3D2.CacheEditMenu.Patcher.COM3D2.CacheEditMenu.dll"))
- using (var ms = new MemoryStream())
- {
- int read;
- while ((read = s.Read(buffer, 0, buffer.Length)) > 0)
- ms.Write(buffer, 0, read);
- Assembly.Load(ms.ToArray());
- }
- }
- }
- }
|