about summary refs log tree commit diff
path: root/pkgs/games
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/games')
-rw-r--r--pkgs/games/build-support/build-game.nix6
-rw-r--r--pkgs/games/build-support/default.nix4
-rw-r--r--pkgs/games/build-support/setup-hooks/default.nix7
-rw-r--r--pkgs/games/build-support/setup-hooks/gog-unpack.sh71
-rw-r--r--pkgs/games/default.nix1
5 files changed, 86 insertions, 3 deletions
diff --git a/pkgs/games/build-support/build-game.nix b/pkgs/games/build-support/build-game.nix
index 5c1f1ef4..459fca75 100644
--- a/pkgs/games/build-support/build-game.nix
+++ b/pkgs/games/build-support/build-game.nix
@@ -1,4 +1,4 @@
-{ stdenv, lib, file, unzip, buildSandbox, autoPatchelfHook
+{ stdenv, lib, file, unzip, buildSandbox, autoPatchelfHook, gogUnpackHook
 
 , withPulseAudio ? true, libpulseaudio ? null
 , alsaLib
@@ -18,7 +18,9 @@ assert withPulseAudio -> libpulseaudio != null;
 buildSandbox (stdenv.mkDerivation ({
   buildInputs = [ stdenv.cc.cc ] ++ buildInputs;
 
-  nativeBuildInputs = [ unzip autoPatchelfHook ] ++ nativeBuildInputs;
+  nativeBuildInputs = [
+    unzip autoPatchelfHook gogUnpackHook
+  ] ++ nativeBuildInputs;
 
   preUnpack = preUnpack + ''
     mkdir "$name"
diff --git a/pkgs/games/build-support/default.nix b/pkgs/games/build-support/default.nix
index 1832f987..0e7574ec 100644
--- a/pkgs/games/build-support/default.nix
+++ b/pkgs/games/build-support/default.nix
@@ -1,4 +1,4 @@
-{ config, callPackage, ... }:
+{ config, callPackage, callPackages, ... }:
 
 {
   buildGame = callPackage ./build-game.nix {
@@ -6,4 +6,6 @@
   };
   buildUnity = callPackage ./build-unity.nix {};
   monogamePatcher = callPackage ./monogame-patcher {};
+
+  inherit (callPackages ./setup-hooks {}) gogUnpackHook;
 }
diff --git a/pkgs/games/build-support/setup-hooks/default.nix b/pkgs/games/build-support/setup-hooks/default.nix
new file mode 100644
index 00000000..9f35dad7
--- /dev/null
+++ b/pkgs/games/build-support/setup-hooks/default.nix
@@ -0,0 +1,7 @@
+{ makeSetupHook, libarchive, innoextract }:
+
+{
+  gogUnpackHook = makeSetupHook {
+    deps = [ libarchive innoextract ];
+  } ./gog-unpack.sh;
+}
diff --git a/pkgs/games/build-support/setup-hooks/gog-unpack.sh b/pkgs/games/build-support/setup-hooks/gog-unpack.sh
new file mode 100644
index 00000000..8b70803c
--- /dev/null
+++ b/pkgs/games/build-support/setup-hooks/gog-unpack.sh
@@ -0,0 +1,71 @@
+unpackCmdHooks+=(_tryUnpackGogMakeSelf _tryUnpackGogInnoSetup)
+
+_tryUnpackGogMakeSelf() {
+  # Make sure it's really a Makeself installer with GOG.com modifications.
+  sed -n -e '1,/^\([^#]\| *\)$/ {
+    /This script.*Makeself/ {
+      n; /GOG\.com/q
+    }
+    200q1 # This is getting too long, so quit immediately.
+    b
+  }
+  q1' "$curSrc" || return 1
+
+  # The file consists of a shell script at the top, followed by a tarball with
+  # the installer and after that tarball, the actual ZIP file with the game
+  # data follows. So we need to calculate the offsets accordingly, which
+  # luckily are dumped using --dumpconf (we only get the sizes, but we can
+  # infer the starting offset for the ZIP file using those).
+  local zipfileOffset="$(
+    eval "$($SHELL "$curSrc" --dumpconf)"
+    declare -i offset=1
+    offset+="$(head -n $(($OLDSKIP - 1)) "$curSrc" | wc -c)"
+    for fs in $filesizes; do
+      offset+="$fs"
+    done
+    echo "$offset"
+  )"
+
+  # Unfortunately bsdtar exits with failure if one of the patterns specified
+  # using the --include flag doesn't match. However, if the desktop icon is
+  # missing it's not the end of the world, so we need to find another way to
+  # make it happen without bsdtar returning a failure.
+  #
+  # Let's introduce -s, which is used to substitute the paths. While it may
+  # sound eligible to be used in conjunction --include, it's only really useful
+  # for our case if the inclusion patterns would be matched _after_ the
+  # substitiotions. Unfortunately, they're matched before the substitions.
+  #
+  # So what we do instead is rewrite *everything* that we want to include into
+  # a special path "/_/game" and rewrite everything that doesn't begin with /
+  # into "skip". We're (ab)using the fact here that files coming from the
+  # archive never start with "/", but during the substitutions the leading
+  # slash isn't stripped.
+  #
+  # In the end the resulting paths are normalized, so "/..." will be turned
+  # into "./...", so all we need to do in the end is to strip 2 components from
+  # the resulting path. This discards every path that has been renamed to
+  # "skip".
+  tail -c"+$zipfileOffset" "$curSrc" | bsdtar -xf - \
+    -s '!^data/noarch/game/\(.*\)$!/_/game/\1!' \
+    -s '!^data/noarch/support/icon\.png$!/_/game/xdg-icon.png!' \
+    -s '!^[^/].*!skip!' --strip-components=2
+}
+
+_tryUnpackGogInnoSetup() {
+  innoextract -i "$curSrc" &> /dev/null || return 1
+
+  local -a unpackArgs=()
+  if [ -n "$innoExtractOnly" ]; then
+    local i
+    for i in $innoExtractOnly; do
+      unpackArgs+=("--include" "$i")
+    done
+  fi
+
+  if [ -z "$innoExtractKeepCase" ]; then
+    unpackArgs+=("-L")
+  fi
+
+  innoextract -s "${unpackArgs[@]}" -m "$curSrc"
+}
diff --git a/pkgs/games/default.nix b/pkgs/games/default.nix
index bead9271..71ccdf5e 100644
--- a/pkgs/games/default.nix
+++ b/pkgs/games/default.nix
@@ -23,6 +23,7 @@ let
     self = import ./build-support {
       inherit (super) config;
       callPackage = pkgs.lib.callPackageWith (super // self);
+      callPackages = pkgs.lib.callPackagesWith (super // self);
     };
   in self;