#!/bin/bash # build410.sh -- assemble BTL4OPT.EXE from the reconstructed 4.10 tree. # # Stages: # 1. mass-compile the merged engine source (CODE/BT over CODE/RP over # source410 backfills) into build410/obj/{munga,mungal4}/ # 2. compile the BT game TUs (CODE originals + source410) into # build410/obj/{bt,btl4}/ # 3. tlib the four libs; prebuilt-1995 .obj fallbacks fill source gaps # 4. tlink32 with the authentic OPT.MAK order; unresolved externals -> # build410/UNRESOLVED.txt (the canonical remaining-work ledger) # # Usage: ./build410.sh [engine|bt|libs|link|all|status] T=/c/VWE/TeslaRel410 TW=c:/VWE/TeslaRel410 export PATH="$T/BORLAND/BC45/BIN:$PATH" C=$TW/CODE/BT R=$TW/CODE/RP S=$TW/restoration/source410 B=$T/restoration/build410 Bw=$TW/restoration/build410 INC="$S/override;$C/BT_L4;$C/BT;$C/MUNGA;$C/MUNGA_L4;$C/MUNGA_L4/SOS/BC4;$S/MUNGA;$S/MUNGA_L4;$R/MUNGA;$R/MUNGA_L4;$R/MUNGA_L4/NetNub;$R/MUNGA_L4/sos/bc4;$C/MUNGA_L4/LIBDPL;$C/MUNGA_L4/NETNUB;$C/MUNGA_L4/NETNUB/INCLUDE;$S/MUNGA_L4;$R/MUNGA_L4/libDPL;$R/MUNGA_L4/libDPL/dpl;$S/shim;$S/BT;$S/BT_L4;$TW/BORLAND/BC45/INCLUDE" FLAGS="-c -DLBE4 -DDEBUG_LEVEL=0 -DDEBUG_STREAM=cout \ -b -r -ff -AT -k- -N- -v- -5 -a4 -V -Jg -x- -RT- -O2 -w-" mkdir -p "$B"/obj/{munga,mungal4,bt,btl4} "$B"/lib # compile one TU into a bucket; skip if the obj is newer than the source cc() { # cc local out="$B/obj/$1/$(basename "${2%.*}" | tr 'A-Z' 'a-z').obj" [ -f "$out" ] && [ "$out" -nt "$2" ] && return 0 if bcc32 $FLAGS -I"$INC" -o"$(cygpath -w "$out" 2>/dev/null || echo $out)" "$2" \ > "$B/obj/$1/$(basename "${2%.*}").log" 2>&1; then return 0 else rm -f "$out"; return 1 fi } # merged engine source view: BT tree wins, RP fills, source410 backfills last merged() { # merged [S410dir] { ls "$1"/*.CPP "$1"/*.cpp 2>/dev/null | sed 's/.*[\\/]//' ls "$2"/*.CPP "$2"/*.cpp 2>/dev/null | sed 's/.*[\\/]//' [ -n "$3" ] && ls "$3"/*.CPP 2>/dev/null | sed 's/.*[\\/]//' } | tr 'A-Z' 'a-z' | sort -u } srcfor() { # srcfor [S410dir] case "$1" in filestrm.cpp) echo "$3/FILESTRM.CPP"; return;; # BT pair = post-4.10 drift l4vidper.cpp|l4tsdpl.cpp) return;; # not in mungal4.lib filestub.cpp) return;; # stub.lib member (prebuilt obj) esac for d in "$4" "$2" "$3"; do # source410 overrides, then BT, then RP [ -z "$d" ] && continue for f in "$d"/*.CPP "$d"/*.cpp; do [ -f "$f" ] || continue [ "$(basename "$f" | tr 'A-Z' 'a-z')" = "$1" ] && { echo "$f"; return; } done done } stage_engine() { local ok=0 fail=0 failed="" for lib in munga mungal4; do local bd rd sd if [ $lib = munga ]; then bd=$C/MUNGA; rd=$R/MUNGA; sd=$S/MUNGA; else bd=$C/MUNGA_L4; rd=$R/MUNGA_L4; sd=$S/MUNGA_L4; fi for n in $(merged "$bd" "$rd" "$sd"); do src=$(srcfor "$n" "$bd" "$rd" "$sd") [ -z "$src" ] && continue if cc $lib "$src"; then ok=$((ok+1)); else fail=$((fail+1)); failed="$failed $lib/$n"; fi done done echo "ENGINE: $ok ok, $fail fail" for f in $failed; do echo " FAIL $f"; done | head -60 for f in $failed; do echo "$f"; done > "$B/ENGINE-FAILURES.txt" } stage_bt() { local ok=0 fail=0 for n in $(merged "$C/BT" /dev/null "$S/BT"); do src=$(srcfor "$n" "$C/BT" /dev/null "$S/BT") [ -z "$src" ] && continue if cc bt "$src"; then ok=$((ok+1)); else fail=$((fail+1)); echo " FAIL bt/$n"; fi done for n in $(merged "$C/BT_L4" /dev/null "$S/BT_L4"); do src=$(srcfor "$n" "$C/BT_L4" /dev/null "$S/BT_L4") [ -z "$src" ] && continue if cc btl4 "$src"; then ok=$((ok+1)); else fail=$((fail+1)); echo " FAIL btl4/$n"; fi done echo "BT: $ok ok, $fail fail" } # Authentic 1995 lib member ORDER (MUNGA.MAK / mungal4.mak / BT.MAK / BTL4.MAK). # Order is LOAD-BEARING: tlink emits static-init records in module pull order, # and base-class statics (e.g. NetworkClient::ClassDerivations, network.obj) # must construct before derived ones (IcomManager, icom.obj). Alphabetical # order boots into a null-vptr crash in Derivation::Derivation. ORDER_munga="heap cstr memblock memreg memstrm filestrm verify namelist notation fileutil color resource scalar rect2d random angle vector3d vector4d point3d unitvec rotation motion origin affnmtrx linmtrx matrix mtrxstk spline ray line sphere normal plane extntbox bndgbox boxtree boxlist boxsolid boxsort boxsphr boxcone boxramp boxiramp boxwedge boxdisks boxtile time vdata iterator link plug objstrm socket node slot chain sfeskt srtskt schain vchain tree table hash trace receiver event evtstat cmpnnt simulate subsystm joint network damage entity entityid nttmgr entity2 envirnmt mover segment jmover watcher host hostmgr console scnrole team exptbl caminst cammgr camship cammppr eyecandy player director dropzone explode terrain cultural doorfram door registry lattice intorgn collorgn interest collasst update reticle rndorgn renderer vidrend audio audent audtime audwgt audlvl audloc audcmp audsrc audmidi audseq audwthr audrend wrhous gaugmap gauge lamp gaugrend gaugalrm graph2d mode controls mission apptask app appmgr appmsg spooler icom maptool modtool animtool audtools tool" ORDER_mungal4="l4trace l4file l4time netshare l4serial l4svga16 joystick pcspak l4host l4net l4dplmem l4vidrnd l4video startdpl sosmawe l4audhdw l4audio l4audlvl l4audwtr l4audres l4audrnd l4wrhous l4vb8 l4vb16 l4gauima l4grend l4gauge l4lamp l4plasma l4ctrl l4keybd l4mouse l4rio l4mppr l4app l4splr l4icom l4vidtul l4audtul l4gautul l4ctltul" ORDER_bt="btmssn messmgr mechdmg dmgtable mech mech2 mech3 mech4 mechsub mechtech heat mechmppr powersub sensor gnrator gyro torso hud myomers mechweap emitter ppc projweap mislanch ammobin gauss projtile misthrst seeker missile btplayer btteam btdirect btreg btcnsl bttool" ORDER_btl4="btl4mode btl4rdr btl4gaug btl4gau2 btl4gau3 btl4grnd btl4galm btl4vid btl4mppr btl4arnd btl4mssn btl4app btl4pb" stage_libs() { cd "$B/lib" for lib in munga mungal4 bt btl4; do rm -f $lib.lib ls "$B/obj/$lib"/*.obj >/dev/null 2>&1 || continue : > $lib.rsp eval "order=\$ORDER_$lib" added=" " # authentic makefile order first: compiled obj, else prebuilt-1995 obj for n in $order; do if [ -f "$B/obj/$lib/$n.obj" ]; then printf '+..\obj\%s\%s.obj & ' "$lib" "$n" >> $lib.rsp added="$added$n " else pre=$(find $R/MUNGA/opt $R/MUNGA_L4 -iname "$n.obj" 2>/dev/null | head -1) if [ -n "$pre" ]; then printf '+%s & ' "$(cygpath -w "$pre")" >> $lib.rsp added="$added$n " fi fi done # any extra compiled objs not in the 1995 list go last for o in "$B/obj/$lib"/*.obj; do n=$(basename "${o%.*}") # btl4.obj (main) is linked bare, never a lib member (BTL4.MAK:70) [ "$lib" = btl4 ] && [ "$n" = btl4 ] && continue # l4tstall = the engine TEST main -- its own exe in 1995, never a lib member [ "$n" = l4tstall ] && continue case "$added" in *" $n "*) continue;; esac printf '+..\obj\%s\%s.obj & ' "$lib" "$n" >> $lib.rsp done sed -i '$ s/ &$//' $lib.rsp MSYS2_ARG_CONV_EXCL='*' tlib $lib.lib /P32 @$lib.rsp > $lib.tlib.log 2>&1 echo "$lib.lib: $(grep -c '^+' $lib.rsp) members ($(ls -la $lib.lib 2>/dev/null | awk '{print $5}') bytes)" done } stage_link() { cd "$B" if [ -f obj/btl4/btl4.obj ]; then MAIN=obj/btl4/btl4.obj elif [ -f probe_main.cpp ]; then bcc32 $FLAGS -I"$INC" -oprobe_main.obj probe_main.cpp > probe_main.log 2>&1 || { echo "probe main FAILED (probe_main.log)"; return 1; } MAIN=probe_main.obj fi cp -f "$T/CODE/BT/32STUB.EXE" 32stub.exe 2>/dev/null # single-line sections; SOSDBXC+SOSMBXC = the 32-bit Borland SOS pair # (SOSMW* is 16-bit); WATTCPLG is the 16-bit NetNub TSR side -- excluded cat > link.rsp < link.log 2>&1 grep -i "unresolved" link.log | sed "s/^.*Error: //" | sort -u > UNRESOLVED.txt echo "link exit: $? ; unresolved: $(wc -l < UNRESOLVED.txt) (build410/UNRESOLVED.txt); main=$MAIN" ls -la btl4opt.exe 2>/dev/null } case "${1:-all}" in engine) stage_engine;; bt) stage_bt;; libs) stage_libs;; link) stage_link;; status) for d in munga mungal4 bt btl4; do echo "$d: $(ls "$B/obj/$d"/*.obj 2>/dev/null | wc -l) objs"; done;; all) stage_engine; stage_bt; stage_libs; stage_link;; esac