about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--pkgs/games/build-support/monogame-patcher/default.nix22
-rw-r--r--pkgs/games/build-support/monogame-patcher/src/patcher.cs62
-rw-r--r--pkgs/games/build-support/monogame-patcher/src/patcher.csproj8
-rw-r--r--pkgs/games/build-support/monogame-patcher/src/test.sh78
-rw-r--r--pkgs/games/build-support/monogame-patcher/src/tests.cs10
5 files changed, 113 insertions, 67 deletions
diff --git a/pkgs/games/build-support/monogame-patcher/default.nix b/pkgs/games/build-support/monogame-patcher/default.nix
index 457d124a..bd7b8c9c 100644
--- a/pkgs/games/build-support/monogame-patcher/default.nix
+++ b/pkgs/games/build-support/monogame-patcher/default.nix
@@ -20,26 +20,8 @@ buildDotnetPackage {
       sha256 = "0wf8mzr16d2ni008m60rrk738v8ypk74llk6g8mlyx7rrlchnxaf";
       outputFiles = [ "lib/net45/*" ];
     })
-
-    (fetchNuGet {
-      baseName = "NUnit";
-      version = "3.10.1";
-      sha256 = "159m1wpb9yy2x77x7nl0647jkpzj5j801a2inhdl7hcjys8xrqxi";
-      outputFiles = [ "lib/net45/*" ];
-    })
-
-    (fetchNuGet {
-      baseName = "NUnit.ConsoleRunner";
-      version = "3.8.0";
-      sha256 = "1gspqzfhvpc8yapni7zcr5h2y025swihv78cw07v048l3myf3pzk";
-      outputFiles = [ "tools/*" ];
-    })
   ];
 
-  doCheck = true;
-  checkPhase = ''
-    nunitLibs="$(pkg-config nunit.framework --variable=Libraries)"
-    MONO_PATH="$(dirname "$nunitLibs")" HOME="$PWD" \
-      nunit3-console bin/Release/monogame-patcher.exe
-  '';
+  doInstallCheck = true;
+  installCheckPhase = "$SHELL -e test.sh";
 }
diff --git a/pkgs/games/build-support/monogame-patcher/src/patcher.cs b/pkgs/games/build-support/monogame-patcher/src/patcher.cs
index 794db98e..c9046f0a 100644
--- a/pkgs/games/build-support/monogame-patcher/src/patcher.cs
+++ b/pkgs/games/build-support/monogame-patcher/src/patcher.cs
@@ -27,6 +27,24 @@ class Command {
         this.module = ModuleDefinition.ReadModule(this.infile, rp);
     }
 
