diff options
Diffstat (limited to 'pkgs/games')
-rw-r--r-- | pkgs/games/build-support/monogame-patcher/patcher.cs | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/pkgs/games/build-support/monogame-patcher/patcher.cs b/pkgs/games/build-support/monogame-patcher/patcher.cs index 16878831..c1502ba1 100644 --- a/pkgs/games/build-support/monogame-patcher/patcher.cs +++ b/pkgs/games/build-support/monogame-patcher/patcher.cs @@ -99,11 +99,70 @@ class FixFileStreams : Command { } } +[Verb("replace-call", HelpText="Replace calls to types.")] +class ReplaceCallCmd : GenericOptions { + [Value(0, Min=2, Max=2, HelpText="Call to replace.")] + public IEnumerable<string> replaceCall { get; set; } + + [Value(2, Required=true, MetaName = "type", HelpText = "Types to patch.")] + public IEnumerable<string> typesToPatch { get; set; } + +}; + +class ReplaceCall : Command { + private string search; + private string replace; + + public ReplaceCall(ReplaceCallCmd options) : base(options) { + this.search = options.replaceCall.ToList()[0]; + this.replace = options.replaceCall.ToList()[1]; + + var filtered = this.module.Types + .Where(p => options.typesToPatch.Contains(p.Name)); + + foreach (var toPatch in filtered) + patch_type(toPatch); + + this.save(); + } + + private void patch_method(MethodDefinition md) { + var il = md.Body.GetILProcessor(); + + var found = md.Body.Instructions + .Where(i => i.OpCode == OpCodes.Call) + .Where(i => i.Operand.ToString() == this.search); + + var ctorType = this.module.AssemblyReferences.Select( + x => new { + // XXX: Don't hardcode UnityEngine.Application! + type = this.module.AssemblyResolver.Resolve(x) + .MainModule.GetType("UnityEngine.Application") + } + ).Where(x => x.type != null).Select(x => x.type).First(); + + var newMethod = ctorType.GetMethods() + .Single(x => x.ToString() == this.replace); + var refMethod = this.module.ImportReference(newMethod); + + foreach (Instruction i in found.ToList()) + il.Replace(i, il.Create(OpCodes.Call, refMethod)); + } + + private void patch_type(TypeDefinition td) { + foreach (var nested in td.NestedTypes) patch_type(nested); + foreach (MethodDefinition md in td.Methods) patch_method(md); + } +} + public class patcher { public static int Main(string[] args) { - Parser.Default.ParseArguments<GenericOptions, FixFileStreamsCmd>(args) - .WithParsed<FixFileStreamsCmd>(opts => new FixFileStreams(opts)); + Parser.Default.ParseArguments< + GenericOptions, FixFileStreamsCmd, ReplaceCallCmd + >(args) + .WithParsed<FixFileStreamsCmd>(opts => new FixFileStreams(opts)) + .WithParsed<ReplaceCallCmd>(opts => new ReplaceCall(opts)); return 0; } } |