From dd25608bfa723ba979504234dd689e502c52fcd3 Mon Sep 17 00:00:00 2001 From: aszlig Date: Wed, 1 Jul 2020 06:07:09 +0200 Subject: games/gog: Add Baldur's Gate I and II Both are the enhanced edition from GOG. Packaging is mostly straightforward, although I had to use patchelf with a custom patch, since while --remove-needed removes the DT_NEEDED entries from the ELF it doesn't however remove the corresponding entries in the .gnu.version_r section. The reason why I did this is because we really should not need Expat and OpenSSL, because they're only used by the XMPP portions of the statically linked libjingle. Signed-off-by: aszlig --- pkgs/games/gog/baldurs-gate/default.nix | 78 ++++++++++++++++++++++ .../gog/baldurs-gate/patchelf-remove-verneed.patch | 53 +++++++++++++++ pkgs/games/gog/default.nix | 2 + 3 files changed, 133 insertions(+) create mode 100644 pkgs/games/gog/baldurs-gate/default.nix create mode 100644 pkgs/games/gog/baldurs-gate/patchelf-remove-verneed.patch (limited to 'pkgs') diff --git a/pkgs/games/gog/baldurs-gate/default.nix b/pkgs/games/gog/baldurs-gate/default.nix new file mode 100644 index 00000000..938d1b57 --- /dev/null +++ b/pkgs/games/gog/baldurs-gate/default.nix @@ -0,0 +1,78 @@ +{ stdenv, lib, fetchFromGitHub, autoreconfHook +, buildGame, makeWrapper, fetchGog, openal, libGL +}: + +let + patchelf = stdenv.mkDerivation { + pname = "patchelf"; + version = "2020-06-23"; + + src = fetchFromGitHub { + owner = "NixOS"; + repo = "patchelf"; + rev = "e61654be0acf4454ab070a8c8e1345aa7d5b3d74"; + sha256 = "1bfr6303i0hii8s86kj2j8dhi97abgancb08xpvfx2dh6608kcr0"; + }; + + patches = [ ./patchelf-remove-verneed.patch ]; + nativeBuildInputs = [ autoreconfHook ]; + }; + + mkBaldursGate = { pname, version, src, executable }: buildGame rec { + name = "${pname}-${version}"; + inherit pname version src; + + nativeBuildInputs = [ makeWrapper ]; + buildInputs = [ openal libGL ]; + execName = executable + lib.optionalString stdenv.is64bit "64"; + + # The game uses libjingle for NAT traversal only, so let's remove the + # XMPP-related libraries since all we should need here is STUN/TURN + # support. + buildPhase = '' + ${patchelf}/bin/patchelf \ + --remove-needed libcrypto.so.1.0.0 \ + --remove-needed libssl.so.1.0.0 \ + --remove-needed libexpat.so.1 \ + "$execName" + ''; + + installPhase = '' + install -vD "$execName" "$out/libexec/$pname/$pname" + install -vD -m 0644 engine.lua "$out/share/$pname/engine.lua" + install -vD -m 0644 chitin.key "$out/share/$pname/chitin.key" + cp -rt "$out/share/$pname" data lang movies music scripts + makeWrapper "$out/libexec/$pname/$pname" "$out/bin/$pname" \ + --run "cd '$out/share/$pname'" + ''; + + # Allow access to both data dirs to allow export/import of characters. + sandbox.paths.required = [ + "$XDG_DATA_HOME/Baldur's Gate - Enhanced Edition" + "$XDG_DATA_HOME/Baldur's Gate II - Enhanced Edition" + ]; + }; + +in { + bg1ee = mkBaldursGate { + pname = "baldurs-gate"; + version = "2.5.23121"; + executable = "BaldursGate"; + + src = fetchGog { + productId = 1207666353; + sha256 = "0r8d4pc7rszkgw0wwfvzvng48hc0915qz6vw3hpkhrffccsl9bc0"; + }; + }; + + bg2ee = mkBaldursGate { + pname = "baldurs-gate-2"; + version = "2.5.21851"; + executable = "BaldursGateII"; + + src = fetchGog { + productId = 1207666373; + sha256 = "0l4rbc1zbhasnkbfcspbjb8vwsw574ld2aw6x9gk9bdbr8rz0fik"; + }; + }; +} diff --git a/pkgs/games/gog/baldurs-gate/patchelf-remove-verneed.patch b/pkgs/games/gog/baldurs-gate/patchelf-remove-verneed.patch new file mode 100644 index 00000000..31db58b2 --- /dev/null +++ b/pkgs/games/gog/baldurs-gate/patchelf-remove-verneed.patch @@ -0,0 +1,53 @@ +diff --git a/src/patchelf.cc b/src/patchelf.cc +index ea6c6c0..d2d7d3b 100644 +--- a/src/patchelf.cc ++++ b/src/patchelf.cc +@@ -1344,6 +1344,8 @@ void ElfFile::removeNeeded(const std::set & libs + auto shdrDynStr = findSection(".dynstr"); + char * strTab = (char *) contents + rdi(shdrDynStr.sh_offset); + ++ unsigned int verNeedNum = 0; ++ + Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset)); + Elf_Dyn * last = dyn; + for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++) { +@@ -1358,9 +1360,39 @@ void ElfFile::removeNeeded(const std::set & libs + } + } else + *last++ = *dyn; ++ ++ if (rdi(dyn->d_tag) == DT_VERNEEDNUM) ++ verNeedNum = rdi(dyn->d_un.d_val); + } + + memset(last, 0, sizeof(Elf_Dyn) * (dyn - last)); ++ ++ if (verNeedNum) { ++ auto shdrVersionR = findSection(".gnu.version_r"); ++ Elf_Shdr & shdrVersionRStrings = shdrs[rdi(shdrVersionR.sh_link)]; ++ char * verStrTab = (char *) contents + rdi(shdrVersionRStrings.sh_offset); ++ std::string versionRStringsSName = getSectionName(shdrVersionRStrings); ++ ++ debug("found .gnu.version_r with %i entries, strings in %s\n", verNeedNum, versionRStringsSName.c_str()); ++ ++ Elf_Verneed * need = (Elf_Verneed *) (contents + rdi(shdrVersionR.sh_offset)); ++ Elf_Verneed * last = need; ++ ++ while (verNeedNum > 0) { ++ char * file = verStrTab + rdi(need->vn_file); ++ ++ if (libs.find(file) != libs.end()) { ++ debug("removing .gnu.version_r entry for '%s'\n", file); ++ // Relative offset, so all we need to do here is punch a hole. ++ last->vn_next += need->vn_next; ++ changed = true; ++ } ++ ++ last = need; ++ need = (Elf_Verneed *) (((char *) need) + rdi(need->vn_next)); ++ --verNeedNum; ++ } ++ } + } + + template diff --git a/pkgs/games/gog/default.nix b/pkgs/games/gog/default.nix index 91c06b2d..a651c86d 100644 --- a/pkgs/games/gog/default.nix +++ b/pkgs/games/gog/default.nix @@ -12,6 +12,8 @@ let }; albion = callPackage_i686 ./albion {}; + baldurs-gate = (callPackage ./baldurs-gate {}).bg1ee; + baldurs-gate-2 = (callPackage ./baldurs-gate {}).bg2ee; crosscode = callPackage ./crosscode.nix {}; dungeons3 = callPackage ./dungeons3.nix {}; epistory = callPackage ./epistory.nix { }; -- cgit 1.4.1