forked from arti/vt1200
- seed the game from the raw 0x1E93C0 counter (now_ms() returns 0 on its
first call, so the old seed was always zero)
- track pause ourselves: FocusOut pauses once, FocusIn resumes only what we
paused (game_input('p') is a toggle)
- select ExposureMask so the Expose redraw path actually fires
- play.sh/play_keys.sh rebuild the COFF (OUTNAME=termtris) and assert the
run: status=0, tick>0, loops/events/quit per mode; render.sh asserts the
renderer finished; map symbol lookup is column-order independent
- run.sh passes -lightgun -lightgun_device mouse so the pointer drives the
tablet
- docs: link map addresses, monochrome/reverse wording, honest caption and
limits text
Verified here: play.sh and input.sh pass. Still open: the MAME driver in the
tree is newer than the installed binary (Oct 30 build, VR150-era geometry),
so the acceptance suite must be re-run after a rebuild.
171 lines
4.9 KiB
Bash
Executable File
171 lines
4.9 KiB
Bash
Executable File
#!/bin/sh
|
|
# build.sh -- build a VT1200 COFF with TI TMS34010 r5.01 under 2ine.
|
|
#
|
|
# apps/termtris/build.sh SOURCE.c [SOURCE.c ...] [EXTRA.obj ...]
|
|
#
|
|
# The first .c is the main program; the output is build/<main>.coff. entry.asm
|
|
# and cinit.asm are always assembled and linked. The 2ine loader is outside the
|
|
# repo: point NINE at its build directory (default /home/arti/os2-work/2ine/build).
|
|
set -eu
|
|
|
|
DIR=$(cd "$(dirname "$0")" && pwd)
|
|
ROOT=$(cd "$DIR/../.." && pwd)
|
|
WORK="$DIR/work"
|
|
OUT="$DIR/build"
|
|
NINE="${NINE:-/home/arti/os2-work/2ine/build}"
|
|
LX="$NINE/lx_loader"
|
|
SDK="$ROOT/tools/tms34010-sdk/1990-11 TMS340 Family SDK"
|
|
Z1="$SDK/1990-11-19 TMS340 Family Code Generation Tools (1 of 2) r5.01 rev2564062-1641.zip"
|
|
Z2="$SDK/1990-11-19 TMS340 Family Code Generation Tools (2 of 2) r5.01 rev2564062-1641.zip"
|
|
|
|
if [ ! -x "$LX" ]; then
|
|
echo "build.sh: no 2ine lx_loader at $LX (set NINE=...)" >&2
|
|
exit 1
|
|
fi
|
|
if [ ! -f "$Z1" ] || [ ! -f "$Z2" ]; then
|
|
echo "build.sh: r5.01 SDK zips not found under $SDK" >&2
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p "$WORK" "$OUT"
|
|
if [ ! -x "$WORK/gspac.exe" ]; then
|
|
unzip -oq "$Z1" -d "$WORK"
|
|
unzip -oq "$Z2" -d "$WORK"
|
|
fi
|
|
for so in "$NINE"/lib*.so; do
|
|
[ -e "$so" ] && ln -sf "$so" "$WORK/"
|
|
done
|
|
cp "$DIR/src/vt1200/"*.h "$WORK/" 2>/dev/null || true
|
|
cp "$DIR/src/"*.h "$WORK/" 2>/dev/null || true
|
|
cp "$DIR/src/vt1200/entry.asm" "$DIR/src/vt1200/cinit.asm" "$DIR/src/vt1200/cinitz.asm" "$WORK/"
|
|
|
|
# Collect objects. C sources are copied under their uppercase basename because
|
|
# the OS/2 tools are case-sensitive on this host.
|
|
OBJS=""
|
|
MAIN=""
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
*.c)
|
|
base=$(basename "$arg" .c | tr 'a-z' 'A-Z')
|
|
[ -n "$MAIN" ] || MAIN="$base"
|
|
cp "$arg" "$WORK/$base.C"
|
|
OBJS="$OBJS $base"
|
|
;;
|
|
*.obj)
|
|
cp "$arg" "$WORK/"
|
|
OBJS="$OBJS $(basename "$arg")"
|
|
;;
|
|
*.asm)
|
|
base=$(basename "$arg" .asm | tr 'a-z' 'A-Z')
|
|
cp "$arg" "$WORK/$base.ASM"
|
|
OBJS="$OBJS $base"
|
|
;;
|
|
*)
|
|
echo "build.sh: unsupported input: $arg" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
if [ -z "$MAIN" ]; then
|
|
echo "build.sh: give at least one .c source" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# The 2ine-hosted tools frequently crash during teardown after doing their work
|
|
# (exit 139 / 134). Treat an output file as success, and retry a missing one.
|
|
run() {
|
|
_out=$1
|
|
shift
|
|
i=0
|
|
while [ "$i" -lt 5 ]; do
|
|
( cd "$WORK" && "$LX" "$@" ) >/dev/null 2>&1 || true
|
|
if [ -f "$WORK/$_out" ]; then
|
|
return 0
|
|
fi
|
|
i=$((i + 1))
|
|
done
|
|
echo "build.sh: stage failed to produce $WORK/$_out: $*" >&2
|
|
return 1
|
|
}
|
|
|
|
compile_c() {
|
|
base=$1
|
|
rm -f "$WORK/$base.IF" "$WORK/$base.OPT" "$WORK/$base.ASM" "$WORK/$base.obj"
|
|
run "$base.IF" ./gspac.exe -k -i. "$base.C" "$base.IF"
|
|
run "$base.OPT" ./gspopt.exe -k -O2 "$base.IF" "$base.OPT"
|
|
run "$base.ASM" ./gspcg.exe -m "$base.OPT" "$base.ASM" "$base.TMP"
|
|
run "$base.obj" ./gspa.exe "$base.ASM"
|
|
}
|
|
|
|
compile_asm() {
|
|
base=$1
|
|
rm -f "$WORK/$base.obj"
|
|
run "$base.obj" ./gspa.exe "$base.ASM"
|
|
}
|
|
|
|
|
|
# Compile every collected object exactly once, in the order given.
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
*.c) compile_c "$(basename "$arg" .c | tr 'a-z' 'A-Z')" ;;
|
|
*.asm) compile_asm "$(basename "$arg" .asm | tr 'a-z' 'A-Z')" ;;
|
|
esac
|
|
done
|
|
compile_asm ENTRY
|
|
compile_asm CINIT
|
|
compile_asm CINITZ
|
|
|
|
OUTNAME=${OUTNAME:-$(printf '%s' "$MAIN" | tr 'A-Z' 'a-z')}
|
|
CMD="$WORK/$MAIN.CMD"
|
|
{
|
|
printf '%s\n' '-a'
|
|
printf '%s\n' "-o $MAIN.out"
|
|
printf '%s\n' "-m $MAIN.map"
|
|
printf '%s\n' '-e _start'
|
|
printf '%s\n' 'CINIT.obj'
|
|
printf '%s\n' 'ENTRY.obj'
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
*.c) printf '%s\n' "$(basename "$arg" .c | tr 'a-z' 'A-Z').obj" ;;
|
|
*.asm) printf '%s\n' "$(basename "$arg" .asm | tr 'a-z' 'A-Z').obj" ;;
|
|
*.obj) printf '%s\n' "$(basename "$arg")" ;;
|
|
esac
|
|
done
|
|
printf '%s\n' '-l rts.lib'
|
|
printf '%s\n' 'MEMORY'
|
|
printf '%s\n' '{'
|
|
printf '%s\n' ' prog: origin = 018A0000h, length = 20000h'
|
|
printf '%s\n' ' ram: origin = 01A00000h, length = 40000h'
|
|
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' '}'
|
|
} > "$CMD"
|
|
sed -i 's/$/\r/' "$CMD"
|
|
|
|
rm -f "$WORK/$MAIN.out" "$WORK/$MAIN.map"
|
|
run "$MAIN.out" ./gsplnk.exe "$MAIN.CMD"
|
|
if [ ! -f "$WORK/$MAIN.map" ]; then
|
|
echo "build.sh: no link map" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# An empty .cinit makes the linker's `cinit` symbol point at .text; the entry's
|
|
# cinit walker would then treat an instruction as a record count. Relink with
|
|
# a one-word terminator when the map says the section is empty.
|
|
CSIZE=$(awk '$1 == ".cinit" {print $4; exit}' "$WORK/$MAIN.map")
|
|
if [ "$CSIZE" = "00000000" ]; then
|
|
sed -i 's/CINIT\.obj/CINITZ.obj/' "$CMD"
|
|
rm -f "$WORK/$MAIN.out" "$WORK/$MAIN.map"
|
|
run "$MAIN.out" ./gsplnk.exe "$MAIN.CMD"
|
|
fi
|
|
|
|
cp "$WORK/$MAIN.out" "$OUT/$OUTNAME.coff"
|
|
sed 's/\r$//' "$WORK/$MAIN.map" > "$OUT/$OUTNAME.map"
|
|
echo "build.sh: $OUT/$OUTNAME.coff ($(wc -c < "$OUT/$OUTNAME.coff") bytes)"
|
|
sed -n '1,40p' "$OUT/$OUTNAME.map"
|