forked from arti/vt1200
133 lines
4.3 KiB
Bash
Executable File
133 lines
4.3 KiB
Bash
Executable File
#!/bin/sh
|
|
# Build the Bad Apple payload with the 1987 TI TMS34010 SDK under DOSBox.
|
|
#
|
|
# .text at bit 0x018C0000, .bss at bit 0x01C00000 (the free block the rdebug
|
|
# loader already uses). Outputs: build/player.coff, player.bin, player.env.
|
|
set -eu
|
|
|
|
ROOT=$(cd "$(dirname "$0")/../.." && pwd)
|
|
DIR=$(cd "$(dirname "$0")" && pwd)
|
|
WORK="$DIR/work"
|
|
OUT="$DIR/build"
|
|
IMG="$ROOT/tools/tms34010-sdk/1987-05 TMS34010 SDK/1987-11-06 TMS34010 Simulator-C Tools-ASM Tools.img"
|
|
DOSBOX_CONF="$ROOT/harness/sdk-scratch/dosbox-bench.conf"
|
|
|
|
TEXT=018C0000
|
|
BSS=01C00000
|
|
NET=${NET:-0}
|
|
if [ "$NET" = 1 ]; then
|
|
NAME=player-net
|
|
else
|
|
NAME=player
|
|
fi
|
|
|
|
mkdir -p "$WORK" "$OUT"
|
|
|
|
if [ ! -x "$WORK/GSPCG.EXE" ]; then
|
|
mcopy -s -n -i "$IMG" "::/A2/*" "$WORK/"
|
|
mcopy -s -n -i "$IMG" "::/C2/*" "$WORK/"
|
|
fi
|
|
|
|
cp "$DIR/main.c" "$WORK/MAIN.C"
|
|
cp "$DIR/movie.c" "$WORK/MOVIE.C"
|
|
cp "$DIR/movie.h" "$WORK/MOVIE.H"
|
|
cp "$DIR/romapi.h" "$WORK/ROMAPI.H"
|
|
printf '#define NET_DEFAULT %s\n' "$NET" > "$WORK/MODECFG.H"
|
|
cp "$DIR/fill.asm" "$WORK/FILL.ASM"
|
|
cp "$DIR/entry.asm" "$WORK/ENTRY.ASM"
|
|
|
|
{
|
|
printf '%s\n' '-a'
|
|
printf '%s\n' '-o PLAYER.out'
|
|
printf '%s\n' '-m PLAYER.map'
|
|
printf '%s\n' '-e _start'
|
|
printf '%s\n' 'MAIN.obj'
|
|
printf '%s\n' 'MOVIE.obj'
|
|
printf '%s\n' 'FILL.obj'
|
|
printf '%s\n' 'ENTRY.obj'
|
|
printf '%s\n' '-l RTS.LIB'
|
|
printf '%s\n' 'MEMORY'
|
|
printf '%s\n' '{'
|
|
printf '%s\n' " prog: origin = ${TEXT}h, length = 20000h"
|
|
printf '%s\n' " ram: origin = ${BSS}h, length = 200000h"
|
|
printf '%s\n' '}'
|
|
printf '%s\n' 'SECTIONS'
|
|
printf '%s\n' '{'
|
|
printf '%s\n' ' .text: {} > prog'
|
|
printf '%s\n' ' .data: {} > prog'
|
|
printf '%s\n' ' .cinit: {} > prog'
|
|
printf '%s\n' ' .bss: {} > ram'
|
|
printf '%s\n' '}'
|
|
} > "$WORK/PLAYER.CMD"
|
|
sed -i 's/$/\r/' "$WORK/PLAYER.CMD"
|
|
|
|
{
|
|
printf 'gspcpp MAIN\r\n'
|
|
printf 'gspcc MAIN\r\n'
|
|
printf 'gspcg MAIN\r\n'
|
|
printf 'gspa MAIN MAIN.obj MAIN.lst -l\r\n'
|
|
printf 'gspcpp MOVIE\r\n'
|
|
printf 'gspcc MOVIE\r\n'
|
|
printf 'gspcg MOVIE\r\n'
|
|
printf 'gspa MOVIE MOVIE.obj MOVIE.lst -l\r\n'
|
|
printf 'gspa FILL FILL.obj FILL.lst -l\r\n'
|
|
printf 'gspa ENTRY ENTRY.obj ENTRY.lst -l\r\n'
|
|
printf 'gsplnk PLAYER.cmd\r\n'
|
|
printf 'exit\r\n'
|
|
} > "$WORK/BUILD.BAT"
|
|
|
|
rm -f "$WORK"/MAIN.OBJ "$WORK"/MOVIE.OBJ "$WORK"/FILL.OBJ \
|
|
"$WORK"/ENTRY.OBJ "$WORK"/PLAYER.OUT "$WORK"/PLAYER.MAP \
|
|
"$WORK"/MAIN.LST "$WORK"/MOVIE.LST "$WORK"/FILL.LST \
|
|
"$WORK"/ENTRY.LST
|
|
|
|
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
|
|
timeout 240 dosbox -conf "$DOSBOX_CONF" -noprimaryconf -nolocalconf \
|
|
-c "mount c $WORK" -c "c:" \
|
|
-c "BUILD.BAT" \
|
|
-c "exit" -exit > "$WORK/dosbox.log" 2>&1
|
|
|
|
if [ ! -f "$WORK/PLAYER.OUT" ]; then
|
|
echo "build.sh: GSPLNK produced no PLAYER.OUT" >&2
|
|
sed 's/\r$//' "$WORK/PLAYER.MAP" 2>/dev/null | tail -20 >&2 || true
|
|
for f in MAIN.LST MOVIE.LST FILL.LST ENTRY.LST; do
|
|
sed 's/\r$//' "$WORK/$f" 2>/dev/null | grep -i 'error' \
|
|
| grep -vi 'no errors' >&2 || true
|
|
done
|
|
exit 1
|
|
fi
|
|
for f in MAIN.LST MOVIE.LST FILL.LST ENTRY.LST; do
|
|
if sed 's/\r$//' "$WORK/$f" 2>/dev/null | grep -i 'error' \
|
|
| grep -qvi 'no errors'; then
|
|
echo "build.sh: $f diagnostics:" >&2
|
|
sed 's/\r$//' "$WORK/$f" | grep -in 'error' \
|
|
| grep -vi 'no errors' >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
cp "$WORK/PLAYER.OUT" "$OUT/player.coff"
|
|
sed 's/\r$//' "$WORK/PLAYER.MAP" > "$OUT/player.map"
|
|
sed 's/\r$//' "$WORK/MAIN.LST" > "$OUT/main.lst" 2>/dev/null || true
|
|
sed 's/\r$//' "$WORK/MOVIE.LST" > "$OUT/movie.lst" 2>/dev/null || true
|
|
sed 's/\r$//' "$WORK/FILL.LST" > "$OUT/fill.lst" 2>/dev/null || true
|
|
|
|
python3 "$ROOT/harness/hello-world/cofextract.py" \
|
|
"$WORK/PLAYER.OUT" "$OUT/$NAME.bin" > "$OUT/cofextract.txt"
|
|
cp "$WORK/PLAYER.OUT" "$OUT/$NAME.coff"
|
|
|
|
ENTRY_PTR=$(sed 's/\r$//' "$WORK/PLAYER.MAP" \
|
|
| awk '/ENTRY POINT SYMBOL/ { print $NF; exit }')
|
|
MARK_PTR=$(sed 's/\r$//' "$WORK/PLAYER.MAP" \
|
|
| awk '$2 == "_marker_page" { print $1; exit }')
|
|
if [ -z "$ENTRY_PTR" ] || [ -z "$MARK_PTR" ]; then
|
|
echo "build.sh: no entry point or _marker_page in PLAYER.map" >&2
|
|
exit 1
|
|
fi
|
|
printf 'ENTRY_PTR=0x%s\nMARK_PTR=0x%s\n' "$ENTRY_PTR" "$MARK_PTR" \
|
|
> "$OUT/$NAME.env"
|
|
|
|
echo "build.sh: $OUT/$NAME.bin ($(wc -c < "$OUT/$NAME.bin") bytes)"
|
|
grep -E "ENTRY POINT|^\.(text|cinit|bss)" "$OUT/player.map" | head -8
|
|
echo "build.sh: entry bit 0x$ENTRY_PTR"
|