Soldier of Fortune on modern Linux

Somewhere around 2000, Loki Games released the native Linux version. I bought the CD back then. I still enjoy this game, so I've invested some time getting it working on modern systems. I've identified the following issues with getting SoF working, read on for solutions. NOTE: This is for the original native Linux version. NOT the Windows version in Wine/Windows.

  1. Installer does not run
  2. Game is 32 bit
  3. Game crash on start
  4. No sound
  5. Game does not support desired resolution

The list of problems is not as short as we'd like, but fortunately, there are easy fixes for all of them,

1. Installer does not run

No problem! Installers are for the weak!
Mount your CD (or, if you're somewhat sane, you ripped your CD so you have the ISO on hand. Create a destination directory, and copy the files.

sudo mount -o loop SoF.iso /mnt
mkdir $HOME/sof
cd /mnt
tar -xf paks.tar.gz -C $HOME/sof/
tar -xf binaries.tar.gz -C $HOME/sof/
cp bin/x86/glibc-2.1/sof $HOME/sof/

Done! That's the installation taken care of, but it probably won't run quite yet!

2. Game is 32 bit

Soldier of Fortune is a 32 bit game, that means it was compiled for 32 bit machines, and linked to 32 bit libraries. So if you are running 64 bit Linux, you may need to install a few 32 bit libaries, luckily, modern Linux distributions (still) have elegant support for this.

Before installing additional packages, try running ./sof and see what happens. If it complains, something like 'error while loading shared libraries' then no worries, you'll just need to identify which libraries to install, they are all available!

I went ahead and resolved the most likely dependencies, so start by installing the 32 bit versions of those packages, note that I'm also including the version, not because that exact version is required, but because I know it works at least with that version.

ii libc6:i386 2.27-3ubuntu1 i386 GNU C Library: Shared libraries
ii libx11-6:i386 2:1.6.4-3 i386 X11 client-side library
ii libxext6:i386 2:1.3.3-1 i386 X11 miscellaneous extension library
ii libxcb1:i386 1.13-1 i386 X C Binding
ii libxau6:i386 1:1.0.8-1 i386 X11 authorisation library
ii libxdmcp6:i386 1:1.1.2-3 i386 X11 Display Manager Control Protocol library
ii libbsd0:i386 0.8.7-1 i386 utility functions from BSD systems - shared library

There may be others, but I didn't find them, give it a try, I'm sure you'll get it working even if I missed a few. Here is a list of all 32bit libs on my system, you certainly won't need all of those.. But just in case. Also, here is the linkage info from ldd for the binaries, note those "not found" are just local files, that's no problem.

3. Game crash on start

If running ./sof greets you with the "Fatal signal: Segmentation Fault (SDL Parachute Deployed)" then there is both a simple reason and solution. Here is the full output from a crash:sof-crashlog.txt. What happens is simple: The ref_gl.so library wants to write a nice list of OpenGL extentions. In order to do so, it sets aside a rather large (for the time) buffer, of 8192 bytes, for writing a text-string. It then passes this buffer, along with the format string "GL_EXTENSIONS: %s\n" and a buffer containing all the extensions, to vsprintf. vsprintf then writes the string.. But.. What happens if the buffer with the extensions happen to be longer than the allocated 8192 bytes? Nothing good. The program will (in best cases) crash after overwriting instruction memory with text data.

There are several ways to fix this, the most simple, being to never let vsprintf write to the buffer. See, it's actually a message console, it's never used for anything in the program! How lucky we are, that the only critical of these bugs seem to be in the printing of a console log message!

The easy fix!

The file responsible for this behaviour is ref_gl.so, I don't have the source code for this file, and I don't know if it is considered a part of SoF, but I assume it is. Therefore, I will not be able to provide a fixed file for download, but I am able to instruct you how to fix it yourself. This fix is rather crude, so, take a backup of the file first!

Open the ref_gl.so file in bless, or another hex-editor. These instructions are for bless. Press ctrl+f and type GL_EXTENSIONS, change type from HEX to String, press "Find Next". Now, replace the % with a space. That is, make sure you put another characther, for example, a space, at its place. There are two strings, so, press "Find Next" again, and repeat the process, then save the file. If in doubt, see the video I recorded (flv format, 2.7 MiB).

4. No sound

NOTE:I've seen it crash when using the padsp script, if it crashes after showing video AND a short amount of audio, then don't use padsp.. I'm investigating a fix..

If you're using pulseaudio, you may have trouble getting sound to work, the pulseaudio-utils:i386 package contains a script called padsp, which you can source to make audio work. So go ahead and install that if required. The resolution-hack detailed below also mentions how to modify the "sof" script to include the audio fix.

5. Game does not support desired dresolution

I made a small hack to allow you to play SoF in any resolution you want (The famous SoF Resolution Hack).

It works by preloading a bit of code that will plug a different resolution into the memory structure that the game engine uses to set the OpenGL display resolution.

screenshot

Download

Binary and source: SofResolutionHack.tar.gz 4264 Bytes,(SHA256:3cf017a729842b0d1c9e765154318f151f3210c2f34b113112e5b3999d56f527)

NOTE: Since the instructions above does not generate a config file, step 1 can be skipped, as far as I can tell, the default mode is 3, so I've made the hook active on that mode as well as mode 9.

README.txt

Using this hack is very easy. 3 steps.
 - If you don't use pulseaudio, remove the . padsp line mentioned below.
 - If you want another resolution, simply replace 2560 and 1440 with the width and height you want.

* 0. Copy ResHook.so into your sof directory so it is next to the sof and sof-bin files.
* 1. Open ~/.loki/sof/config.cfg and set gl_mode "9" ( or 3, the default mode)
* 2. Open the sof file inside the sof directory with an editor, go to the end of the file and replace:

  if [ -x "${SOF_DATA_PATH}/sof-bin" ]; then
          ${SOF_DATA_PATH}/sof-bin $*
  fi

* With:

export SOF_WIDTH=2560
export SOF_HEIGHT=1440
. padsp
export LD_PRELOAD="$LD_PRELOAD $SOF_DATA_PATH/ResHook.so"

if [ -x "${SOF_DATA_PATH}/sof-bin" ]; then
        ${SOF_DATA_PATH}/sof-bin $*
fi


**** NOTES FOR 64 bit systems!
To build the hook you need to install libc6-dev-i386