A fork of Eusth's IPA
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

101 lignes
2.9KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using Mono.Cecil;
  6. using Mono.Cecil.Cil;
  7. namespace IPA.Patcher
  8. {
  9. internal class PatchedModule
  10. {
  11. private static readonly string[] ENTRY_TYPES = { "Input", "Display" };
  12. private FileInfo _File;
  13. private ModuleDefinition _Module;
  14. public static PatchedModule Load(string engineFile)
  15. {
  16. return new PatchedModule(engineFile);
  17. }
  18. private PatchedModule(string engineFile)
  19. {
  20. _File = new FileInfo(engineFile);
  21. LoadModules();
  22. }
  23. private void LoadModules()
  24. {
  25. var resolver = new DefaultAssemblyResolver();
  26. resolver.AddSearchDirectory(_File.DirectoryName);
  27. var parameters = new ReaderParameters
  28. {
  29. AssemblyResolver = resolver,
  30. };
  31. _Module = ModuleDefinition.ReadModule(_File.FullName, parameters);
  32. }
  33. public bool IsPatched
  34. {
  35. get
  36. {
  37. foreach (var @ref in _Module.AssemblyReferences)
  38. {
  39. if (@ref.Name == "IllusionInjector")
  40. return true;
  41. }
  42. return false;
  43. }
  44. }
  45. public void Patch()
  46. {
  47. // First, let's add the reference
  48. var nameReference = new AssemblyNameReference("IllusionInjector", new Version(1, 0, 0, 0));
  49. var injectorPath = Path.Combine(_File.DirectoryName, "IllusionInjector.dll");
  50. var injector = ModuleDefinition.ReadModule(injectorPath);
  51. _Module.AssemblyReferences.Add(nameReference);
  52. int patched = 0;
  53. foreach (var type in FindEntryTypes())
  54. {
  55. if (PatchType(type, injector))
  56. {
  57. patched++;
  58. }
  59. }
  60. if (patched > 0)
  61. {
  62. _Module.Write(_File.FullName);
  63. }
  64. else
  65. {
  66. throw new Exception("Could not find any entry type!");
  67. }
  68. }
  69. private bool PatchType(TypeDefinition targetType, ModuleDefinition injector)
  70. {
  71. var targetMethod = targetType.Methods.FirstOrDefault(m => m.IsConstructor && m.IsStatic);
  72. if (targetMethod != null)
  73. {
  74. var methodReference = _Module.Import(injector.GetType("IllusionInjector.Injector").Methods.First(m => m.Name == "Inject"));
  75. targetMethod.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Call, methodReference));
  76. return true;
  77. }
  78. return false;
  79. }
  80. private IEnumerable<TypeDefinition> FindEntryTypes()
  81. {
  82. return _Module.GetTypes().Where(m => ENTRY_TYPES.Contains(m.Name));
  83. }
  84. }
  85. }