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.
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(byte0x00300000of the 4 MiB main RAM); - writes
0xDEAD,0xBEEFand a loop counter0x0400to RAM at bit0x01810000, 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.