|
|
@ -0,0 +1,115 @@ |
|
|
|
using Mono.Cecil; |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.IO; |
|
|
|
using System.Linq; |
|
|
|
using System.Text; |
|
|
|
|
|
|
|
namespace CollectDependencies |
|
|
|
{ |
|
|
|
class VirtualizedModule |
|
|
|
{ |
|
|
|
private const string ENTRY_TYPE = "Display"; |
|
|
|
|
|
|
|
private FileInfo _File; |
|
|
|
private ModuleDefinition _Module; |
|
|
|
|
|
|
|
public static VirtualizedModule Load(string engineFile) |
|
|
|
{ |
|
|
|
return new VirtualizedModule(engineFile); |
|
|
|
} |
|
|
|
|
|
|
|
private VirtualizedModule(string assemblyFile) |
|
|
|
{ |
|
|
|
_File = new FileInfo(assemblyFile); |
|
|
|
|
|
|
|
LoadModules(); |
|
|
|
} |
|
|
|
|
|
|
|
private void LoadModules() |
|
|
|
{ |
|
|
|
var resolver = new DefaultAssemblyResolver(); |
|
|
|
resolver.AddSearchDirectory(_File.DirectoryName); |
|
|
|
|
|
|
|
var parameters = new ReaderParameters |
|
|
|
{ |
|
|
|
AssemblyResolver = resolver, |
|
|
|
}; |
|
|
|
|
|
|
|
_Module = ModuleDefinition.ReadModule(_File.FullName, parameters); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="module"></param>
|
|
|
|
public void Virtualize(string targetfile) |
|
|
|
{ |
|
|
|
|
|
|
|
foreach (var type in _Module.Types) |
|
|
|
{ |
|
|
|
VirtualizeType(type); |
|
|
|
} |
|
|
|
|
|
|
|
_Module.Write(targetfile); |
|
|
|
} |
|
|
|
|
|
|
|
private void VirtualizeType(TypeDefinition type) |
|
|
|
{ |
|
|
|
if(type.IsSealed) |
|
|
|
{ |
|
|
|
// Unseal
|
|
|
|
type.IsSealed = false; |
|
|
|
} |
|
|
|
|
|
|
|
if (type.IsInterface) return; |
|
|
|
if (type.IsAbstract) return; |
|
|
|
|
|
|
|
// These two don't seem to work.
|
|
|
|
if (type.Name == "SceneControl" || type.Name == "ConfigUI") return; |
|
|
|
|
|
|
|
// Take care of sub types
|
|
|
|
foreach (var subType in type.NestedTypes) |
|
|
|
{ |
|
|
|
VirtualizeType(subType); |
|
|
|
} |
|
|
|
|
|
|
|
foreach (var method in type.Methods) |
|
|
|
{ |
|
|
|
if (method.IsManaged |
|
|
|
&& method.IsIL |
|
|
|
&& !method.IsStatic |
|
|
|
&& !method.IsVirtual |
|
|
|
&& !method.IsAbstract |
|
|
|
&& !method.IsAddOn |
|
|
|
&& !method.IsConstructor |
|
|
|
&& !method.IsSpecialName |
|
|
|
&& !method.IsGenericInstance |
|
|
|
&& !method.HasOverrides) |
|
|
|
{ |
|
|
|
method.IsVirtual = true; |
|
|
|
method.IsPublic = true; |
|
|
|
method.IsPrivate = false; |
|
|
|
method.IsNewSlot = true; |
|
|
|
method.IsHideBySig = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
foreach (var field in type.Fields) |
|
|
|
{ |
|
|
|
if (field.IsPrivate) field.IsFamily = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public bool IsVirtualized |
|
|
|
{ |
|
|
|
get |
|
|
|
{ |
|
|
|
var awakeMethods = _Module.GetTypes().SelectMany(t => t.Methods.Where(m => m.Name == "Awake")); |
|
|
|
if (awakeMethods.Count() == 0) return false; |
|
|
|
|
|
|
|
return ((float)awakeMethods.Count(m => m.IsVirtual) / awakeMethods.Count()) > 0.5f; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |