Files
vt1200/harness/c-hello/build.sh
T
arti 8f831eaf33 fix(video): model the real unit's VR319 monitor
The harness forced the VR150 monitor switch, so the firmware wrote the OS
screen at 1024 px / 128-byte rows.  VT1200_VRAM_REAL then re-read that
framebuffer at the VR319 pitch, which sheared the OS and wrapped the right
quarter of every row.

Model VR319 (switch 0x60) by default -- the real unit's mode -- so the
firmware itself programs 1280x1024 with a 256-byte row pitch (CONVDP=0x14).
The renderer's pitch follows VT1200_MONITOR, and the destination span now
comes from HEBLNK..HSBLNK instead of x=0, placing the active 1280 px at
x=336 in MAME's 1696-wide raster.

Verified: clean Terminal Manager at frame 600, legible faithful diagnostics
menu and level-1 error screens, tile mode PASS with tile_check 1280/1280
tiles, tablet/mouse pixel-identical.  VT1200_MONITOR=VR150 reproduces the
old geometry; the regression baseline moves 198 -> 199 (2 PCs) and is
recorded in harness/mame/README.md.
2026-10-31 20:53:51 +02:00

117 lines
4.1 KiB
Bash
Executable File

#!/bin/sh
# Build the C hello world with the 1987 TI TMS34010 SDK (K&R C compiler).
#
# harness/c-hello/build.sh
#
# Pipeline: gspcpp -> gspcc -> gspcg -> gspa -> gsplnk, all under DOSBox.
# entry.asm is assembled separately: it is the process entry (sets STK/FP,
# calls _main, `rets`) and replaces boot.obj, whose exit path is a `for(;;)`
# spin followed by an `reti` -- both wrong for a create_process child.
#
# .text/.data are linked at bit 0x018A0000, .bss at 0x01A00000 (both inside the
# firmware's large free block).
#
# Outputs: build/hello.coff (the linker output the COFF loader eats),
# hello.map, hello.lst, entry.lst, hello.obj
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=018A0000
BSS=01A00000
# `build.sh emu` builds a 128-byte-stride variant for the harness's VR150 mode
# (VT1200_MONITOR=VR150); the default VR319 layout matches the real unit.
MODE=${1:-real}
NAME=hello
if [ "$MODE" = "emu" ]; then NAME=hello-emu; 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
if [ "$MODE" = "emu" ]; then
sed 's/#define ROW_BYTES 256/#define ROW_BYTES 128/' "$DIR/hello.c" > "$WORK/HELLO.C"
else
cp "$DIR/hello.c" "$WORK/HELLO.C"
fi
cp "$DIR/entry.asm" "$WORK/ENTRY.ASM"
{
printf '%s\n' '-a'
printf '%s\n' '-o HELLO.out'
printf '%s\n' '-m HELLO.map'
printf '%s\n' '-e _start'
printf '%s\n' 'HELLO.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 = 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' '}'
} > "$WORK/HELLO.CMD"
sed -i 's/$/\r/' "$WORK/HELLO.CMD"
rm -f "$WORK"/HELLO.OBJ "$WORK"/HELLO.OUT "$WORK"/HELLO.LST \
"$WORK"/HELLO.MAP "$WORK"/HELLO.HI "$WORK"/HELLO.LO \
"$WORK"/HELLO.ASM "$WORK"/HELLO.CPP "$WORK"/HELLO.IF \
"$WORK"/ENTRY.OBJ "$WORK"/ENTRY.LST
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
timeout 240 dosbox -conf "$DOSBOX_CONF" -noprimaryconf -nolocalconf \
-c "mount c $WORK" -c "c:" \
-c "gspcpp HELLO" \
-c "gspcc HELLO" \
-c "gspcg HELLO" \
-c "gspa HELLO HELLO.obj HELLO.lst -l" \
-c "gspa ENTRY ENTRY.obj ENTRY.lst -l" \
-c "gsplnk HELLO.cmd" \
-c "exit" -exit > "$WORK/dosbox.log" 2>&1
if [ ! -f "$WORK/HELLO.OUT" ]; then
echo "build.sh: GSPLNK produced no HELLO.OUT" >&2
sed 's/\r$//' "$WORK/HELLO.MAP" 2>/dev/null | tail -20 >&2 || true
exit 1
fi
if [ ! -f "$WORK/HELLO.OBJ" ] || [ ! -f "$WORK/ENTRY.OBJ" ]; then
echo "build.sh: missing object file (compile/assemble failed)" >&2
for f in HELLO.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
# NB: the C code generator writes "***" banner comments into the .s file, so the
# assembly listing is full of asterisks; only real error lines are matched here.
for f in HELLO.LST ENTRY.LST; do
if sed 's/\r$//' "$WORK/$f" | 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/HELLO.OUT" "$OUT/$NAME.coff"
cp "$WORK/HELLO.OBJ" "$OUT/hello.obj"
cp "$WORK/ENTRY.OBJ" "$OUT/entry.obj"
sed 's/\r$//' "$WORK/HELLO.MAP" > "$OUT/hello.map"
sed 's/\r$//' "$WORK/HELLO.LST" > "$OUT/hello.lst"
sed 's/\r$//' "$WORK/ENTRY.LST" > "$OUT/entry.lst"
[ -f "$WORK/HELLO.ASM" ] && sed 's/\r$//' "$WORK/HELLO.ASM" > "$OUT/hello.s"
echo "build.sh: $OUT/$NAME.coff ($(wc -c < "$OUT/hello.coff") bytes)"
sed -n '1,40p' "$OUT/hello.map"