Files
vt1200/harness/hello-world/README.md
T
SDD 1608a68cdb hello-world: the TMS34010 SDK assembles code that runs on the emulated VT1200
An 82-byte payload written in GSPA assembly, linked at bit 01800000h and
loaded into main RAM by harness/mame/hello.lua, executes on the CPU: it
writes DEAD/BEEF and a 1024-iteration counter into RAM and fills a 256x64
block in video RAM, which appears in the frame dump at x 256..511,
y 136..199.  Entry is a debugger breakpoint on the level-0 menu idle loop,
not a delivery mechanism.  Includes the build script, a COFF .text
extractor (gsprom's hex addresses wrap at 64 KB), the run log, RAM excerpt,
frame crops including a no-load control, and HELLO_WORLD_REPORT.md.
2026-10-18 01:20:38 +03:00

3.5 KiB

Hello world: a payload built with the TMS34010 SDK

A minimal payload written in GSPA assembly, assembled and linked by the 1987 TI TMS34010 SDK (GSPA 2.00 / GSPLNK 2.00) under DOSBox, then loaded into main RAM and entered by harness/mame/hello.lua.

This is our code, not a disassembly of the firmware. The ROM (vt1200_v22.bin, md5 b46a3e442ccb86134d2356bd70d22fd2) is only read.

Read harness/mame/HELLO_WORLD_REPORT.md for the evidence and caveats. The short version:

  • linked at bit 0x01800000 (byte 0x00300000 of the 4 MiB main RAM);
  • writes 0xDEAD, 0xBEEF and a loop counter 0x0400 to RAM at bit 0x01810000, and fills a 256x64 block in video RAM at row 100, column 64;
  • both are observed from inside the emulator (RAM readback) and from a frame dump (white block at screen x 256..511, y 136..199).

Build

harness/hello-world/build.sh                 # origin defaults to 01800000h
harness/hello-world/build.sh 01840000        # alternate bit address

It extracts the DOS tools into work/ on first use (same image and method as harness/sdk-roundtrip/roundtrip.sh), assembles hello.asm, links it, and extracts the .text section from the COFF with cofextract.py.

Outputs:

file what it is
payload.bin the linked bytes (82 bytes)
payload.map GSPLNK's map, with the bit-address origin
work/HELLO.LST GSPA listing (addresses in bits)

payload.bin and payload.map are committed, so the MAME run does not need DOSBox or the SDK. Rebuild them to change the payload.

Run

From the repository root:

M=/home/arti/code/k-space/mame0289/vt1200

HELLO_END=150 \
VT1200_DUMP_FRAME=145 VT1200_DUMP_RAM=145 \
VT1200_DUMP_DIR=harness/hello-world/evidence \
$M vt1200 -rompath harness/mame/roms -video none -sound none -nothrottle \
   -debug -debugger none \
   -autoboot_script harness/mame/hello.lua -autoboot_delay 0

Environment knobs (all optional):

variable default meaning
HELLO_AT 120 frame at which to load the payload and arm the entry breakpoint
HELLO_END 150 frame at which to inspect the markers and exit
HELLO_PAYLOAD harness/hello-world/payload.bin linked payload
HELLO_ORIGIN 0x01800000 load/entry bit address

Set HELLO_AT=9999 for the control run: nothing is loaded, and the markers stay zero.

Mechanism (and what it is not)

hello.lua lets the firmware boot to the level-0 diagnostics menu, writes the payload bytes into RAM at frame 120, and arms a breakpoint on the menu's idle loop (3FDCE400, dsjs a9, itself). The breakpoint action assigns pc = 01800000 and resumes. The payload then runs, masks interrupts, writes its markers and the VRAM block, and spins.

This is debugger entry, not a delivery mechanism. It proves the toolchain produces runnable code and the payload runs on the emulated CPU; it says nothing about how code would reach a real terminal.

Evidence files

file what it shows
evidence/hello-run.log transcript of the run above
evidence/hello-ram-marker.txt RAM excerpt: payload bytes and marker words
evidence/hello-frame-145.png the frame at 145, cropped to the menu + block
evidence/control-frame-145.png the same crop with HELLO_AT=9999 (no block)
evidence/hello-payload.dis dis34 disassembly of payload.bin, base 01800000

The .ppm and .bin dumps referenced in hello-run.log are large and are not committed; the command above regenerates them.