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/gog/albion/config.patch19
-rw-r--r--pkgs/games/gog/albion/default.nix183
-rw-r--r--pkgs/games/gog/albion/error-log-stderr.patch100
-rw-r--r--pkgs/games/gog/albion/scons.patch74
-rw-r--r--pkgs/games/gog/albion/sdl2.patch60
-rw-r--r--pkgs/games/gog/albion/xdg-paths.patch259
-rw-r--r--pkgs/games/gog/default.nix2
7 files changed, 697 insertions, 0 deletions
diff --git a/pkgs/games/gog/albion/config.patch b/pkgs/games/gog/albion/config.patch
new file mode 100644
index 00000000..6bac229c
--- /dev/null
+++ b/pkgs/games/gog/albion/config.patch
@@ -0,0 +1,19 @@
+diff --git a/games/Albion/release/linux/Albion.cfg b/games/Albion/release/linux/Albion.cfg
+index 50d4327..8c901f1 100644
+--- a/games/Albion/release/linux/Albion.cfg
++++ b/games/Albion/release/linux/Albion.cfg
+@@ -50,11 +50,11 @@ Audio_MIDI_Device=
+ #     - this setting renders the 3d part of the game in the native resolution instead of rendering it in the original resolution and then scaling it
+ #     - there are some minor issues, read the readme for more information
+ # Display_MouseCursor=normal/minimal/none - shape of SDL mouse cursor in window mode
+-Display_ScaledWidth=720
+-Display_ScaledHeight=480
++Display_ScaledWidth=1280
++Display_ScaledHeight=960
+ Display_Fullscreen=no
+ Display_Enhanced_3D_Rendering=on
+-Display_MouseCursor=normal
++Display_MouseCursor=none
+ 
+ 
+ # Screenshot settings
diff --git a/pkgs/games/gog/albion/default.nix b/pkgs/games/gog/albion/default.nix
new file mode 100644
index 00000000..1242ecb7
--- /dev/null
+++ b/pkgs/games/gog/albion/default.nix
@@ -0,0 +1,183 @@
+{ stdenv, lib, buildSandbox, fetchGog, fetchzip, innoextract, SDL2, SDL2_mixer
+, bchunk, p7zip, alsaLib, writeText
+
+# For static recompilation
+, fetchFromGitHub, scons, judy, python, nasm, autoreconfHook
+
+, language ? "en"
+}:
+
+let
+  version = "1.6.1";
+
+  staticRecompilerSource = fetchFromGitHub {
+    owner = "M-HT";
+    repo = "SR";
+    rev = "albion_v${version}";
+    sha256 = "0yspgssfk5xbrs5krq0sin561rgb0fva4hk7mlxlcrvs0xpqf5z8";
+  };
+
+  mkPatchedWildMidi = variant: stdenv.mkDerivation {
+    name = "${variant}-0.2.3.5patched";
+    src = "${staticRecompilerSource}/midi-libs/${variant}-0.2.3.5svn";
+    nativeBuildInputs = [ autoreconfHook ];
+    buildInputs = [ alsaLib ];
+    postPatch = "sed -i -e '/^CFLAGS/s/-pedantic//' configure.ac";
+  };
+
+  compileMidiPlugin = variant: let
+    commonDrvAttrs = rec {
+      name = "midi-plugin-${variant}";
+      soname = "midi-${variant}";
+      sourceFile = "${soname}.c";
+      midiLib = "WildMidi";
+
+      src = "${staticRecompilerSource}/midi-plugins";
+
+      buildInputs = lib.singleton (mkPatchedWildMidi variant);
+
+      timidityCfg = let
+        gusPatches = lib.overrideDerivation (fetchzip {
+          url = "http://sebt3.openpandora.org/pnd/timidity_midi_installer.pnd";
+          sha256 = "0nznac8lxcbj0fwbg0njlnh3ysa3d3c5i24n2cw0yv5yqji4cdsb";
+          stripRoot = false;
+        }) (lib.const { unpackCmd = "${p7zip}/bin/7z x \"$curSrc\""; });
+      in writeText "timidity-albion.cfg" ''
+        dir ${gusPatches}/eawpats
+        source ${gusPatches}/eawpats/sounds.cfg
+      '';
+
+      postPatch = ''
+        sed -i -e 's!getenv("TIMIDITY_CFG")!"'"$timidityCfg"'"!' \
+          midi-wildmidi.c
+      '';
+
+      buildPhase = ''
+        gcc -shared -Wl,-soname,"$soname.so" -I. \
+          -o "$soname.so" -fpic -m32 -O2 -Wall \
+          "$sourceFile" -l"$midiLib"
+      '';
+
+      installPhase = ''
+        install -vD "$soname.so" "$out/lib/$soname.so"
+      '';
+    };
+
+    extraAttrs = lib.optionalAttrs (variant == "wildmidiA") {
+      soname = "midiA-wildmidi";
+      sourceFile = "albion/midiA-wildmidi.c";
+      midiLib = "WildMidiA";
+    };
+
+  in stdenv.mkDerivation (commonDrvAttrs // extraAttrs);
+
+  udis86 = stdenv.mkDerivation {
+    name = "udis86";
+    src = "${staticRecompilerSource}/SR/udis86-1.6";
+    postPatch = "chmod +x configure mkinstalldirs";
+    preInstall = "mkdir -p \"$out/lib\" \"$out/bin\"";
+  };
+
+  gameData = stdenv.mkDerivation rec {
+    name = "albion-game-data-${version}";
+    version = "3";
+
+    src = fetchGog {
+      productId = 1436955815;
+      downloadName = "${language}1installer1";
+      sha256 = ({
+        de = "0ylhma70kcj255i03gy5xa3adb8hfw2xpk1m2pp5880aqkmr06k7";
+        en = "0x0s2q0x7kjz6qfhb9qs5d959caijiinpc7xv4rx9n7mmb7xlh5m";
+      }).${language};
+    };
+
+    outputs = [ "out" "dev" ];
+
+    nativeBuildInputs = [ innoextract ];
+    phases = [ "unpackPhase" "patchPhase" "installPhase" ];
+    unpackCmd = toString [
+      "innoextract"
+      "--include" "game.gog"
+      "--include" "game.ins"
+      "--include" "MAIN.EXE"
+      "--include" "SETUP.INI"
+      "-m" "\"$curSrc\""
+    ];
+    patchPhase = ''
+      sed -i -e '
+        s,^SOURCE_PATH=.*,SOURCE_PATH=C:\\,
+        s/^\(MODE_[^=]*=\)N$/\1Y/
+      ' SETUP.INI
+    '';
+    installPhase = ''
+      ${bchunk}/bin/bchunk game.gog game.ins game_cd
+      ${p7zip}/bin/7z x game_cd01.iso ALBION
+      mv ALBION "$out"
+      install -vD -m 0644 SETUP.INI "$out/setup.ini"
+      install -vD -m 0644 MAIN.EXE "$dev/albion_main.exe"
+    '';
+  };
+
+in buildSandbox (stdenv.mkDerivation {
+  name = "albion-${version}";
+  inherit version;
+
+  src = staticRecompilerSource;
+
+  patches = [
+    ./scons.patch ./xdg-paths.patch ./config.patch ./sdl2.patch
+    ./error-log-stderr.patch ./cdpath-is-gamedir.patch
+    ./storepaths.patch
+  ];
+
+  wildmidi = compileMidiPlugin "wildmidi";
+  wildmidiA = compileMidiPlugin "wildmidiA";
+
+  postPatch = ''
+    substituteInPlace games/Albion/SR-Main/main.c \
+      --subst-var-by GAME_CONFIG_FILE "$out/etc/albion.cfg" \
+      --subst-var-by GAME_DATA_PATH ${lib.escapeShellArg gameData.out}
+
+    substituteInPlace games/Albion/SR-Main/virtualfs.c \
+      --subst-var-by SETUP_INI_PATH "${gameData.out}/setup.ini"
+
+    substituteInPlace games/Albion/SR-Main/Albion-music-midiplugin.c \
+      --replace ./midi-wildmidi.so "$wildmidi/lib/midi-wildmidi.so" \
+      --replace ./midiA-wildmidi.so "$wildmidiA/lib/midiA-wildmidi.so" \
+  '';
+
+  nativeBuildInputs = [ scons judy python nasm udis86 ];
+  buildInputs = [ SDL2 SDL2_mixer ];
+
+  NIX_CFLAGS_COMPILE = "-I${lib.getDev SDL2}/include/SDL2";
+
+  buildPhase = ''
+    scons -C SR debug=1
+
+    mkdir tmp
+    pushd tmp
+    cp ../SR-games/Albion/SR/x86/*.sci .
+    ../SR/SR.exe ${gameData.dev}/albion_main.exe Albion-main.asm
+    rm *.sci
+    python ../SR-games/Albion/SR/compact_source.py
+    nasm -felf -dELF -O1 -w+orphan-labels -w-number-overflow \
+      -i../SR-games/Albion/SR/x86/ Albion-main_linux.asm 2> a.a || :
+    python ../SR-games/Albion/SR/repair_short_jumps.py
+    popd
+
+    mv tmp/seg*.inc tmp/Albion-main.asm tmp/Albion-main_linux.asm \
+      games/Albion/SR-Main/x86
+    rm -r tmp
+
+    scons -C games/Albion/SR-Main debug=1 device=pc-linux sdl2=1
+  '';
+
+  installPhase = ''
+    install -vD -m 0644 games/Albion/release/linux/Albion.cfg \
+      "$out/etc/albion.cfg"
+    install -vD games/Albion/SR-Main/SR-Main "$out/bin/albion"
+  '';
+}) {
+  paths.required = [ "$XDG_DATA_HOME/albion" "$XDG_CONFIG_HOME/albion" ];
+  paths.runtimeVars = [ "LD_LIBRARY_PATH" ];
+}
diff --git a/pkgs/games/gog/albion/error-log-stderr.patch b/pkgs/games/gog/albion/error-log-stderr.patch
new file mode 100644
index 00000000..9819f1f1
--- /dev/null
+++ b/pkgs/games/gog/albion/error-log-stderr.patch
@@ -0,0 +1,100 @@
+diff --git a/games/Albion/SR-Main/Albion-proc-vfs.c b/games/Albion/SR-Main/Albion-proc-vfs.c
+index c3d2d4f..faa90e7 100644
+--- a/games/Albion/SR-Main/Albion-proc-vfs.c
++++ b/games/Albion/SR-Main/Albion-proc-vfs.c
+@@ -232,6 +232,8 @@ FILE *Game_fopen(const char *filename, const char *mode)
+     fprintf(stderr, "fopen: original name: %s\n", filename);
+ #endif
+ 
++    if (strcasecmp(filename, "error.log") == 0) return stderr;
++
+     vfs_err = vfs_get_real_name(filename, (char *) &temp_str, &realdir);
+ 
+ #if defined(__DEBUG__)
+@@ -260,6 +262,8 @@ int Game_open(const char *pathname, int flags, mode_t mode)
+     fprintf(stderr, "open: original name: %s\n", pathname);
+ #endif
+ 
++    if (strcasecmp(pathname, "error.log") == 0) return STDERR_FILENO;
++
+     vfs_err = vfs_get_real_name(pathname, (char *) &temp_str, &realdir);
+ 
+ #if defined(__DEBUG__)
+@@ -726,6 +730,16 @@ int Game_closedir(struct watcom_dirent *dirp)
+     return 0;
+ }
+ 
++int Game_close(int fd)
++{
++    return fd == STDERR_FILENO ? 0 : close(fd);
++}
++
++int Game_fclose(FILE *stream)
++{
++    return stream == stderr ? 0 : fclose(stream);
++}
++
+ static void Conv_find(struct watcom_find_t *buffer, struct watcom_dirent *direntp)
+ {
+     // file attributes
+diff --git a/games/Albion/SR-Main/Albion-proc-vfs.h b/games/Albion/SR-Main/Albion-proc-vfs.h
+index 0cf4491..2e16671 100644
+--- a/games/Albion/SR-Main/Albion-proc-vfs.h
++++ b/games/Albion/SR-Main/Albion-proc-vfs.h
+@@ -110,6 +110,8 @@ extern int Game_rename(const char *oldpath, const char *newpath);
+ extern struct watcom_dirent *Game_opendir(const char *dirname);
+ extern struct watcom_dirent *Game_readdir(struct watcom_dirent *dirp);
+ extern int Game_closedir(struct watcom_dirent *dirp);
++extern int Game_close(int fd);
++extern int Game_fclose(FILE *stream);
+ extern uint32_t Game_dos_findfirst(const char *path, const uint32_t attributes, struct watcom_find_t *buffer);
+ extern uint32_t Game_dos_findnext(struct watcom_find_t *buffer);
+ extern uint32_t Game_dos_findclose(struct watcom_find_t *buffer);
+diff --git a/games/Albion/SR-Main/x86/SR-asm-calls.asm b/games/Albion/SR-Main/x86/SR-asm-calls.asm
+index 3cb2cc8..e1741dc 100644
+--- a/games/Albion/SR-Main/x86/SR-asm-calls.asm
++++ b/games/Albion/SR-Main/x86/SR-asm-calls.asm
+@@ -71,6 +71,8 @@
+     %define Game_chdir _Game_chdir
+     %define close _close
+     %define Game_closedir _Game_closedir
++    %define Game_close _Game_close
++    %define Game_fclose _Game_fclose
+     %define ctime _ctime
+     %define Game_dos_findclose _Game_dos_findclose
+     %define Game_dos_findnext _Game_dos_findnext
+@@ -171,14 +173,14 @@ extern Game_WaitFor2ndVerticalRetrace
+ ; 1 param
+ extern asctime
+ extern Game_chdir
+-extern close
++extern Game_close
+ extern Game_closedir
+ extern ctime
+ extern Game_dos_findclose
+ extern Game_dos_findnext
+ extern Game_dos_getvect
+ extern Game_ExitMain_Asm
+-extern fclose
++extern Game_fclose
+ extern Game_filelength
+ extern free
+ extern ftime
+@@ -798,7 +800,7 @@ SR_j___close:
+ 
+ ; eax = int handle
+ 
+-        Game_Call_Asm_Reg1 close,'get_errno_val'
++        Game_Call_Asm_Reg1 Game_close,'get_errno_val'
+ 
+ ; end procedure SR___close
+ 
+@@ -875,7 +877,7 @@ SR_fclose:
+ 
+ ; eax = FILE *fp
+ 
+-        Game_Call_Asm_Reg1 fclose,'get_errno_val'
++        Game_Call_Asm_Reg1 Game_fclose,'get_errno_val'
+ 
+ ; end procedure SR_fclose
+ 
diff --git a/pkgs/games/gog/albion/scons.patch b/pkgs/games/gog/albion/scons.patch
new file mode 100644
index 00000000..5a1c0d7b
--- /dev/null
+++ b/pkgs/games/gog/albion/scons.patch
@@ -0,0 +1,74 @@
+diff --git a/SR/SConstruct b/SR/SConstruct
+index 2fb2874..f2fb527 100644
+--- a/SR/SConstruct
++++ b/SR/SConstruct
+@@ -20,6 +20,8 @@
+ #  SOFTWARE.
+ #
+ 
++import os
++
+ udis86_path = './udis86-1.6/'
+ 
+ # set help text
+@@ -30,7 +32,8 @@ Help(vars.GenerateHelpText(env))
+ debug = env['debug']
+ 
+ # default settings
+-env = Environment(CCFLAGS      = '-O2',
++env = Environment(ENV          = os.environ,
++                  CCFLAGS      = '-O2',
+                   CPPPATH      = '.',
+                   INCPREFIX    = '-I' + udis86_path,
+                   LIBPATH      = 'libudis86',
+diff --git a/games/Albion/SR-Main/SConstruct b/games/Albion/SR-Main/SConstruct
+index 96bbefb..6743470 100644
+--- a/games/Albion/SR-Main/SConstruct
++++ b/games/Albion/SR-Main/SConstruct
+@@ -50,12 +50,14 @@ Help(vars.GenerateHelpText(env))
+ if device == 'pc-linux':
+     # default settings
+     if sdl2 > 0:
+-        env = Environment(CCFLAGS      = '-m32 -O2 -DUSE_SDL2',
++        env = Environment(ENV          = os.environ,
++                          CCFLAGS      = '-m32 -O2 -DUSE_SDL2',
+                           LINKFLAGS    = '-m32',
+                           LIBS         = ['SDL2_mixer', 'SDL2', 'pthread', 'm', 'dl']
+                          )
+     else:
+-        env = Environment(CCFLAGS      = '-m32 -O2 -DALLOW_OPENGL',
++        env = Environment(ENV          = os.environ,
++                          CCFLAGS      = '-m32 -O2 -DALLOW_OPENGL',
+                           LINKFLAGS    = '-m32',
+                           LIBS         = ['SDL_mixer', 'SDL', 'pthread', 'm', 'dl', 'GL']
+                          )
+diff --git a/games/Albion/SR-Main/x86/SConscript b/games/Albion/SR-Main/x86/SConscript
+index c88c7e9..848efa8 100644
+--- a/games/Albion/SR-Main/x86/SConscript
++++ b/games/Albion/SR-Main/x86/SConscript
+@@ -20,6 +20,7 @@
+ #  SOFTWARE.
+ #
+ 
++import os
+ import re
+ 
+ Import('device')
+@@ -38,13 +39,13 @@ nasmscan = Scanner(function = nasmfile_scan,
+ SourceFileScanner.add_scanner('.asm', nasmscan)
+ 
+ if device == 'pc-linux':
+-    env = Environment(tools=['nasm'], ASFLAGS = ' -felf -dELF -Ox -w+orphan-labels -w-number-overflow -ix86/')
+-    env2 = Environment(tools=['nasm'], ASFLAGS = ' -felf -dELF -O1 -w+orphan-labels -w-number-overflow -ix86/')
++    env = Environment(ENV=os.environ, tools=['nasm'], ASFLAGS = ' -felf -dELF -Ox -w+orphan-labels -w-number-overflow -ix86/')
++    env2 = Environment(ENV=os.environ, tools=['nasm'], ASFLAGS = ' -felf -dELF -O1 -w+orphan-labels -w-number-overflow -ix86/')
+ 
+     obj = env2.Object('Albion-main_linux.asm')
+ else:
+-    env = Environment(tools=['nasm'], ASFLAGS = ' -fwin32 -Ox -w+orphan-labels -w-number-overflow -ix86/')
+-    env2 = Environment(tools=['nasm'], ASFLAGS = ' -fwin32 -O1 -w+orphan-labels -w-number-overflow -ix86/')
++    env = Environment(ENV=os.environ, tools=['nasm'], ASFLAGS = ' -fwin32 -Ox -w+orphan-labels -w-number-overflow -ix86/')
++    env2 = Environment(ENV=os.environ, tools=['nasm'], ASFLAGS = ' -fwin32 -O1 -w+orphan-labels -w-number-overflow -ix86/')
+ 
+     obj = env2.Object('Albion-main.asm')
+ 
diff --git a/pkgs/games/gog/albion/sdl2.patch b/pkgs/games/gog/albion/sdl2.patch
new file mode 100644
index 00000000..6b4bc93f
--- /dev/null
+++ b/pkgs/games/gog/albion/sdl2.patch
@@ -0,0 +1,60 @@
+diff --git a/games/Albion/SR-Main/Albion-proc-events.c b/games/Albion/SR-Main/Albion-proc-events.c
+index c323530..97eedd1 100644
+--- a/games/Albion/SR-Main/Albion-proc-events.c
++++ b/games/Albion/SR-Main/Albion-proc-events.c
+@@ -893,19 +893,19 @@ void Game_ProcessKEvents(void)
+                     else goto _after_switch1;
+             #endif
+                 }
+-                else if ((cevent->key.keysym.unicode > 0) && (cevent->key.keysym.unicode < 128))
++                else if ((cevent->key.keysym.sym > 0) && (cevent->key.keysym.sym < 128))
+                 {
+-                    scancode = scancode_table[cevent->key.keysym.unicode];
+-                    ascii_code = cevent->key.keysym.unicode;
++                    scancode = scancode_table[cevent->key.keysym.sym];
++                    ascii_code = cevent->key.keysym.sym;
+                 }
+-                else if (cevent->key.keysym.unicode != 0)
++                else if (cevent->key.keysym.sym != 0)
+                 {
+                     scancode = 0;
+                     ascii_code = 0;
+ 
+                     if ((ascii_code == 0) && (Albion_Font_Lang != AL_UNKNOWN))
+                     {
+-                        switch (cevent->key.keysym.unicode)
++                        switch (cevent->key.keysym.sym)
+                         {
+                             case 0x00E4: // ä
+                                 ascii_code = 0x84;
+@@ -935,7 +935,7 @@ void Game_ProcessKEvents(void)
+ 
+                     if ((ascii_code == 0) && (Albion_Font_Lang == AL_ENG_FRE))
+                     {
+-                        switch (cevent->key.keysym.unicode)
++                        switch (cevent->key.keysym.sym)
+                         {
+                             case 0x00E9: // é
+                                 ascii_code = 0x82;
+@@ -998,7 +998,7 @@ void Game_ProcessKEvents(void)
+ 
+                     if ((ascii_code == 0) && (Albion_Font_Lang == AL_CZE))
+                     {
+-                        switch (cevent->key.keysym.unicode)
++                        switch (cevent->key.keysym.sym)
+                         {
+                             case 0x00E9: // é
+                                 ascii_code = 0x82;
+diff --git a/games/Albion/SR-Main/main.c b/games/Albion/SR-Main/main.c
+index c9c3125..0d32bcb 100644
+--- a/games/Albion/SR-Main/main.c
++++ b/games/Albion/SR-Main/main.c
+@@ -930,8 +930,6 @@ static void Game_Initialize2(void)
+     Init_Audio2();
+     Init_Input2();
+ 
+-    SDL_EnableUNICODE(1);
+-
+     Game_VideoAspectX = (360 << 16) / Picture_Width;
+     Game_VideoAspectY = (240 << 16) / Picture_Height;
+ 
diff --git a/pkgs/games/gog/albion/xdg-paths.patch b/pkgs/games/gog/albion/xdg-paths.patch
new file mode 100644
index 00000000..13ba4a1c
--- /dev/null
+++ b/pkgs/games/gog/albion/xdg-paths.patch
@@ -0,0 +1,259 @@
+diff --git a/games/Albion/SR-Main/virtualfs.c b/games/Albion/SR-Main/virtualfs.c
+index 34e0544..7d3acec 100644
+--- a/games/Albion/SR-Main/virtualfs.c
++++ b/games/Albion/SR-Main/virtualfs.c
+@@ -22,7 +22,9 @@
+  *
+  */
+ 
++#define _GNU_SOURCE
+ #define _FILE_OFFSET_BITS 64
++#include <fcntl.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <malloc.h>
+@@ -283,6 +285,177 @@ void vfs_visit_dir(file_entry *vdir)
+     vdir->dir_visited = 1;
+ }
+ 
++#define CONCAT_ENV(path) \
++    if (asprintf(&result, "%s/%s", env, path) == -1) { \
++        perror("asprintf"); \
++        exit(1); \
++    }
++
++#define DEFINE_XDG_GETTER(fun_name, envar, fallback) \
++    static char *fun_name(void) { \
++        const char *env; \
++        static char *result = NULL; \
++        if (result == NULL) { \
++            if ((env = getenv(envar)) != NULL) { \
++                CONCAT_ENV("albion"); \
++            } else if ((env = getenv("HOME")) != NULL) { \
++                CONCAT_ENV(fallback "/albion"); \
++            } else { \
++                fputs("Unable to determine " envar " or HOME.\n", stderr); \
++                exit(1); \
++            } \
++        } \
++        return result; \
++    }
++
++DEFINE_XDG_GETTER(getDataDir, "XDG_DATA_HOME", ".local/share");
++DEFINE_XDG_GETTER(getConfigDir, "XDG_CONFIG_HOME", ".config");
++
++static int makeDirs(const char *path)
++{
++    char *buf, *p;
++
++    if (*path == '\0')
++        return 1;
++
++    if ((buf = strdup(path)) == NULL)
++        return 1;
++
++    for (p = buf + 1; *p != '\0'; p++) {
++        if (*p != '/') continue;
++        *p = '\0';
++        mkdir(buf, 0777);
++        *p = '/';
++    }
++
++    mkdir(buf, 0777);
++
++    free(buf);
++    return 0;
++}
++
++typedef struct {
++    file_entry *dir;
++    const char *root;
++} unix_dir_cache_t;
++
++unix_dir_cache_t *unixDirCache[100];
++
++static void setUnixDir(const char *root, file_entry **dir)
++{
++    int i;
++    file_entry *newdir;
++
++    if (dir == NULL)
++        return;
++
++    for (i = 0; unixDirCache[i] != NULL; ++i) {
++        if (strcmp(unixDirCache[i]->root, root) == 0) {
++            *dir = unixDirCache[i]->dir;
++            return;
++        }
++    }
++
++    if ((newdir = (file_entry *)malloc(sizeof(file_entry))) == NULL)
++        return;
++
++    memset(newdir, 0, sizeof(file_entry));
++
++    newdir->dos_name[0] = 'X';
++    newdir->dos_name[1] = ':';
++    newdir->dos_name[2] = '\0';
++
++    newdir->real_name[0] = '.';
++    newdir->real_name[1] = '\0';
++
++    newdir->dos_fullname = strdup(newdir->dos_name);
++    newdir->real_fullname = strdup(root);
++
++    newdir->attributes = 1;
++    newdir->dir_visited = 0;
++
++    newdir->parent = newdir;
++    newdir->next = NULL;
++    newdir->prev = NULL;
++    newdir->first_child = NULL;
++    *dir = newdir;
++
++    unixDirCache[i] = (unix_dir_cache_t*)malloc(sizeof(unix_dir_cache_t));
++    if (unixDirCache[i] != NULL) {
++        makeDirs(root);
++        unixDirCache[i]->root = strdup(root);
++        unixDirCache[i]->dir = newdir;
++    }
++}
++
++static const char *manglePath(const char *xdg_path, const char *subdir,
++                              const char *path, file_entry **dir)
++{
++    char *buf;
++
++    if (*path == '/' || *path == '\\')
++        path++;
++
++    if (subdir == NULL) {
++        setUnixDir(xdg_path, dir);
++        return path;
++    }
++
++    if (asprintf(&buf, "%s/%s", xdg_path, subdir) == -1)
++        return NULL;
++
++    setUnixDir(buf, dir);
++    free(buf);
++    return path;
++}
++
++#define MANGLE_PATH(xdgpath, subdir, off) \
++    origdosname = manglePath(xdgpath, subdir, origdosname + off, &parse_dir)
++
++static void maybeCreateSetupIni()
++{
++    char *buf;
++    int fd_in, fd_out;
++    static int done = 0;
++
++    if (done) return;
++
++    if (asprintf(&buf, "%s/%s", getConfigDir(), "setup.ini") == -1) {
++        return;
++    }
++
++    if (access(buf, F_OK) == 0) {
++        done = 1;
++        free(buf);
++        return;
++    }
++
++    makeDirs(getConfigDir());
++
++    fd_out = open(buf, O_WRONLY | O_CREAT, 0666);
++    free(buf);
++
++    if (fd_out == -1)
++        return;
++
++    if ((fd_in = open("@SETUP_INI_PATH@", O_RDONLY)) == -1) {
++        close(fd_out);
++        return;
++    }
++
++    buf = malloc(8192);
++
++    while (1) {
++        ssize_t result = read(fd_in, buf, 8192);
++        if (result == -1 || result == 0) break;
++        if (write(fd_out, buf, result) != result) break;
++    }
++
++    close(fd_in);
++    close(fd_out);
++    done = 1;
++}
++
+ /*
+ return value:
+ 0 - dos path found (realdir = found entry)
+@@ -292,9 +465,20 @@ return value:
+ int vfs_get_real_name(const char *origdosname, char *buf, file_entry **realdir)
+ {
+     char upperdosname[MAX_PATH], *dosname, *backslash;
+-    file_entry *parse_dir, *new_parse_dir;
++    file_entry *parse_dir = NULL, *new_parse_dir;
+     int ret;
+ 
++    if (strncasecmp(origdosname, "xldlibs\\current", 15) == 0) {
++        MANGLE_PATH(getDataDir(), "chars", 15);
++    } else if (strncasecmp(origdosname, "saves", 5) == 0) {
++        MANGLE_PATH(getDataDir(), "saves", 5);
++    } else if (strncasecmp(origdosname, "setup.ini", 10) == 0) {
++        maybeCreateSetupIni();
++        MANGLE_PATH(getConfigDir(), NULL, 0);
++    } else if (strncasecmp(origdosname, "setup.tmp", 10) == 0) {
++        MANGLE_PATH(getConfigDir(), NULL, 0);
++    }
++
+     // convert dos name to uppercase
+     {
+         int i;
+@@ -316,28 +500,30 @@ int vfs_get_real_name(const char *origdosname, char *buf, file_entry **realdir)
+ 
+ 
+     // find initial directory for parsing
+-    if (dosname[0] == '\\')
+-    {
+-        parse_dir = &Game_CDir;
+-        dosname++;
+-    }
+-    else if (dosname[0] == 'C' && dosname[1] == ':')
+-    {
+-        if (dosname[2] == '\\')
++    if (parse_dir == NULL) {
++        if (dosname[0] == '\\')
+         {
+             parse_dir = &Game_CDir;
+-            dosname+=3;
++            dosname++;
++        }
++        else if (dosname[0] == 'C' && dosname[1] == ':')
++        {
++            if (dosname[2] == '\\')
++            {
++                parse_dir = &Game_CDir;
++                dosname+=3;
++            }
++            else
++            {
++                parse_dir = Game_Current_Dir;
++                dosname+=2;
++            }
+         }
+         else
+         {
+             parse_dir = Game_Current_Dir;
+-            dosname+=2;
+         }
+     }
+-    else
+-    {
+-        parse_dir = Game_Current_Dir;
+-    }
+ 
+     // find directory
+     for (backslash = strchr(dosname, '\\'); backslash != NULL; backslash = strchr(dosname, '\\'))
diff --git a/pkgs/games/gog/default.nix b/pkgs/games/gog/default.nix
index 111091c3..8d8379a3 100644
--- a/pkgs/games/gog/default.nix
+++ b/pkgs/games/gog/default.nix
@@ -10,6 +10,8 @@ let
     fetchGog = callPackage ./fetch-gog {
       inherit (config.gog) email password;
     };
+
+    albion = callPackage_i686 ./albion { inherit (pkgs) buildSandbox; };
   };
 in {
   options.gog = {