From fb43ad0db601e579be47ec32f8ed5590ed285498 Mon Sep 17 00:00:00 2001 From: aszlig Date: Fri, 28 Jul 2017 20:00:28 +0200 Subject: games: Add DOTT and Grim Fandango Both are the remastered versions available via Humble Bundle and both also needed a bit of patching via an LD preloader in order to work as intended. Day of the Tentacle conforms to XDG but it assumes that the data directory is in the same directory of the executable, so we fake /proc/self/exe to point to the "$out/share/dott/DUMMY". The "DUMMY" here is because the implementation does a dirname() on the directory. Grim Fandango on the other hand needs a bit more patching, so we first of all override the _first_ chdir() the game does to point to the data directory but we also override fopen64() and opendir() to use the XDG_DATA_HOME-based save directory whenever one of these calls point to "./Saves/..." because the data directory resides inside the store and thus is (of course) read-only. I had the expressions for these two games laying around for quite a while, so while merging another game from a PR I thought it would be a good opportinity to merge them as well. Signed-off-by: aszlig --- pkgs/games/humblebundle/default.nix | 2 + pkgs/games/humblebundle/dott.nix | 70 ++++++++++++ pkgs/games/humblebundle/grim-fandango.nix | 177 ++++++++++++++++++++++++++++++ 3 files changed, 249 insertions(+) create mode 100644 pkgs/games/humblebundle/dott.nix create mode 100644 pkgs/games/humblebundle/grim-fandango.nix (limited to 'pkgs/games/humblebundle') diff --git a/pkgs/games/humblebundle/default.nix b/pkgs/games/humblebundle/default.nix index e1c7c0e1..c7d760ac 100644 --- a/pkgs/games/humblebundle/default.nix +++ b/pkgs/games/humblebundle/default.nix @@ -14,9 +14,11 @@ let bastion = callPackage ./bastion.nix {}; brigador = callPackage ./brigador.nix {}; cavestoryplus = callPackage ./cavestoryplus.nix {}; + dott = callPackage_i686 ./dott.nix {}; fez = callPackage ./fez.nix {}; ftl = callPackage ./ftl.nix {}; guacamelee = callPackage_i686 ./guacamelee.nix {}; + grim-fandango = callPackage_i686 ./grim-fandango.nix {}; hammerwatch = callPackage ./hammerwatch.nix {}; jamestown = callPackage ./jamestown.nix {}; liads = callPackage ./liads.nix {}; diff --git a/pkgs/games/humblebundle/dott.nix b/pkgs/games/humblebundle/dott.nix new file mode 100644 index 00000000..8f098d05 --- /dev/null +++ b/pkgs/games/humblebundle/dott.nix @@ -0,0 +1,70 @@ +{ stdenv, fetchHumbleBundle, mesa, libpulseaudio, alsaLib, libudev +, writeText +}: + +stdenv.mkDerivation rec { + name = "dott-remastered-${version}"; + version = "1.4.1"; + + src = fetchHumbleBundle { + machineName = "dayofthetentacle_linux_beYLi"; + suffix = "tar.gz"; + md5 = "667b2a8a082702832242321515e55e70"; + }; + + unpackCmd = "mkdir \"$name\" && tar xf \"$curSrc\" -C \"$name\""; + + preloader = writeText "dott-preloader.c" '' + #define _GNU_SOURCE + #include + #include + #include + #include + + static int datadir_size = sizeof(DOTT_DATADIR) - 1; + + ssize_t readlink(const char *path, char *buf, size_t bufsize) { + static ssize_t (*_readlink) (const char *, char *, size_t) = NULL; + if (_readlink == NULL) _readlink = dlsym(RTLD_NEXT, "readlink"); + + if (strncmp(path, "/proc/self/exe", 15) == 0) { + ssize_t copylen = datadir_size > bufsize ? bufsize : datadir_size; + memcpy(buf, DOTT_DATADIR, copylen); + return copylen; + } else { + return _readlink(path, buf, bufsize); + } + } + + int SteamAPI_Init(void) { + return 0; + } + ''; + + rpath = stdenv.lib.makeLibraryPath [ + mesa stdenv.cc.cc libpulseaudio alsaLib.out libudev + ]; + + buildPhase = '' + cc -Werror -Wall -std=gnu11 -shared "$preloader" -o preload.so -fPIC \ + -DDOTT_DATADIR="\"$out/share/dott/DUMMY\"" + patchelf --set-rpath "$rpath" lib/libfmod.so.8 + patchelf \ + --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \ + --remove-needed libsteam_api.so \ + --add-needed "$out/libexec/dott/libdott-preload.so" \ + Dott + patchelf --set-rpath "$out/libexec/dott:$rpath" Dott + ''; + + installPhase = '' + install -vsD preload.so "$out/libexec/dott/libdott-preload.so" + install -vD lib/libfmod.so.8 "$out/libexec/dott/libfmod.so.8" + install -vD Dott "$out/bin/dott" + if ldd "$out/bin/dott" | grep -F 'not found'; then exit 1; fi + install -vD -m 0644 tenta.cle "$out/share/dott/tenta.cle" + ''; + + dontStrip = true; + dontPatchELF = true; +} diff --git a/pkgs/games/humblebundle/grim-fandango.nix b/pkgs/games/humblebundle/grim-fandango.nix new file mode 100644 index 00000000..c2b450e5 --- /dev/null +++ b/pkgs/games/humblebundle/grim-fandango.nix @@ -0,0 +1,177 @@ +{ stdenv, fetchHumbleBundle, mesa, libpulseaudio, alsaLib, SDL2, writeText +, xorg +}: + +stdenv.mkDerivation rec { + name = "grim-fandango-remastered-${version}"; + version = "1.4.0"; + + src = fetchHumbleBundle { + machineName = "grimfandango_linux"; + suffix = "tar.gz"; + md5 = "52e0590850102a1ae0db907bef413e57"; + }; + + preloader = writeText "grim-preloader.c" '' + #define _GNU_SOURCE + #include + #include + #include + #include + #include + #include + #include + #include + #include + + int chdir(const char *path) { + static int (*_chdir) (const char *) = NULL; + if (_chdir == NULL) { + _chdir = dlsym(RTLD_NEXT, "chdir"); + return _chdir(GRIM_DATADIR); + } + return _chdir(path); + } + + #define CONCAT_ENV(path) \ + if (asprintf(&result, "%s/%s", env, path) == -1) { \ + perror("asprintf"); \ + exit(1); \ + } + + static char *getSaveDir(void) { + const char *env; + static char *result = NULL; + + if (result == NULL) { + if ((env = getenv("XDG_DATA_HOME")) != NULL) { + CONCAT_ENV("grim-fandango"); + } else if ((env = getenv("HOME")) != NULL) { + CONCAT_ENV(".local/share/grim-fandango"); + } else { + fputs("Unable to determine XDG_DATA_HOME or HOME.\n", stderr); + exit(1); + } + } + + return result; + } + + static void makedirs(char *path) + { + int pathlen = strlen(path); + + static int (*_mkdir) (const char *, mode_t) = NULL; + if (_mkdir == NULL) _mkdir = dlsym(RTLD_NEXT, "mkdir"); + + for (int i = 1; i < pathlen; ++i) { + if (path[i] == '/') { + path[i] = '\0'; + _mkdir(path, 0777); + path[i] = '/'; + } + } + } + + static char *mkSavePath(const char *path) + { + int savelen, pathlen; + char *buf, *savedir; + + savedir = getSaveDir(); + savelen = strlen(savedir); + pathlen = strlen(path); + buf = malloc(savelen + pathlen + 1); + strncpy(buf, savedir, savelen); + strncpy(buf + savelen, path, pathlen + 1); + + return buf; + } + + int mkdir(const char *pathname, mode_t mode) { + return 0; + } + + FILE *fopen64(const char *path, const char *mode) { + FILE *fp; + char *buf; + + static FILE *(*_fopen) (const char *, const char *) = NULL; + if (_fopen == NULL) _fopen = dlsym(RTLD_NEXT, "fopen64"); + + if (strncmp(path, "./Saves/", 8) == 0) { + path += 7; + buf = mkSavePath(path); + if ((fp = _fopen(buf, mode)) == NULL) { + makedirs(buf); + fp = _fopen(buf, mode); + } + free(buf); + return fp; + } + + return _fopen(path, mode); + } + + DIR *opendir(const char *name) { + DIR *dp; + char *buf; + + static DIR *(*_opendir) (const char *) = NULL; + if (_opendir == NULL) _opendir = dlsym(RTLD_NEXT, "opendir"); + + if (strncmp(name, "./Saves/", 8) == 0) { + name += 7; + buf = mkSavePath(name); + if ((dp = _opendir(buf)) == NULL) { + makedirs(buf); + dp = _opendir(buf); + } + free(buf); + return dp; + } + + return _opendir(name); + } + ''; + + rpath = stdenv.lib.makeLibraryPath [ + mesa stdenv.cc.cc libpulseaudio alsaLib.out SDL2 xorg.libX11 + ]; + + buildPhase = '' + cc -Werror -Wall -std=gnu11 -shared "$preloader" -o preload.so -fPIC \ + -DGRIM_DATADIR="\"$out/share/grim-fandango\"" + patchelf --set-rpath "$rpath" bin/libchore.so + patchelf --set-rpath "$rpath" bin/libLua.so + patchelf \ + --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \ + --add-needed "$out/libexec/grim-fandango/libgrim-preload.so" \ + bin/GrimFandango + patchelf --replace-needed libSDL2-2.0.so.1 libSDL2.so bin/GrimFandango + patchelf --set-rpath "$out/libexec/grim-fandango:$rpath" bin/GrimFandango + ''; + + installPhase = '' + install -vsD preload.so "$out/libexec/grim-fandango/libgrim-preload.so" + install -vD bin/libchore.so "$out/libexec/grim-fandango/libchore.so" + install -vD bin/libLua.so "$out/libexec/grim-fandango/libLua.so" + install -vD bin/GrimFandango "$out/bin/grim-fandango" + if ldd "$out/bin/grim-fandango" | grep -F 'not found'; then exit 1; fi + + mkdir -p "$out/share/grim-fandango" + find bin -maxdepth 1 -mindepth 1 \ + \( -path bin/i386 \ + -o -path bin/amd64 \ + -o -path bin/common-licenses \ + -o -path bin/scripts \ + -o -path bin/GrimFandango \ + -o -name '*.so' \ + -o -name '*.so.*' \ + -o -name '*.txt' \ + \) -prune -o -print | xargs cp -vrt "$out/share/grim-fandango" + ''; + + dontStrip = true; + dontPatchELF = true; +} -- cgit 1.4.1