12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- 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 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);
- PatchHelper(createTexture, createTexturePrefix, null, 0);
- 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());
- }
- }
- }
- }
|