Getting UT436 to run again in 2025, mostly for compatibility checks.
The original installer, ut-install-436.run is broken these days:
$ ./ut-install-436.run --extract-only
Verifying archive integrity...tail: cannot open '+6' for reading: No such file or directory
Error in check sums 1237260170 2341625838
It exercises a call syntax that is no longer supported.
Replacing tail +6
by tail -n +6
leads to the next
error:
Verifying archive integrity...Error in check sums 2463042252 2341625838
Something is wrong with the checksumming. There is an `exit 1` statement in the if..else branch where the checksum failure is evaluated. Removing that (in other words, "proceed even with faulty checksum"), the next error encountered is:
trap: usage: trap [-lp] [[arg] signal_spec ...]
The call to trap
is missing the signal
specification. After adding the missing ERR
argument to the
trap command like so:
-[ "$keep" = y ] || trap 'cd /tmp; /bin/rm -rf $tmpdir; exit $res'
+[ "$keep" = y ] || trap 'cd /tmp; /bin/rm -rf $tmpdir; exit $res' ERR
we get to the next issue:
Verifying archive integrity...Error in check sums 388931346 2341625838
OK
Uncompressing Unreal Tournament version 436 Linux install
gzip: stdin: not in gzip format
tar: This does not look like a tar archive
tar: Exiting with failure status due to previous errors
./436.run: line 162: ./setup.sh: No such file or directory
At this point, I found it to be easier to just rip the compressed part off manually with a hex editor or similar utilities, in this case I used GNU ddrescue. Once the compressed portion of the .run file is extracted, you will find some more archives and another setup program (graphical installer portion). Needless to say, that setup program fails for similar reasons, depending on archaic command-line program behavior or something. Anyway, there is luckily no need to run the graphical installer, as the Linux parts of UT are conveniently packaged in data.tar.gz, which just needs to be unpacked. All in all, like so:
$ hexdump -C ut-install-436.run
...
000016d0 73 0a 45 4e 44 5f 4f 46 5f 53 54 55 42 0a 1f 8b |s.END_OF_STUB...|
...
$ ddrescue ut-install-436.run 436.tgz -i 0x16de -o 0
$ mkdir x436
$ tar -C x436 -xf 436.tgz
$ tar -C ~/ut99isounpacked -xvf x436/data.tar.gz
$ cd x436/setup.data; ./bin/Linux/x86/loki_patch patch.dat ~/ut99isounpacked
You must run loki_patch. Luckily, this program seems to be trivial enough (and originally written in C or so) that it does not depend on changed sh behavior. If you were to ignore loki_patch, ut-bin later would otherwise die with:
appError called:
Class Actor Member Owner problem: Script=48 C++=52
With loki_patch having completed, now tend to the library
requirements for ut-bin. As ldd ut-bin
will show, libnsl1-32bit,
libX11-6-32bit and libXext6-32bit are needed. Use the system package to install
them. Running ut-bin then gives the following new errors:
Initializing OpenGLDrv...
binding libGL.so.1
appError called:
Could not load OpenGL library
cd ~/ut99isounpacked/System/
$ ./ut-bin -log
Failed to load 'WinDrv': Can't find file for package 'WinDrv'
Failed to load 'Class WinDrv.WindowsClient': Can't find file for package 'WinDrv'
Can't find file for package 'WinDrv'
appError called:
Can't find file for package 'WinDrv'
Executing UObject::StaticShutdownAfterError
Signal: SIGIOT [iot trap]
Aborting.
Exiting.
Name subsystem shut down
The INI file still declares WinDrv. At this point you need to extract OpenGL.ini.tar.gz. This file is somewhere alongside data.tar.gz from earlier:
$ cd ~/ut99isounpacked; tar -xvf $path_to_x436/OpenGL.ini.tar.gz
If you get
$ ./ut-bin -log
...
Input system initialized for SDLViewport0
Opening SDL viewport.
Bound to OpenGLDrv.so
Loaded render device class.
Initializing OpenGLDrv...
binding libGL.so.1
appError called:
Could not load OpenGL
This points to Mesa-libGL1-32bit being absent. (Because OpenGLDrv.so is dlopened, it could not be spotted earlier when we ran ldd.) Install it.
If you get
binding libGL.so.1
Resizing SDL viewport. X: 0 Y: 0
OpenGL
appError called:
Couldn't set video mode: No video modes supported. (??)
you still have INI problems.
436 ought to run now.
binding libGL.so.1
Resizing SDL viewport. X: 640 Y: 480
OpenGL
GL_VENDOR : Intel
GL_RENDERER : Mesa Intel(R) Iris(R) Xe Graphics (TGL GT2)
GL_VERSION : 4.6 (Compatibility Profile) Mesa 25.0.0
GL_EXTENSIONS : GL_ARB_multisample...
Device supports: GL
Device supports: GL_EXT_bgra
...
Bound to ALAudio.so
open /dev/dsp: No such file or directory
Audio initialization failed.
Game engine initialized
Startup time: 0.863434 seconds.
Entering main loop.
URL: Adding default option Name=Player
URL: Adding default option Class=Botpack.TMale2
URL: Adding default option team=255
URL: Adding default option skin=SoldierSkins.blkt
URL: Adding default option Face=SoldierSkins.Othello
Browse: Index.unr?entry?Name=Player?Class=Botpack.TMale2?team=255?skin=SoldierSkins.blkt?Face=SoldierSkins.Othello
To remedy the audio issue, load the OSS emulation layer. Install alsa-oss-32bit, libasound2-32bit, and, because of dlopen and $modern_userspace, also libpulse0-32bit and pipewire-alsa-32bit.
LD_PRELOAD=/usr/lib/libaoss.so.0 ./ut-bin
With emission over pipewire and Bluetooth, sound is pretty broken. This may be the result of all the newfangled technology and nobody ever anticipated stacking so many compat layers.
If you run into a symbol error involving GLIBC_ or GLIBCXX_ (I think this was with v451), this is because the bundled libstdc++.so.6 is disliked by the system ld.so/by the system libc.so. Fixable by simply force-loading the system-provided first (UT's own libstdc++ is then disregarded):
LD_PRELOAD=/usr/lib/libstdc++.so.6:/usr/lib/libaoss.so.0 ./ut-bin