about summary refs log tree commit diff
path: root/pkgs/games/humblebundle/opus-magnum.nix
blob: 9b6d27cd56919be739b5b7aab5ce9bb2f36682e5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
{ stdenv, lib, buildGame, fetchHumbleBundle, makeWrapper, mono50
, SDL2, SDL2_image, SDL2_mixer, libvorbis

, fetchNuGet, writeText
}:

let
  cecil = fetchNuGet {
    baseName = "Mono.Cecil";
    version = "0.10-beta7";
    sha256 = "03bina3llcnylrfrvp5psnwrfn757j7zch5r360rpdn7gmcjjcpl";
    outputFiles = [ "lib/net40/*" ];
  };

  patcher = writeText "patcher.cs" ''
    using System.Linq;
    using System.Collections.Generic;
    using Mono.Cecil;
    using Mono.Cecil.Cil;
    using Mono.Cecil.Rocks;

    public class patcher {
      public static void Main() {
        var module = ModuleDefinition.ReadModule("Lightning.exe");
        var typesToPatch = new List<string>() {
          "#=qpBcj_0KQZcJ0ffkrxQcNZQ==",
          "#=qEMEvBoEQXql_zRuLLk1x6w==",
          "#=qZzmwsUfWWbRLjboUcCgm9sc9s0f6yVsIVJ2gWSL_c4g=",
          "PsdImage"
        };

        var filtered = module.Types.Where(p => typesToPatch.Contains(p.Name));
        foreach (var toPatch in filtered) {
          foreach (MethodDefinition md in toPatch.Methods) {
            var il = md.Body.GetILProcessor();
            var fileStreams = md.Body.Instructions
              .Where(i => i.OpCode == OpCodes.Newobj)
              .Where(i => (i.Operand as MethodReference).DeclaringType
                          .FullName == "System.IO.FileStream");

            foreach (Instruction i in fileStreams.ToList()) {
              var fileAccessRead = il.Create(OpCodes.Ldc_I4_1);
              il.InsertBefore(i, fileAccessRead);

              var ctorType = module.AssemblyReferences.Select(
                x => new {
                  type = 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 = module.ImportReference(newCtor);
              il.Replace(i, il.Create(OpCodes.Newobj, refCtor));
            }
          }
        }
        module.Write("LightningPatched.exe");
      }
    }
  '';

in buildGame rec {
  name = "opus-magnum-${version}";
  version = "1";

  src = fetchHumbleBundle {
    machineName = "opus_magnum_4vffp_linux_Z9zWf";
    suffix = "zip";
    md5 = "aefe8aae8cd3dd3915be8d8cd6f3705d";
  };

  arch = if stdenv.system == "x86_64-linux" then "x86_64" else "x86";

  nativeBuildInputs = [ makeWrapper mono50 cecil ];

  patchPhase = ''
    { export MONO_PATH=${cecil}/lib/dotnet/Mono.Cecil
      mcs ${lib.escapeShellArg patcher} -out:patcher \
        -lib:${cecil}/lib/dotnet/Mono.Cecil \
        -r:Mono.Cecil -r:Mono.Cecil.Rocks
      mono patcher
      mv LightningPatched.exe Lightning.exe
    }
  '';

  buildPhase = let
    dllmap = {
      SDL2 = "${SDL2}/lib/libSDL2.so";
      SDL2_image = "${SDL2_image}/lib/libSDL2_image.so";
      SDL2_mixer = "${SDL2_mixer}/lib/libSDL2_mixer.so";
      libvorbisfile-3 = "${libvorbis}/lib/libvorbisfile.so";
    };
  in lib.concatStrings (lib.mapAttrsToList (dll: target: ''
    sed -i -e '/<dllmap.*dll="${dll}\.dll".*os="linux"/ {
      s!target="[^"]*"!target="${target}"!
    }' Lightning.exe.config
  '') dllmap);

  installPhase = ''
    mkdir -p "$out/bin" "$out/share/opus-magnum" "$out/libexec/opus-magnum"
    cp -rvt "$out/share/opus-magnum" Content PackedContent
    cp -rvt "$out/libexec/opus-magnum" Lightning.exe* Ionic.Zip.Reduced.dll

    makeWrapper ${lib.escapeShellArg mono50}/bin/mono "$out/bin/opus-magnum" \
      --add-flags "$out/libexec/opus-magnum/Lightning.exe" \
      --run "cd '$out/share/opus-magnum'"
  '';

  sandbox.paths.required = [ "$XDG_DATA_HOME/Opus Magnum" "$HOME/Desktop" ];
}