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.4 KiB

  1. using Mono.Cecil;
  2. using System;
  3. using System.IO;
  4. using System.Linq;
  5. namespace IPA.Patcher
  6. {
  7. class VirtualizedModule
  8. {
  9. private readonly FileInfo _file;
  10. private ModuleDefinition _module;
  11. public static VirtualizedModule Load(string engineFile)
  12. {
  13. return new VirtualizedModule(engineFile);
  14. }
  15. private VirtualizedModule(string assemblyFile)
  16. {
  17. _file = new FileInfo(assemblyFile);
  18. LoadModules();
  19. }
  20. private void LoadModules()
  21. {
  22. var resolver = new DefaultAssemblyResolver();
  23. resolver.AddSearchDirectory(_file.DirectoryName);
  24. var parameters = new ReaderParameters
  25. {
  26. AssemblyResolver = resolver,
  27. };
  28. _module = ModuleDefinition.ReadModule(_file.FullName, parameters);
  29. }
  30. /// <summary>
  31. ///
  32. /// </summary>
  33. public void Virtualize()
  34. {
  35. foreach (var type in _module.Types)
  36. {
  37. VirtualizeType(type);
  38. }
  39. Console.WriteLine();
  40. _module.Write(_file.FullName);
  41. }
  42. private void VirtualizeType(TypeDefinition type)
  43. {
  44. if(type.IsSealed)
  45. {
  46. // Unseal
  47. type.IsSealed = false;
  48. }
  49. if (type.IsInterface) return;
  50. if (type.IsAbstract) return;
  51. // These two don't seem to work.
  52. if (type.Name == "SceneControl" || type.Name == "ConfigUI") return;
  53. //Console.CursorTop--;
  54. Console.CursorLeft = 0;
  55. Program.ClearLine();
  56. Console.Write("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. var methodDefinitions = awakeMethods as MethodDefinition[] ?? awakeMethods.ToArray();
  93. if (!methodDefinitions.Any()) return false;
  94. return ((float)methodDefinitions.Count(m => m.IsVirtual) / methodDefinitions.Count()) > 0.5f;
  95. }
  96. }
  97. }
  98. }