A fork of Eusth's IPA
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.1KB

  1. using Mono.Cecil;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. namespace IPA.Patcher
  8. {
  9. class VirtualizedModule
  10. {
  11. private const string ENTRY_TYPE = "Display";
  12. private FileInfo _File;
  13. private ModuleDefinition _Module;
  14. public static VirtualizedModule Load(string engineFile)
  15. {
  16. return new VirtualizedModule(engineFile);
  17. }
  18. private VirtualizedModule(string assemblyFile)
  19. {
  20. _File = new FileInfo(assemblyFile);
  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. /// <summary>
  34. ///
  35. /// </summary>
  36. /// <param name="module"></param>
  37. public void Virtualize()
  38. {
  39. foreach (var type in _Module.Types)
  40. {
  41. VirtualizeType(type);
  42. }
  43. _Module.Write(_File.FullName);
  44. }
  45. private void VirtualizeType(TypeDefinition type)
  46. {
  47. if(type.IsSealed)
  48. {
  49. // Unseal
  50. type.IsSealed = false;
  51. }
  52. if (type.IsInterface) return;
  53. if (type.IsAbstract) return;
  54. // These two don't seem to work.
  55. if (type.Name == "SceneControl" || type.Name == "ConfigUI") return;
  56. Console.WriteLine("Virtualizing {0}", type.Name);
  57. // Take care of sub types
  58. foreach (var subType in type.NestedTypes)
  59. {
  60. VirtualizeType(subType);
  61. }
  62. foreach (var method in type.Methods)
  63. {
  64. if (method.IsManaged
  65. && method.IsIL
  66. && !method.IsStatic
  67. && !method.IsVirtual
  68. && !method.IsAbstract
  69. && !method.IsAddOn
  70. && !method.IsConstructor
  71. && !method.IsSpecialName
  72. && !method.IsGenericInstance
  73. && !method.HasOverrides)
  74. {
  75. method.IsVirtual = true;
  76. method.IsPublic = true;
  77. method.IsPrivate = false;
  78. method.IsNewSlot = true;
  79. method.IsHideBySig = true;
  80. }
  81. }
  82. foreach (var field in type.Fields)
  83. {
  84. if (field.IsPrivate) field.IsFamily = true;
  85. }
  86. }
  87. public bool IsVirtualized
  88. {
  89. get
  90. {
  91. var awakeMethods = _Module.GetTypes().SelectMany(t => t.Methods.Where(m => m.Name == "Awake"));
  92. if (awakeMethods.Count() == 0) return false;
  93. return ((float)awakeMethods.Count(m => m.IsVirtual) / awakeMethods.Count()) > 0.5f;
  94. }
  95. }
  96. }
  97. }