CompilingTTDPatchOnLinux

From TTWiki
Jump to: navigation, search

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

  1. 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".
  2. 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.)

  1. 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.
  2. 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
  3. 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
  4. 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
  5. 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)
  6. compile it, pick the same prefix as above obviously:
    ./configure --prefix=/usr --target=i686-pc-mingw32
    make
    make install
  7. 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
  8. 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
  9. 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.

  1. 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)
  2. run the compiler bootstrap
    . build.sh (if that doesn't work, try ./build.sh)
  3. 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.
  4. Copy the binaries, headers and libraries:
    cd rel2
    cp -a binl binw h lh lib286 /usr/local/openwatcom
  5. 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
  6. Test that you can compile TTDPatch now
    /usr/local/openwatcom/setvars
    make alld
  7. 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.