
# =========================================================
#         Configuration part
# =========================================================

# Version info is now in version.def to prevent remaking everything
# when the Makefile is changed
include version.def

# Choose whether to use Borland C++ (set to 1) or OpenWatcom (set to 0)
# for compiling the DOS version
USEBCC = 0

# Uncomment if your debugger/OS crashes when the program encounters
# int3 instruction breakpoints
# -dNOINT3=1: use an endless loop instead; otherwise don't break at all
# NASMDEF += -dNOINT3

# Set to 1 to not link protected code, but use ttdprot*.bin either 
# as separate file or appended to the executable
# Note that you must set this 0 for LoadTycoon under Linux.
USEPROTBIN = 0

# This determines whether to build for Linux or for Windows, when in doubt.
LINUX = 1

# Tools
SHELL = /bin/bash	# typical on Cygwin

# Use large model for the DOS version
MODEL = l

# Set DEBUG to 0 if not defined yet. To change, define it as an environment
# variable, or run `make DEBUG=1 <targets...>'
ifeq ($(DEBUG),)
DEBUG=0
endif

# Borland compilers and options
BCC16 = bcc
BCC32 = bcc32

ifeq ($(DEBUG),1)
COPTS = -v -y -k -Od -N
else
COPTS = -v -y -k- -O1
endif

# Watcom compilers and options
CC16 = wcl

ifeq ($(DEBUG),1)
CC16OPTS = -3 -zp1 -c -e7 -wx -wcd=202 -zq -bt=DOS -nt=_MYTEXT -hc -d3 -od
CL16OPTS = -zq -wx -fm -l=DOS -hc -d3
else
CC16OPTS = -3 -zp1 -c -e7 -wx -wcd=202 -zq -bt=DOS -nt=_MYTEXT -hc -d1 -s -obkls
CL16OPTS = -zq -wx -fm -l=DOS -hc -d1
endif

# GNU compilers and options
CC = gcc
CXX = g++
CPP = gcc -E
CFLAGS = -g -Os -march=i386 -mcpu=pentium -Wall -Wno-unused -Wwrite-strings
CXXFLAGS = $(CFLAGS)
ifeq ($(LINUX),1)
	LDOPT = 
else
	LDOPT = -Wl,--subsystem,console,-s
endif
LDOPT += $(LDLIBS) $(LDEXTRAOPTS)
LDOPT += -Wl,-Map,$(@:%=%.map)		# to make map files
AR = ar

# to use crtdll; comment out to use msvcrt
# may need to adjust mingw include and crt1.o path
#CFLAGS += -D__CRTDLL__ -U__MSVCRT__ -I/usr/include/mingw
#LDOPT += -nostartfiles /usr/lib/mingw/crt1.o -lcrtdll -lcoldname

# to test makelang
# makelang.o: CFLAGS += -DTESTMAKELANG

# defines for compiling all C and assembly sources
# this is a space-separated list without the command line switches 
# like -d; those will be added later because they differ
DEFS = DEBUG=$(DEBUG) 

ifeq ($(USEPROTBIN),1)
	DEFS += USEPROTBIN
endif

# same, but each specialized for the DOS, Windows or Linux versions
DOSDEFS = $(DEFS) WINTTDX=0 LINTTDX=0
WINDEFS = $(DEFS) WINTTDX=1 LINTTDX=0
LINDEFS = $(DEFS) WINTTDX=0 LINTTDX=1

ifeq ($(LINUX),1)
	USEDEFS = $(LINDEFS)
else
	USEDEFS = $(WINDEFS)
endif

# NASM compiler and options
NASM = nasm
NASMPRE = nasm -e
NASMOPT = -w+orphan-labels
ifeq ($(LINUX),1)
	NASMFMT = -f elf -dLINTTDX
else
	NASMFMT = -f coff -dCOFF
endif

# temporary response files
DRSP = $(TEMP)/BCC.RSP
URSP = $(subst \,\\,$(shell cygpath -w $(DRSP)))