+    protected MethodReference find_method_ref(string fullSig) {
+        foreach (var aref in this.module.AssemblyReferences) {
+            var resolved = this.module.AssemblyResolver.Resolve(aref);
+            foreach (var type in resolved.MainModule.Types) {
+                foreach (var ctor in type.GetConstructors()) {
+                    if (ctor.ToString() != fullSig) continue;
+                    return this.module.ImportReference(ctor);
+                }
+                foreach (var meth in type.GetMethods()) {
+                    if (meth.ToString() != fullSig) continue;
+                    return this.module.ImportReference(meth);
+                }
+            }
+        }
+
+        throw new Exception($"Method reference for {fullSig} not found.");
+    }
+
     public void save() {
         if (this.outfile == this.infile)
             this.module.Write();
@@ -36,10 +54,17 @@ class Command {
 }
 
 class FixFileStreams : Command {
+    private MethodReference betterFileStream;
+
     public FixFileStreams(FixFileStreamsCmd options) : base(options) {
         var filtered = this.module.Types
             .Where(p => options.typesToPatch.Contains(p.Name));
 
+        this.betterFileStream = this.find_method_ref(
+            "System.Void System.IO.FileStream::.ctor" +
+            "(System.String,System.IO.FileMode,System.IO.FileAccess)"
+        );
+
         foreach (var toPatch in filtered)
             patch_type(toPatch);
 
@@ -57,24 +82,7 @@ class FixFileStreams : Command {
         foreach (Instruction i in fileStreams.ToList()) {
             var fileAccessRead = il.Create(OpCodes.Ldc_I4_1);
             il.InsertBefore(i, fileAccessRead);
-
-            var ctorType = this.module.AssemblyReferences.Select(
-                x => new {
-                    type = this.module.AssemblyResolver.Resolve(x)
-                        .MainModule.GetType("System.IO.FileStream")
-                }
-            ).Where(x => x.type != null).Select(x => x.type).First();
-
-            string wantedCtor = "System.Void System.IO.FileStream"
-                              + "::.ctor(System.String,"
-                              + "System.IO.FileMode,"
-                              + "System.IO.FileAccess)";
-
-            var newCtor = ctorType.GetConstructors()
-                .Single(x => x.ToString() == wantedCtor);
-
-            var refCtor = this.module.ImportReference(newCtor);
-            il.Replace(i, il.Create(OpCodes.Newobj, refCtor));
+            il.Replace(i, il.Create(OpCodes.Newobj, this.betterFileStream));
         }
     }
 
@@ -86,11 +94,11 @@ class FixFileStreams : Command {
 
 class ReplaceCall : Command {
     private string search;
-    private string replace;
+    private MethodReference replace;
 
     public ReplaceCall(ReplaceCallCmd options) : base(options) {
         this.search = options.replaceCall.ToList()[0];
-        this.replace = options.replaceCall.ToList()[1];
+        this.replace = this.find_method_ref(options.replaceCall.ToList()[1]);
 
         var filtered = this.module.Types
             .Where(p => options.typesToPatch.Contains(p.Name));
@@ -108,20 +116,8 @@ class ReplaceCall : Command {
             .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));
+            il.Replace(i, il.Create(OpCodes.Call, this.replace));
     }
 
     private void patch_type(TypeDefinition td) {
diff --git a/pkgs/games/build-support/monogame-patcher/src/patcher.csproj b/pkgs/games/build-support/monogame-patcher/src/patcher.csproj
index 994b78e5..03307287 100644
--- a/pkgs/games/build-support/monogame-patcher/src/patcher.csproj
+++ b/pkgs/games/build-support/monogame-patcher/src/patcher.csproj
@@ -7,7 +7,6 @@
     <Compile Include="assembly-info.cs"/>
     <Compile Include="options.cs"/>
     <Compile Include="patcher.cs"/>
-    <Compile Include="tests.cs"/>
   </ItemGroup>
 
   <PropertyGroup>
@@ -16,7 +15,6 @@
 
     <CecilInfo>Version=0.10.0.0$(Blurb)50cebf1cceb9d05e</CecilInfo>
     <CmdLineInfo>Version=2.2.1.0$(Blurb)de6f01bd326f8c32</CmdLineInfo>
-    <NUnitInfo>Version=3.10.1.0$(Blurb)2638cd05610744eb</NUnitInfo>
   </PropertyGroup>
 
   <ItemGroup>
@@ -24,12 +22,14 @@
       <SpecificVersion>False</SpecificVersion>
       <Private>True</Private>
     </Reference>
-    <Reference Include="Mono.Cecil.Rocks"/>
+    <Reference Include="Mono.Cecil.Rocks, $(CecilInfo)">
+      <SpecificVersion>False</SpecificVersion>
+      <Private>True</Private>
+    </Reference>
     <Reference Include="CommandLine, $(CmdLineInfo)">
       <SpecificVersion>False</SpecificVersion>
       <Private>True</Private>
     </Reference>
-    <Reference Include="nunit.framework, $(NUnitInfo)"/>
   </ItemGroup>
 
   <PropertyGroup>
diff --git a/pkgs/games/build-support/monogame-patcher/src/test.sh b/pkgs/games/build-support/monogame-patcher/src/test.sh
new file mode 100644
index 00000000..80260c80
--- /dev/null
+++ b/pkgs/games/build-support/monogame-patcher/src/test.sh
@@ -0,0 +1,78 @@
+set -x
+cd "$(mktemp -d)"
+
+cat > "a.cs" <<EOF
+using System;
+
+public class a {
+    public static string replaceMe(string foo) {
+        Console.WriteLine("foo called: " + foo);
+        return "foo";
+    }
+}
+EOF
+
+cat > "b.cs" <<EOF
+using System;
+using System.IO;
+
+public class b {
+    public static string replacement(string bar) {
+        if (bar == "nope")
+            return "nope";
+        Console.WriteLine("bar called: " + bar);
+        return "bar";
+    }
+
+    public static void wrongFileStreamUse() {
+        var fs = new FileStream("write_test.txt", FileMode.Open);
+        if (fs.CanWrite)
+            Console.WriteLine("can write");
+        else
+            Console.WriteLine("can not write");
+    }
+}
+EOF
+
+cat > "test1.cs" <<EOF
+class test1 {
+    public static void Main() {
+        a.replaceMe("xxx");
+        b.replacement("nope");
+    }
+}
+EOF
+
+cat > "test2.cs" <<EOF
+class test1 {
+    public static void Main() {
+        b.wrongFileStreamUse();
+    }
+}
+EOF
+
+mcs a.cs -target:library -out:a.dll
+mcs b.cs -target:library -out:b.dll
+
+mcs test1.cs -r:a -r:b -out:test1.exe
+mcs test2.cs -r:a -r:b -out:test2.exe
+
+! "$out/bin/monogame-patcher" replace-call -i test1.exe \
+    "System.String a::replaceMe(System.String)" \
+    "System.String b::notfound(System.String)" \
+    test1 2> /dev/null
+
+"$out/bin/monogame-patcher" replace-call -i test1.exe \
+    "System.String a::replaceMe(System.String)" \
+    "System.String b::replacement(System.String)" \
+    test1
+
+test "$(mono test1.exe)" = "bar called: xxx"
+
+echo foo > write_test.txt
+
+test "$(mono test2.exe)" = "can write"
+
+"$out/bin/monogame-patcher" fix-filestreams -i b.dll b
+
+test "$(mono test2.exe)" = "can not write"
diff --git a/pkgs/games/build-support/monogame-patcher/src/tests.cs b/pkgs/games/build-support/monogame-patcher/src/tests.cs
deleted file mode 100644
index 8b9d3ee3..00000000
--- a/pkgs/games/build-support/monogame-patcher/src/tests.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using NUnit.Framework;
-
-[TestFixture]
-public class PatcherTests {
-    [Test]
-    public void foo() {
-        // Dummy test
-        Assert.IsTrue(true);
-    }
-}