diff options
author | aszlig <aszlig@nix.build> | 2018-02-08 20:04:07 +0100 |
---|---|---|
committer | aszlig <aszlig@nix.build> | 2018-02-09 16:33:28 +0100 |
commit | b014da8a00032fded8c249bcbe52d80bc9de8e48 (patch) | |
tree | 1139db49b6b06ddfbc514bed54faab837f1d656d /pkgs/games | |
parent | aaf8390e5e0eab0d89fdd5c7e40359985871d74f (diff) |
pkgs/games/humblebundle: Add Owlboy
Very similar to other games using Mono, but this has a similar problem to what Opus Magnum had (see 523dcef1f77251a4cfeb3428a0b13c0ec1d9c342) but instead of using Cecil for patching I'm using LD_PRELOAD instead because the number of occasions we need to patch is not only higher but also there are different constructors in use for System.IO.FileStream, so patching becomes much much harder. Signed-off-by: aszlig <aszlig@nix.build>
Diffstat (limited to 'pkgs/games')
-rw-r--r-- | pkgs/games/humblebundle/default.nix | 1 | ||||
-rw-r--r-- | pkgs/games/humblebundle/owlboy.nix | 102 |
2 files changed, 103 insertions, 0 deletions
diff --git a/pkgs/games/humblebundle/default.nix b/pkgs/games/humblebundle/default.nix index 3ed0b3b6..4a0792c4 100644 --- a/pkgs/games/humblebundle/default.nix +++ b/pkgs/games/humblebundle/default.nix @@ -25,6 +25,7 @@ let liads = callPackage ./liads.nix {}; megabytepunch = callPackage_i686 ./megabytepunch.nix {}; opus-magnum = callPackage ./opus-magnum.nix {}; + owlboy = callPackage ./owlboy.nix {}; pico-8 = callPackage ./pico-8.nix {}; rocketbirds = callPackage ./rocketbirds.nix {}; spaz = callPackage ./spaz.nix {}; diff --git a/pkgs/games/humblebundle/owlboy.nix b/pkgs/games/humblebundle/owlboy.nix new file mode 100644 index 00000000..a6c42577 --- /dev/null +++ b/pkgs/games/humblebundle/owlboy.nix @@ -0,0 +1,102 @@ +{ stdenv, lib, buildGame, fetchHumbleBundle, unzip, makeWrapper, mono50 +, SDL2, SDL2_image, openal, libvorbis +, writeText +}: + +buildGame rec { + name = "owlboy-${version}"; + version = "20171229"; + + src = fetchHumbleBundle { + suffix = "bin"; + machineName = "owlboy_linux"; + md5 = "c2e99502013c7d2529bc2aefb6416dcf"; + }; + + unpackCmd = "${unzip}/bin/unzip -qq \"$curSrc\" 'data/*' || :"; + + nativeBuildInputs = [ makeWrapper ]; + + libdir = if stdenv.system == "x86_64-linux" then "lib64" else "lib"; + + prePatch = '' + find -type f -name '*.ini' -exec sed -i -e 's/${"\r"}$//' {} + + ''; + + buildPhase = let + dllmap = { + SDL2 = "${SDL2}/lib/libSDL2.so"; + SDL2_image = "${SDL2_image}/lib/libSDL2_image.so"; + soft_oal = "${openal}/lib/libopenal.so"; + libvorbisfile-3 = "${libvorbis}/lib/libvorbisfile.so"; + MojoShader = "$out/lib/owlboy/libmojoshader.so"; + }; + in '' + cc -Werror -shared "$preloader" -o preloader.so -ldl -fPIC \ + -DSTOREPATH=\"$out\" + '' + lib.concatStrings (lib.mapAttrsToList (dll: target: '' + sed -i -e '/<dllmap.*dll="${dll}\.dll".*os="linux"/ { + s!target="[^"]*"!target="'"${target}"'"! + }' FNA.dll.config + '') dllmap); + + # The game tries to open data files in read-write mode, so use LD_PRELOAD to + # avoid this whenever a store path is involved. + preloader = writeText "owlboy-preloader.c" '' + #define _GNU_SOURCE + #include <dlfcn.h> + #include <fcntl.h> + #include <stdarg.h> + #include <stdio.h> + #include <stdbool.h> + #include <string.h> + #include <sys/stat.h> + + static bool isDataPath(const char *path) { + return strncmp(path, "content/", 8) == 0 + || strncmp(path, STOREPATH, sizeof(STOREPATH) - 1) == 0; + } + + int access(const char *path, int mode) { + static int (*_access) (const char *, int) = NULL; + if (_access == NULL) _access = dlsym(RTLD_NEXT, "access"); + if (isDataPath(path) && mode & W_OK) + mode = mode & ~W_OK | R_OK; + return _access(path, mode); + } + + int open(const char *path, int flags, ...) { + va_list ap; + mode_t mode; + static int (*_open) (const char *, int, mode_t) = NULL; + if (_open == NULL) _open = dlsym(RTLD_NEXT, "open"); + va_start(ap, flags); + mode = va_arg(ap, mode_t); + va_end(ap); + if (isDataPath(path) && flags & O_RDWR) + flags = flags & ~O_RDWR | O_RDONLY; + return _open(path, flags, mode); + } + ''; + + installPhase = '' + mkdir -p "$out/bin" "$out/share" "$out/libexec/owlboy" + install -vD preloader.so "$out/lib/owlboy/preloader.so" + cp -rv content "$out/share/owlboy" + cp -rv monoconfig "$out/libexec/owlboy/Owlboy.exe.config" + cp -rvt "$out/libexec/owlboy" Owlboy.exe \ + FNA.dll* GamedevUtility.dll MoonSharp.Interpreter.dll TimSort.dll + cp -rvt "$out/lib/owlboy" "$libdir/libmojoshader.so" + ln -vs "$out/share/owlboy" "$out/libexec/owlboy/content" + + makeWrapper ${lib.escapeShellArg mono50}/bin/mono \ + "$out/bin/owlboy" \ + --set LD_PRELOAD "$out/lib/owlboy/preloader.so" \ + --add-flags "$out/libexec/owlboy/Owlboy.exe" \ + --run "cd '$out/libexec/owlboy'" + ''; + + sandbox.paths.required = [ + "$XDG_DATA_HOME/Owlboy" "$XDG_CONFIG_HOME/Owlboy" + ]; +} |