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.

120 lines
3.4 KiB

  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. Console.WriteLine();
  44. _Module.Write(_File.FullName);
  45. }
  46. private void VirtualizeType(TypeDefinition type)
  47. {
  48. if(type.IsSealed)
  49. {
  50. // Unseal
  51. type.IsSealed = false;
  52. }
  53. if (type.IsInterface) return;
  54. if (type.IsAbstract) return;
  55. // These two don't seem to work.
  56. if (type.Name == "SceneControl" || type.Name == "ConfigUI") return;
  57. //Console.CursorTop--;
  58. Console.CursorLeft = 0;
  59. Program.ClearLine();
  60. Console.Write("Virtualizing {0}", type.Name);
  61. // Take care of sub types
  62. foreach (var subType in type.NestedTypes)
  63. {
  64. VirtualizeType(subType);
  65. }
  66. foreach (var method in type.Methods)
  67. {
  68. if (method.IsManaged
  69. && method.IsIL
  70. && !method.IsStatic
  71. && !method.IsVirtual
  72. && !method.IsAbstract
  73. && !method.IsAddOn
  74. && !method.IsConstructor
  75. && !method.IsSpecialName
  76. && !method.IsGenericInstance
  77. && !method.HasOverrides)
  78. {
  79. method.IsVirtual = true;
  80. method.IsPublic = true;
  81. method.IsPrivate = false;
  82. method.IsNewSlot = true;
  83. method.IsHideBySig = true;
  84. }
  85. }
  86. foreach (var field in type.Fields)
  87. {
  88. if (field.IsPrivate) field.IsFamily = true;
  89. }
  90. }
  91. public bool IsVirtualized
  92. {
  93. get
  94. {
  95. var awakeMethods = _Module.GetTypes().SelectMany(t => t.Methods.Where(m => m.Name == "Awake"));
  96. if (awakeMethods.Count() == 0) return false;
  97. return ((float)awakeMethods.Count(m => m.IsVirtual) / awakeMethods.Count()) > 0.5f;
  98. }
  99. }
  100. }
  101. }