Loki logo

Loki games on modern Linux

The Games that Linux People Play


Between 1999 and 2002, Loki Software released native Linux version of a small list of contemporary commercial games.

If you're too young and have not lived those glorious days, here is a backup of their old (now broken) website so that you could feel the thrill. The FAQ is of no help today, but if you want see how the birth of the modern Linux game industry looked like, don't be shy and check out ;)

The Linux of year 2000 is very different from the Linux we know today, and so it can be quite difficult to get such old binaries working well on modern systems. While the Linux kernel has maintained very good backwards compatibility, other parts of a Linux distribution have changed, from the X server to libraries glibc, libstdc++, and SDL.

The Problems

The dynamically-linked binaries segfault, or are missing important feature.

The Bad Ideas

Using the static binaries does work on modern systems, but is problematic as the libraries compiled into them are old and have bugs; for example:

Another popular solution is to use an old version of glibc such as 2.2.5. However all the other libraries linked by the game must also be compiled against an equally old (or older) version of glibc. This is the "traditional way" of running these old games, by using the infamous loki_compat_libs-1.5.tar.bz2 compilation. However, they're not up-to-date enough to support PulseAudio/PipeWire, or any of the more modern parts of the Linux graphics stack, so ultimately don't solve all of the problems.

The Solution

  1. The idea is to use a little shim that adds back functions required by the old dynamically-linked binaries.
    This way you still run a modern stack with a recent glibc, latest xorg/wayland, Mesa, ...

  2. elfhash will be used to rename symbols to prevent clashes with system libraries.

  3. SDL

    Games were often build against libSDL-1.1.so.0 which is both very old, and unavailable in modern distribution. But it is ABI compatible with libSDL-1.2.so.0 that was the main version of SDL used for a decade and that was updated to support newer systems. patchelf will be used to change the dependency to SDL 1.2.

    But the story doesn't end there. SDL 1.2 was superseded by SDL 2.0 back in 2014 (and, indeed, SDL 3.0 is currently being worked on in 2024). SDL 2.0 is much more suited to modern hardware and operating systems than SDL 1.2 ever was. Not only does it provide native support for newer APIs like Wayland and Pipewire, it also supports newer ways of handling fullscreen windows (without nasty resolution changes or breaking Alt+Tab) and provides a hardware-accelerated 2D API which is much better suited to modern GPUs.

    SDL2's API is, while reminiscent of SDL 1.2's, not compatible, and indeed lacks some features. Some sort of compatibility layer is needed to adapt the old API into the new one, and to restore or emulate the missing functionality. Fortunately, such a compatibility layer already exists: sdl12-compat. Most Linux distros ship sdl12-compat instead of the original SDL 1.2 library, so you're likely already using it.

  4. Sound

    Some games use the original sound system for Linux, OSS, that was superseded by ALSA in 2002. On modern Linux, there is no more a /dev/dsp device file.

    There is an elegant solution to this problem: osspd. It's a userspace daemon that emulate the OSS devices (/dev/dsp, /dev/adsp and /dev/mixer).

    In the end the pipeline looks like this (it's a lot of forwarding, but on modern machines, it won't be too noticeable) :

    game-binary -> /dev/dsp -> CUSE -> osspd -> ossp-padsp -> pulseaudio -> ALSA -> speakers/headphones


Thanks to Ryan C. Gordon and Sam Lantinga, they both worked at Loki back in the days and still work today on tools (like the SDL) we can use to make & play games on Linux.

I must credit David Gow for his technical article that prompted me to do some research and replay those old games :-)

The Games

Assuming the games are patched to the latest available patches (and there are never going to be newer patches) then to run them use the following instructions. The dynamic binaries are used where available.

Don't forget to export one of those environment variables, to prevent your graphics driver to expose an outrageously long list of OpenGL extensions.

$ export MESA_EXTENSION_MAX_YEAR=2002       # Mesa
$ export __GL_ExtensionStringVersion=17700  # Nvidia

If you don't do that, some games (heretic2, kingpin, shogo, sin, sof) will crash on startup.


Credits: https://davidgow.net/hacks/civctp.html


Path the binary:

$ patchelf --replace-needed libSDL_mixer-1.0.so.0 libSDL_mixer-1.2.so.0 civctp.dynamic
$ patchelf --replace-needed libSDL-1.1.so.0 libSDL-1.2.so.0 civctp.dynamic
$ perl -pe 's/\x{E8}\x{F5}\x{96}\x{B6}\x{FF}\x{89}\x{C0}\x{89}\x{45}\x{FC}\x{8B}\x{43}\x{04}\x{3B}\x{45}\x{FC}\x{75}\x{05}\x{FF}\x{43}\x{08}\x{EB}\x{14}/\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}/' < civctp.dynamic > civctp.dynamic_tmp
$ perl -pe 's/\x{83}\x{7B}\x{08}\x{00}\x{7E}\x{05}\x{FF}\x{4B}\x{08}\x{EB}\x{15}/\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}\x{90}/' < civctp.dynamic_tmp > civctp.dynamic

