Files
arti 1d8656ca10 udpstream: PIXBLT L,XY blit primitive (vram.asm) and a 256 KB .bss
vram_blit_ copies a 1-bpp rectangle from RAM to VRAM.  The manual has no L,L
variant, so the destination is XY and the hardware forms the address:
  B0=SADDR  B1=SPTCH  B2=DADDR(XY)  B3=DPTCH=0x800  B4=OFFSET=0x04000000
  B7=DYDX   PSIZE=1  PMASK=0  CONVSP=CONVDP=0x14  CONTROL raster-op=0
SPTCH is a parameter because 0 makes every row read the same source address,
which is how one expanded row can be stamped eight times down the screen.

The .bss region in the linker command grows from 0x40000 to 0x200000 address
units (32 KB -> 256 KB) so a 1280x1024 1-bpp frame buffer (163840 B) fits; the
previous .coff had been built from sources that were not yet committed.

bench-sweep.sh gains its executable bit.
2026-10-30 17:44:27 +02:00

117 lines
4.0 KiB
Bash
Executable File

#!/bin/sh
# Build the raw LANCE receive probe.
#
# harness/udpstream/build.sh
#
# .text at bit 0x018C0000, .bss at 0x01C00000 (both inside the firmware's large
# free block), entry _start, no .cinit (the runtime's autoinit pass does not
# run -- see harness/c-hello/README.md).
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
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
SRC=${LANCE_SRC:-$DIR/lance.c}
cp "$SRC" "$WORK/LANCE.C"
cp "$DIR/romapi.h" "$WORK/ROMAPI.H"
cp "$DIR/entry.asm" "$WORK/ENTRY.ASM"
cp "$DIR/vram.asm" "$WORK/VRAM.ASM"
{
printf '%s\n' '-a'
printf '%s\n' '-o LANCE.out'
printf '%s\n' '-m LANCE.map'
printf '%s\n' '-e _start'
printf '%s\n' 'LANCE.obj'
printf '%s\n' 'ENTRY.obj'
printf '%s\n' 'VRAM.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/LANCE.CMD"
sed -i 's/$/\r/' "$WORK/LANCE.CMD"
rm -f "$WORK"/LANCE.OBJ "$WORK"/LANCE.OUT "$WORK"/LANCE.LST \
"$WORK"/LANCE.MAP "$WORK"/LANCE.ASM "$WORK"/LANCE.CPP \
"$WORK"/LANCE.IF "$WORK"/ENTRY.OBJ "$WORK"/ENTRY.LST \
"$WORK"/VRAM.OBJ "$WORK"/VRAM.LST
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
timeout 240 dosbox -conf "$DOSBOX_CONF" -noprimaryconf -nolocalconf \
-c "mount c $WORK" -c "c:" \
-c "gspcpp LANCE" \
-c "gspcc LANCE" \
-c "gspcg LANCE" \
-c "gspa LANCE LANCE.obj LANCE.lst -l" \
-c "gspa ENTRY ENTRY.obj ENTRY.lst -l" \
-c "gspa VRAM VRAM.obj VRAM.lst -l" \
-c "gsplnk LANCE.cmd" \
-c "exit" -exit > "$WORK/dosbox.log" 2>&1
if [ ! -f "$WORK/LANCE.OUT" ]; then
echo "build.sh: GSPLNK produced no LANCE.OUT" >&2
sed 's/\r$//' "$WORK/LANCE.MAP" 2>/dev/null | tail -20 >&2 || true
for f in LANCE.LST ENTRY.LST VRAM.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 LANCE.LST ENTRY.LST VRAM.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
OUTNAME=${LANCE_OUT:-lance.coff}
cp "$WORK/LANCE.OUT" "$OUT/$OUTNAME"
sed 's/\r$//' "$WORK/LANCE.MAP" > "$OUT/lance.map"
# Guard: the marker block (MARK in the source) must sit clear of .text, or the
# payload overwrites its own code with cell() writes (an illegal-opcode crash).
python3 - "$SRC" "$OUT/lance.map" <<'PYCHK'
import re, sys
src, mp = sys.argv[1], sys.argv[2]
m = re.search(r'#define\s+MARK\s+(0x[0-9A-Fa-f]+)', open(src).read())
if m:
mark = int(m.group(1), 16)
for ln in open(mp):
f = ln.split()
if len(f) >= 4 and f[0] == '.text':
start, size = int(f[2], 16), int(f[3], 16)
end = start + size
if end > mark:
sys.stderr.write("build: ERROR .text ends at 0x%X, past MARK 0x%X\n" % (end, mark))
sys.exit(1)
print("build: .text ends 0x%X, MARK 0x%X (%d bytes clear)" % (end, mark, (mark - end) // 8))
PYCHK
sed 's/\r$//' "$WORK/LANCE.LST" > "$OUT/lance.lst"
sed 's/\r$//' "$WORK/ENTRY.LST" > "$OUT/entry.lst"
sed 's/\r$//' "$WORK/VRAM.LST" > "$OUT/vram.lst"
echo "build.sh: $OUT/$OUTNAME ($(wc -c < "$OUT/lance.coff") bytes)"
grep -E "ENTRY POINT|^\.(text|cinit|bss)" "$OUT/lance.map" | head -8