ifeq ($(USEBCC),1)
STRIP = tdstrip
else
STRIP = wstrip -q
endif

# No configuration below here...

# Define the name of the default target (actual definition below)
all:

# =======================================================================
#           collect info about source files
# =======================================================================

asmsources:=	ttdprot.asm $(wildcard *.ah) common.h flagdata.h versiond.h \
			$(wildcard patches/*.asm) $(wildcard patches/*.ah) patches/texts.h
csources:=	ttdpatch.c error.c grep.c switches.c loadlng.c checkexe.c myalloc.c auxfiles.c
doscsources:=	$(csources) dos.c
lincsources:=	ttdpatcl.c error.c grep.c switches.c loadlng.c myalloc.c auxfiles.c linux.c
wincsources:=	$(csources) windows.c codepage.c
versiondata:=	$(wildcard versions/*.ver)

langhsources:=	$(wildcard lang/*.h)
langobjs:=	$(langhsources:%.h=%.o)

ifeq ($(USEPROTBIN),0)
dosobjs:=	$(doscsources:%.c=%.obj) ttdprotd.obj
winobjs:=	ttdprotw.o ttdpatchw.res $(wincsources:%.c=%.o) libz.a
lin:	ttdprotl.bin
linobjs:=	$(lincsources:%.c=%.o)
# We link ttdprotl.obj in loadlinux
else
dos:	ttdprotd.bin
dosobjs:=	$(doscsources:%.c=%.obj)
win:	ttdprotw.bin
winobjs:=	$(wincsources:%.c=%.o) ttdpatchw.res libz.a
lin:	ttdprotl.bin
linobjs:=	$(lincsources:%.c=%.o)
endif

# =======================================================================
#           dependencies are in Makefile.dep, include that
# =======================================================================

include Makefile.dep

# =======================================================================
#           special targets
# =======================================================================

.PHONY:	all alld allw dos win nodebug clean cleantemp remake

# automatic compilation: make the listing with correct addresses and
# the DOS executable file
all:	lin mkpttxt
alld:	dos mkpttxt
allw:	win mkpttxt
lin:	ttdprotl.lst libttdpatch.a language.dat
dos:	ttdprotd.lst ttdpatch.exe
win:	ttdprotw.lst ttdpatchw.exe

# [test and testw are my own stuff -- Marcin]
.PHONY: test testw

test: ttdprotd.lst ttdpatch.exe
	@cp -v -u --remove-destination ttdpatch.exe \
		`perl -wlne '/^VERSION\s*\=\s*(\S*)/ && print "$(subst \,/,$(GAMEDIR))/ttdpatch-".$$1.".exe";' version.def`

testw: ttdprotw.lst ttdpatchw.exe
	@cp -v -u --remove-destination ttdpatchw.exe \
		`perl -wlne '/^VERSION\s*\=\s*(\S*)/ && print "$(subst \,/,$(GAMEDIR))/ttdpatchw-".$$1.".exe";' version.def`


nodebug:
ifneq ($(DEBUG),0)
	@echo Run as mk R
	@exit 1
endif
	@echo Making non-debug version.

# remove temporary files
cleantemp:
	rm -f x*.asm
	rm -f *.asp
	rm -f *.{o,obj,OBJ,a}
	rm -f lang/*.{o,map,exe} lang/language.*
	rm -f *.lst *.LST
	rm -f ttdload.ovl

# remove files that depend on compiler flags (DEBUG, etc.)
remake:
	touch reloc.inc
	rm -f *.{o,obj,OBJ,bin,bil} lang/*.o
	rm -f x*.asm
	rm -f mkpttxt.exe

# remove temporary files and all compilation results that can be
# remade with make
clean:	cleantemp
	echo > reloc.inc
	rm -f language.dat
	rm -f language.ucd
	rm -f ttdprotd.exe
	rm -f ttdprotw.exe
	rm -f lang/*.{new,o}
	rm -f *.{bin,bil}
	rm -f *.{map,MAP}
	rm -f *.{res,RES}
	rm -f langerr.h
	rm -f sw_lists.h
	rm -f patches/texts.h
	rm -f version{d,w}.h

# ========================================================================
#            Actual compilation rules for the C sources
# ========================================================================

# how to make an object file from a C file
ifeq ($(USEBCC),1)
%.obj : %.c
	@echo "-3 -a -c -d -f- -u -K -j7"				> $(DRSP)
	@echo "-zC_mytext"						>> $(DRSP)
	@echo "-m$(MODEL) $(foreach DEF,$(DOSDEFS),-D$(DEF)) "		>> $(DRSP)
	@echo $< 							>> $(DRSP)
	$(BCC16) $(COPTS) -o$@ @$(URSP)
	@perl -e 's//pop/e;rename uc, lc or die "Error"' $@
else
%.obj : %.c
	$(CC16) $(CC16OPTS) -fo=$@ -m$(MODEL) $(foreach DEF,$(DOSDEFS),-d$(DEF)) $<
endif

%.o : %.c
	$(CC) -c -o $@ $(CFLAGS) $(foreach DEF,$(USEDEFS),-D$(DEF)) $<

%.S : %.c
	$(CC) -S -o $@ $(CFLAGS) $(foreach DEF,$(USEDEFS),-D$(DEF)) $<

%.lst : %.S
	as -a $< -o /dev/null > $@

% : %.o
	$(CC) -o $@ $^ $(LDOPT)

%.a :
	$(AR) cru $@ $^

%.o : %.asm
	$(NASM) $(NASMOPT) $(NASMFMT) $(NASMDEF) $< -o $@

%.obj : %.asm
	$(NASM) $(NASMOPT) -f obj -dOBJ $(NASMDEF) $< -o $@

# -------------------------------------------------------------------------
#                  The assembly modules
# -------------------------------------------------------------------------


# make the assembler file by passing the source through
# the C pre-compiler, using perl to add correct, original
# line numbers

# set different preprocessor defines for each target
xd.asm:	XASMDEF =  $(foreach DEF,$(DOSDEFS),-D$(DEF))
xw.asm:	XASMDEF =  $(foreach DEF,$(WINDEFS),-D$(DEF))
xl.asm:	XASMDEF =  $(foreach DEF,$(LINDEFS),-D$(DEF))

# common compilation rule for the preprocessed targets
xd.asm xw.asm xl.asm:	$(asmsources)
	$(CPP) $(XASMDEF) - < $< | perl perl/lineinfo.pl > $@

# same but with no line info and empty lines removed
# for editors that can't handle >32768 lines
xdc.asm xwc.asm xlc.asm:	$(asmsources)
	$(CPP) $(XASMDEF) - < $< | perl perl/noempty.pl > $@

# make a listing which uses the actual offsets in memory (from preprocessed assembly)
ttdprot%.lst : x%.asm
	$(NASM) $(NASMOPT) -f obj -dUSEORG -dOBJ $(NASMDEF) $< -l $@ -o /dev/null

# assemble the protected code module, with no relocatable addresses
ttdprot%.o : x%.asm
	$(NASM) $(NASMOPT) -f coff -dCOFF $(NASMDEF) $< -o $@

ttdprot%.obj : x%.asm
	$(NASM) $(NASMOPT) -f obj -dOBJ $(NASMDEF) $< -o $@

# make flat binary for making sure code is correct
ttdprot%.bin : x%.asm
	$(NASM) $(NASMOPT) -f bin -dBIN $(NASMDEF) $< -o $@

# and with the right offsets too
ttdprot%.bil : x%.asm
	$(NASM) $(NASMOPT) -f bin -dUSEORG -dBIN $(NASMDEF) $< -o $@

# finally a pre-processed assembly file for debugging the pre-processor
ttdprot%.asp:	x%.asm
	$(NASM) $(NASMOPT) -e -dPREPROCESSONLY -dBIN $(NASMDEF) $< -o $@

texts.lst:	texts.asp
	$(NASM) $(NASMOPT) $(NASMDEF) $< -l $@ -o /dev/null

texts.asp:	texts.asm
	$(NASM) $(NASMOPT) -e -dPREPROCESSONLY $(NASMDEF) $< -o $@

patches/texts.h:	texts.lst
	perl perl/texts.pl < $< > $@

# generate relocations for the Windows version
reloc.inc:	ttdprotw.lst
	if ! OLDCRC=`grep RELOCCRC reloc.inc` perl perl/reloc.pl < $< > $@; then rm xw.asm; make $<; touch $@; fi;

# ---------------------------------------------------------------------
#               Language data
# ---------------------------------------------------------------------

# define rules for the language modules
langerr.h:	language.h common.h
	perl perl/langerr.pl $^ > $@

makelang:	LDLIBS = -L. -lz
makelang:	makelang.o $(langobjs) switches.o codepage.o texts.o

lang/%.o:	lang/%.h
	$(CC) -c -o $@ $(CFLAGS) -DLANGUAGE=${patsubst lang/%.h,%,$<} proclang.c

# test versions of makelang with a single language: make lang/<language> and run
# the executable to make a single-language language.dat file
lang/%:		makelang.c lang/%.o switches.o codepage.o texts.o
	$(CC) -o $@ $(CFLAGS) $(LDOPT) $(foreach DEF,$(USEDEFS),-D$(DEF)) -DSINGLELANG=${patsubst lang/%,%,$@} $^ -L. -lz

# for mkpttxt, include only the first language in texts_f.o
# (actually now we use all)
#texts_f.o: texts.asm texts.inc
#	$(NASM) $(NASMOPT) -f coff -dONLYFIRST -o $@ $<

mkpttxt.o:       mkpttxt.c patches/texts.h
mkpttxt:         mkpttxt.o texts.o

# ----------------------------------------------------------------------
#               Resource file for Windows version
# ----------------------------------------------------------------------

%.res : %.rc
	windres -i $< -o $@ -O coff


# ----------------------------------------------------------------------
#               The executables
# ----------------------------------------------------------------------


# make both uncompressed (for testing) and compressed language data
language.dat: makelang
	@$< n > /dev/null 2> makelang.err
	$< > makelang.log 2> makelang.err

# link the modules to the exe file
ifeq ($(USEBCC),1)
ttdprotd.exe:	$(dosobjs)
	@echo "-M -v -y -f-" 		> $(DRSP)
	@echo $^ 			>> $(DRSP)
	@echo zlib_bc$(MODEL).lib	>> $(DRSP)
	@echo exec_bc$(MODEL).lib	>> $(DRSP)
	$(BCC16) -m$(MODEL) -e$@	@$(URSP)
else
ttdprotd.exe:	$(dosobjs)
	$(CC16) $(CL16OPTS) -m$(MODEL) -fe=$@ $^ zlib_ow$(MODEL).lib exec_ow$(MODEL).lib
endif

ttdprotw:
	$(CC) -o $@ $^ $(LDOPT)

# compress it, and link the language data to it too
ttdpatch.exe:	ttdprotd.exe language.dat
ttdpatchw.exe:	ttdprotw language.dat

# with USEPROTBIN, we also need the appropriate binary
ifeq ($(USEPROTBIN),1)
ttdpatch.exe:	ttdprotd.bin
ttdpatchw.exe:	ttdprotw.bin
endif

ifeq ($(USEBCC),1)
ttdpatch.exe:
	cp $< $@
	$(STRIP) $@
	upx -qq --best $@
ifeq ($(USEPROTBIN),1)
	cat --binary language.dat ttdprotd.bin >> $@
else
	cat --binary language.dat >> $@
endif
else
# for some reason compressing ttdpatch.exe compiled with Open Watcom 1.0
# with UPX does no good (looks like a relocation table error)
ttdpatch.exe:
	cp $< $@
	$(STRIP) $@
ifeq ($(USEPROTBIN),1)
	cat --binary language.dat ttdprotd.bin >> $@
else
	cat --binary language.dat >> $@
endif
endif

ttdpatchw.exe:
	cp $<.exe $@
	upx -qq --best --compress-icons=0 $@
ifeq ($(USEPROTBIN),1)
	cat --binary language.dat ttdprotw.bin >> $@
else
	cat --binary language.dat >> $@
endif

libttdpatch.a: $(linobjs)

# ----------------------------------------------------------------------
#                       additional stuff
# ----------------------------------------------------------------------

# make libz.a from the sources
LIBZTEMPDIR = zlib
libz.a:
	mkdir -p $(LIBZTEMPDIR)
	cd $(LIBZTEMPDIR); unzip -n ../zlib_src; ./configure; make libz.a; 
	cp $(LIBZTEMPDIR)/libz.a $@
	@echo NOTE: You can remove the $(LIBZTEMPDIR) directory, it is no longer needed.

# recreate versionX.h if deleted or the Makefile changes

versiond.h:
	@echo // Autogenerated by make.  Do not edit.  Edit version.def or the Makefile instead. > $@
	@echo "#define TTDPATCHVERSION \"$(VERSIONSTR) (DOS)\"" >> $@
	@echo "#define TTDPATCHVERSIONNUM 0x$(VERSIONNUM)L" >> $@
	@echo "#define TTDPATCHVERSIONSHORT \"$(VERSION)\"" >> $@
	@echo "#define TTDPATCHVERSIONMAJOR $(VERSIONMAJOR)" >> $@
	@echo "#define TTDPATCHVERSIONMINOR $(VERSIONMINOR)" >> $@
	@echo "#define TTDPATCHVERSIONREVISION $(VERSIONREVISION)" >> $@
	@echo "#define TTDPATCHVERSIONBUILD $(VERSIONBUILD)" >> $@

versionw.h:
	@echo // Autogenerated by make.  Do not edit.  Edit version.def or the Makefile instead. > $@
	@echo "#define TTDPATCHVERSION \"$(VERSIONSTR) (Windows)\"" >> $@
	@echo "#define TTDPATCHVERSIONNUM 0x$(VERSIONNUM)L" >> $@
	@echo "#define TTDPATCHVERSIONSHORT \"$(VERSION)\"" >> $@
	@echo "#define TTDPATCHVERSIONMAJOR $(VERSIONMAJOR)" >> $@
	@echo "#define TTDPATCHVERSIONMINOR $(VERSIONMINOR)" >> $@
	@echo "#define TTDPATCHVERSIONREVISION $(VERSIONREVISION)" >> $@
	@echo "#define TTDPATCHVERSIONBUILD $(VERSIONBUILD)" >> $@

# sorted switch list
sw_lists.h:	sw_list.h
	perl perl/sw_sort.pl < $^ > $@

# Autodetection of the TTDPATCH program size, for deciding when to swap out
# - make ttdpatch.exe with a bogus memsize
# - run it on mem.exe to report how large it really is
# - force a remake of dos.obj with that new size
#
# memsize.h is not normally re-made if anything changes because it'll still
# be "almost" correct.  Force a remake by deleting it just before doing
# a make dist or so.

ifeq ($(USEBCC),1)
memsize.h:
	echo "#define TTDPATCHSIZE 65536" > $@
	make
	rm -f $@
	TTDPATCH '-!t-m-f-s-c' $(subst \,/,$(WINDIR))/command/mem.exe /C | perl perl/memsize.pl > $@
	rm -f dos.obj ttdload.ovl
else
memsize.h:
	echo "#define TTDPATCHSIZE 65536" > $@
	make
	rm -f $@
	echo '@echo off' > memsize.bat
	echo TTDPATCH '-!t-m-f-s-c' $(subst \,/,$(WINDIR))/command/mem.exe '/C > memsize.log' >> memsize.bat
	$(subst \,/,$(WINDIR))/command/start.exe /w memsize.bat
	@rm -f ttdpatch.dat
	perl perl/memsize.pl memsize.log > $@
	rm -f memsize.bat memsize.log
	rm -f dos.obj ttdload.ovl
endif