Run the game:

SDL12COMPAT_FAKE_CDROM_PATH=/path/to/soundtrack LD_LIBRARY_PATH=$(pwd) LD_PRELOAD=/path/to/lokishim.so ./civctp.dynamic


LD_PRELOAD=/path/to/lokishim.so ./descent3.dynamic



Path the binary:

patchelf --replace-needed libSDL-1.1.so.0 libSDL-1.2.so.0 hg2stub

Run the game:



Unfortunately the binary is statically linked with an old SDL, so we are stuck with it and it's bugs.
It is recommended to use the pak4.pk3 file provided by Chunky Kibbles to fix a crashing problem during the game.

./fakk2 -w +set r_gldriver /usr/lib/i386-linux-gnu/libGL.so.1


Unfortunately, even the "dynamic" binary is statically linked with an old SDL, so we are stuck with that version and it's bugs

Path the binary:

$ patchelf --remove-needed libesd.so.0 heretic2.dynamic

Run the game:

./heretic2.dynamic +set vid_ref glx +set gl_driver /usr/lib/i386-linux-gnu/libGL.so.1


SDL12COMPAT_COMPATIBILITY_AUDIOCVT=1 LD_PRELOAD=/path/to/lokishim.so ./heroes3.dynamic


LD_PRELOAD=/path/to/lokishim.so:libX11.so.6 ./kohan.dynamic


TODO - Only static binaries on CD.


The folks at Project Magma took over maintenance and have continued to release binaries for Linux up to 2021, so the old Loki binaries aren't needed anymore

Postal Plus

TODO - Only static binary on CD.

A new native (SDL2 based) Linux version is available for free on Steam.


Path the binary:

$ patchelf --replace-needed libSDL-1.1.so.0 libSDL-1.2.so.0 rt2.dynamic

Run the game:

SDL12COMPAT_FAKE_CDROM_PATH=/path/to/soundtrack LD_PRELOAD=libX11.so.6 ./rt2.dynamic


Path the binary:

$ elfhash -f __dynamic_cast -t __dynloki_cast System/Core.so

Run the game:

./System/rune-bin -log


LD_PRELOAD=/path/to/lokishim.so ./smac.dynamic
LD_PRELOAD=/path/to/lokishim.so ./smacx.dynamic


Use this shim: https://github.com/twolife/sc3u-nptl

TODO: libopenal-0.0.so

Path the binaries:

$ patchelf --replace-needed libSDL-1.1.so.0 libSDL-1.2.so.0 sc3u.dynamic
$ patchelf --replace-needed libSDL-1.1.so.0 libSDL-1.2.so.0 sc3bat.dynamic

Run the game:

LD_LIBRARY_PATH=$(pwd) LD_PRELOAD=/path/to/sc3u-nptl.so:libstdc++-libc6.2-2.so.3 ./sc3u.dynamic


Path the binary:

$ elfhash -f sl_add -t sl_adx liboasnd.so
$ patchelf --replace-needed libSDL-1.1.so.0 libSDL-1.2.so.0 sof-bin

Run the game:


Tribes 2

TODO - or not, masterserver have been down for years


OldUnreal took over maintenance of the Unreal Tournament code base after reaching an agreement with Epic Games in 2019. So the old Loki binaries have modern replacement and aren't needed anymore.


Other games from the same era

In 2000-2001 Hyperion Entertainment did port and released 2 more games of interest, that suffers from the same problems as the Loki ones.


Path the binaries:

$ patchelf --replace-needed libSDL-1.1.so.0 libSDL-1.2.so.0 cdaudio.dll
$ patchelf --replace-needed libSDL-1.1.so.0 libSDL-1.2.so.0 client
$ patchelf --replace-needed libSDL-1.1.so.0 libSDL-1.2.so.0 shogolauncher

Run the game:

LD_PRELOAD=/path/to/lokishim.so ./shogo

It may run too fast on modern computers. Add "MaxFPS" "30" to the ~/.hyperion/Shogo/autoexec.cfg configuration file.


Path the binary:

$ patchelf --remove-needed libSDL-1.1.so.0 sin.exe

Run the game:

LD_PRELOAD=/path/to/lokishim.so ./sin.exe +set vid_ref gl +set gl_driver_lib /usr/lib/i386-linux-gnu/libGL.so.1