CompilingTTDPatchOnLinux
This page tells you what you need to do to compile TTDPatch on Linux. This won't make actual Linux binaries, so you still need to run it through Wine or VMWare or similar. However, it makes it possible to do all the development work without having to boot Windows.
First of all, get the sources for TTDPatch 2.0.1 alpha 49 or higher. The Makefile included with older versions isn't set up to support cross compiliation on Linux.
When you're ready, edit Makefile.local (make will create it on first run if you don't have one yet) to use the following definitions:
WINCC = CROSS
HOST = INTEL
After that, it should automatically use the right compiler and settings. If your mingw32 is not 3.4.0 or higher, you'll also have to uncomment the last line that changes -mtune to -mcpu (but make sure it changes CFLAGS-CROSS not CFLAGS-CYGWIN). Finally, if you don't have the upx executable packer, uncomment the NOUPX line.
Part 1 - Compiling the Windows version of TTDPatch
If your distribution has a mingw32 gcc cross compiler
- Install the mingw32 gcc cross compiler together with the corresponding binutils and runtime. E.g. on debian-based distros, try "apt-get install mingw32 mingw32-binutils mingw32-runtime".
- The patch Makefile assumes that this compiler is called i686-pc-mingw32-gcc. If it has a different name (try "find /usr -name \*mingw32\*gcc" to find out), you need to edit the Makefile
- For patch sources 2.5 beta 2 or higher, define the compiler prefix in Makefile.local. This should be the filename you found above minus the -gcc part. The following example works for Ubuntu:
- CROSS-PREFIX = i586-mingw32msvc
- For patch sources before 2.5 beta 2, you need to change Makefile.setup: modify all occurences of "i686-pc-mingw32" to match your compiler prefix.
If you don't have a mingw32 gcc cross compiler
If your distribution doesn't comes with one, the following instructions tell you how to make one. They assume that you already have a working mingw32 compiler from the cygwin suite, or at least the mingw32 headers and runtime libraries.
If you don't have Cygwin installed, you can just download the packages "w32api" and "mingw-runtime" from a Cygwin mirror and install them manually. In that case, use these packages instead of files from /mnt/d/cygwin below. (This is just a shortcut to avoid having to compile the runtime and libraries as well.)
- this assumes you have cygwin installed in /mnt/d/cygwin and the TTDPatch source tree in /mnt/d/ttdpatch, and that the cross compiler will be installed in /usr/i686-pc-mingw32 with executables in /usr/bin having an i686-pc-mingw32 prefix. Modify as appropriate.
- get the GNU binutils source, unpack, change to source dir; it needs to be a version no older than 2005 for correct linking of the Windows executables
- configure, compile and install (for the latter you probably need to be root or use sudo):
- ./configure --prefix=/usr --target=i686-pc-mingw32
- make
- make install
- setup the includes and libraries for mingw32 from your cygwin installation
- cd /usr/i686-pc-mingw32
- mkdir -p include sys-include lib
- cp -a /mnt/d/cygwin/usr/include/mingw/* include
- cp -a /mnt/d/cygwin/usr/include/w32api/* sys-include
- cp -a /mnt/d/cygwin/lib/mingw/* lib
- cp -a /mnt/d/cygwin/lib/w32api/* lib
- get the gcc-core source, unpack, change to source dir. (I used gcc-core-3.4.1-1-src.tar.bz2 from the cygwin archives, untared it, untared the gcc-core-3.4.1.tar.bz2 contained but didn't apply the patch)
- compile it, pick the same prefix as above obviously:
- ./configure --prefix=/usr --target=i686-pc-mingw32
- make
- make install
- put the nasm executable distributed with alpha 50 or higher in your path before any other nasm executables (or overwrite any existing ones in /usr/bin or wherever it is). If this doesn't work for you e.g. due to library incompatibilities, get the nasm sources (0.98.39 or higher), unpack, change to the source dir
- install the TTDPatch nasm patches
- zcat /mnt/d/ttdpatch/nasm/*.gz|patch -p1
- compile nasm:
- ~./configure --prefix=/usr
- make
- make install
- make sure the patch Makefile.local has WINCC set to LINUX (default is CYGWIN) and set the HOST as appropriate to INTEL or PPC depending on the CPU of the computer you're compiling on
- now try compiling the patch with
- make allw
Please report any problems, errors or other difficulties so I may update and improve these instructions.
Part 2 - Compiling the DOS version of TTDPatch
This can be done by building the OpenWatcom compiler for Linux. OpenWatcom automatically supports all targets, so you just build it as a regular compiler. Here are the steps that worked for compiling OpenWatcom 1.4 on Linux.
- get the .tar.bz2 version of the latest OpenWatcom source, and unpack it. (note, you'll need about 400-500 MB space to compile it)
- run the compiler bootstrap
- . build.sh (if that doesn't work, try ./build.sh)
- build the rest of the stuff we need and copy to rel2:
- . setvars.sh
- cd clib
- builder rel2
- cd ../mathlib
- builder rel2
- cd ../emu86
- builder rel2
- Building the clib takes a while, there should be a way to make only the libs for a certain target system but I couldn't figure it out.
- Copy the binaries, headers and libraries:
- cd rel2
- cp -a binl binw h lh lib286 /usr/local/openwatcom
- Copy setvars.sh to /usr/local/openwatcom/setvars and edit these:
- export OWROOT=/usr/local/openwatcom
- export WATCOM=$OWROOT
- export LIB=$OWROOT/lib286
- export INCLUDE=$OWROOT/h
- Leave the rest as they are
- Test that you can compile TTDPatch now
- /usr/local/openwatcom/setvars
- make alld
- If everything works you can remove the OpenWatcom source directory, or run
- cd bld
- builder clean
- to clean up everything you don't need, which saves about 200-250 MB.
Please report any problems, errors or other difficulties so I may update and improve these instructions.
Now that you can compile the DOS patch, you also need to actually be able to run it, in order to generate memsize.h. This file needs to be correct when distributing the DOS patch, so that the patch knows when it needs to swap out, and when not memory is available to run TTD safely.
It does this by running the patch, and then the patch itself runs the DOS command mem.exe to display the size of ttdpatch.exe in memory.
It's easy to manually do this every time by getting ttdpatch.exe to run in VMWare, dosemu or dosbox, and manually enter the required commands to recreate memsize.h:
- within DOS: ttdpatch -!t-m-f-s-c mem.exe /c > mem.out
- within your development environment: perl perl/memsize.pl < mem.out > memsize.h
However, it's also quite possible to automate this using dosemu. This is probably a good idea if you have dosemu working anyway, and are going to compile the DOS version more than once. Here's what you do:
- to get this working, you first need a working installation of dosemu. Make sure it is able to run mem.exe, and that a drive where ttdpatch.exe can be found is mounted within dosemu.
- get dosemu to run the commands given on the dosemu command line. I did it by adding the following at the end of autoexec.bat:
- unix -e
- if not errorlevel 1 exitemu
- (if no -E commands are given, this will display an error message and return to the DOS prompt, else the emulator will exit after running the command)
- create a batch file called ttdpatch.bat somewhere in the DOS PATH, with the following contents:
- d:
- cd \ttdpatch
- shift
- ttdpatch %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 > ttdpatch.out
- this assumes that your patch development directory is accessible as "d:\ttdpatch" in dosemu
- now try running it, to test that everything works
- dosemu -E "ttdpatch -h"
- this should put the TTDPatch help output in /mnt/d/ttdpatch/ttdpatch.out; if it does not, fix whatever is wrong
- now create a shell script called "dos", and put in it the following lines:
- #!/bin/sh
- dosemu -dumb -E "$*" < /dev/null &> /dev/null
- cat /mnt/d/ttdpatch/ttdpatch.out
- rm /mnt/d/ttdpatch/ttdpatch.out
- this calls dosemu, has it execute the command line given to it, discards all output from dosemu but replays the output of the command that was put in /mnt/d/ttdpatch/ttdpatch.out
- make sure the WINDIR environment variable (for make) is set such that $WINDIR/command/mem.exe points to mem.exe in dosemu, for example set it to "d:" and put mem.exe in d:/command/.
Now, after making a DOS executable for distribution (e.g. "make DEBUG=0 remake dos"), delete memsize.h and run "make memsize.h". This should, hopefully, invoke the above script, thus calling ttdpatch.exe within dosemu and capturing its output, which is then parsed by a Perl script to produce memsize.h. Then make a final pass of "make DEBUG=0 dos" to recompile dos.c with this new size information.