c-hello: first C program on the VT1200, running on real hardware

The 1987 TI K&R toolchain already compiled and linked a fib test, but nothing
had ever been executed on a VT1200. This is that program: hello.c draws HELLO
into video RAM (1 bpp, bit 0x04000000, no X11) and is loaded through the COFF
loader with hostload.py, on the real unit and in MAME.

Two runtime traps shaped the design, both recorded in the README:

  * boot.obj's exit() is `for(;;)` and _c_int00 ends in `reti`.  That is a
    standalone-ROM runtime, not a process: the child spun forever, and because
    the VT1200 OS is cooperative it took the whole terminal down (illegal
    opcode on hardware).  entry.asm replaces boot.obj -- set STK/FP, call
    _main, `rets` back to the create_process trampoline, the same return
    xhello uses -- and the image carries no .cinit (tables are built in code).
  * Pointers are bit addresses and pointer arithmetic scales by object size,
    so p + n on a char * is n bytes.  The pre-fix frame in evidence/ is that
    bug: 32 one-byte bars spread across a row.

Framebuffer geometry is not portable: the real unit is 1280 px wide at a
256-byte row pitch, MAME's canvas is 1024 px at 128.  build.sh builds both
(ROW_BYTES), and the README records how the real pitch was measured from a
real-unit frame rather than taken from MAME.

Evidence: real-unit frames in harness/c-hello/evidence/ (the pre-fix stripes
and the working HELLO), and dwt/loader/evidence/real-unit-xhello/ for the X
window that ran on the unit earlier.
This commit is contained in:
arti committed 2026-10-29 18:25:38 +02:00
1 parent 6338095683
commit 41b0979aef
16 files changed
+1124

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

+1
View File
@@ -0,0 +1 @@
work/
+115
View File
@@ -0,0 +1,115 @@
# harness/c-hello — the first C program on the VT1200
A C hello world built with the **1987 TI TMS34010 SDK** (K&R compiler,
`GSPCC`/`GSPCG` 2.01, `GSPA`/`GSPLNK` 2.00, `RTS.LIB`) and run on **real
hardware** — not a debugger poke of assembly, and no X11: it writes the word
`HELLO` straight into video RAM.
It is also the project's smallest end-to-end proof of the C path:
```
gspcpp -> gspcc -> gspcg -> gspa -> gsplnk (DOSBox, 1987 tools)
-> hello.coff (GSPLNK COFF, sections at bit addresses)
-> dwt/loader/hostload.py (rdebug -> malloc -> poke COFF -> COFF loader)
-> loader.asm (free-list check, copy .text, zero .bss, create_process)
-> _start (entry.asm) -> main -> VRAM at bit 0x04000000
```
## Files
| file | what it is |
|---|---|
| `hello.c` | the payload: 5x7 font, 8x-scaled `HELLO` in a black 256x72 box, markers at `0x018A8000` |
| `entry.asm` | the process entry: sets `STK`/`FP`, `calla _main`, `rets` (replaces `boot.obj`) |
| `build.sh` | DOSBox wrapper; `build.sh` = real unit (256-byte row pitch), `build.sh emu` = MAME (128) |
| `build/hello.coff` | linked image for the real unit, entry `_start` |
| `build/hello-emu.coff` | same source with `ROW_BYTES 128`, for MAME's canvas |
| `build/hello.map`, `hello.lst`, `entry.lst`, `hello.s` | link map and listings |
| `evidence/hello_frame.png` | real unit, **pre-fix**: the pointer-arithmetic bug, one-byte bars spread over a whole row |
| `evidence/hello_real_frame.png` | real unit, working: the current box at x=40 and, to its right, the previous run's box at x=320 (nothing erases VRAM between runs) |
| `work/` | extracted SDK + DOS scratch (git-ignored) |
## Build
```sh
./harness/c-hello/build.sh # real unit: .text 0x018A0000, .bss 0x01A00000
./harness/c-hello/build.sh emu # MAME: same addresses, 128-byte row pitch
```
Both land inside the firmware's large free block (byte `0x0C03AA..0x400000` on a
fresh boot). The link map must show `.cinit` empty and entry `_start`:
```
ENTRY POINT SYMBOL: "_start" address: 018A17E0
.text 018A0000 .cinit 018A1870 (size 0) .bss 01A00000
```
## Run
Real unit (rdebug on TCP 771; the terminal needs the OS up):
```sh
python3 dwt/heapmap.py --host 100.103.100.103 --at 0x018A0000 # read-only preflight
python3 dwt/heapmap.py --host 100.103.100.103 --at 0x01A00000
python3 dwt/loader/hostload.py --host 100.103.100.103 \
--coff harness/c-hello/build/hello.coff \
--out harness/c-hello/evidence --real --settle 3
python3 dwt/solve.py --host 100.103.100.103 --peek 0x018A8000 --len 8 # HELL DONE
python3 dwt/screenshot.py --host 100.103.100.103 --real --out /tmp/hello.png
```
MAME (debugger-assisted, no network):
```sh
VT1200_SKIP_LEVEL1=1 LOADER_AT=2500 LOADER_END=2800 LOADER_SNAP=1 \
LOADER_COFF=$PWD/harness/c-hello/build/hello-emu.coff LOADER_OUT=/tmp/chello \
/home/arti/code/k-space/mame0289/vt1200 vt1200 \
-rompath harness/mame/roms -video none -sound none -nothrottle -skip_gameinfo \
-debug -debugger none -autoboot_script dwt/loader/loader.lua -autoboot_delay 0
```
Success = loader status 0, `entry=0x018A17E0`, markers `48454C4C`/`444F4E45`
(`HELL`/`DONE`), and the box on screen. On the real unit the box is at
**x=40, y=800**, 256x72 pixels.
## Three traps this image exists to record
1. **`boot.obj`'s `exit()` is `for(;;)` and `_c_int00` ends in `reti`.**
That is a standalone-ROM runtime, not a process. Linked with `-c`, the child
finishes `main`, spins forever (the linked `jruc self` at `0x018A1520`), and
because the VT1200 OS is cooperative it starves the whole machine; on real
hardware the terminal fell over with an illegal opcode. `-cr` is no better —
it still pulls in `boot.obj` and still defines `_c_int00`. Hence
`entry.asm`: no `boot.obj`, entry `_start`, plain `rets` back to the
`create_process` trampoline (the same return `xhello` uses). `SP` (the OS's
interrupt stack) is left alone; only `STK`/`FP` are set.
2. **Pointers are bit addresses and pointer arithmetic scales by object size.**
A `char *` step is 8 bits, so `p + px*8` advances 8 *bytes*, not one. Address
bytes as `addr + px*8` bits and cast. The pre-fix frame
(`evidence/hello_frame.png`) is that bug: 32 one-byte bars spread over a
whole row.
3. **No `.cinit`.** With `entry.asm` the runtime's autoinit pass never runs, so
the image must not need static initializers. The font and order tables are
filled in `build_font()` at runtime.
## Geometry is not portable between the real unit and MAME
The two framebuffers differ, and the payload carries the difference as
`ROW_BYTES`:
| | real unit (measured) | MAME |
|---|---|---|
| base | bit `0x04000000` | bit `0x04000000` |
| row pitch | **256 bytes** (`ROW_BYTES 256`) | 128 bytes (`VMEM_PITCH_BITS`) |
| pixels per row | 1280 (160 bytes) + 96 B `0x55` mask | 1024 |
| screen | 1280x1024 | 1024x864 snapshot in MAME's 1280x901 |
The real pitch is measured, not assumed: a payload writing at `row*2048` bits
lands on scanline `row` and a 256-pixel box at pixel 40 appears at x=40 — and
the pre-fix frame's bars, written 8 bytes apart from byte 40, run to the end of
a 1280-pixel line. Under a 128-byte pitch the same writes would wrap into the
next memory row. `dwt/screenshot.py --real` (1280 wide, stride 256, LSB-first)
also decodes live VRAM correctly, which pins the bit order.
Do not use a MAME frame as proof of pixel placement: same code, different
framebuffer.
+115
View File
@@ -0,0 +1,115 @@
#!/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 MAME's 1024x1024 canvas.
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"
+35
View File
@@ -0,0 +1,35 @@
GSP COFF Assembler, Version 2.00, 87.300 Thu Oct 29 18:24:36 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; entry.asm -- process entry for the C hello world.
0002 ;
0003 ; The C runtime's boot.obj is designed for a ROM system
0004 ; *system* stack), calls main, calls exit (which is `fo
0005 ; `reti`. None of that fits a process made by the VT12
0006 ; the spin never yields, and `reti` returns from an int
0007 ; happened (it pops a garbage PC -> illegal opcode).
0008 ;
0009 ; So we enter here instead: set the C program stack (ST
0010 ; main, and `rets` back to the create_process trampolin
0011 ; xhello payload uses. SP (the OS's interrupt stack) i
0012 ;
0013 ; _cstack is 4096 bytes; the compiler grows the program
0014
0015 00000000 .text
0016 .globl _start
0017 .globl _main
0018 00000000 _start:
0019 00000000 0740 setf 32, 0, 1
0020 00000010 09EE movi _cstack, a14
00000020 00000000+
0021 00000040 4DCD move a14, a13
0022 00000050 0D5F calla _main
00000060 00000000!
0023 00000080 0960 rets
0024
0025 00000000 .bss _cstack, 32768, 16 ; 32768 bits = 4096 bytes
0026 .end
No Errors, No Warnings
Binary file not shown.
Binary file not shown.
Binary file not shown.
+415
View File
@@ -0,0 +1,415 @@
GSP COFF Assembler, Version 2.00, 87.300 Thu Oct 29 18:24:36 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 *******************************************************
0002 * GSP C COMPILER, Version 2.01, 87.300 *
0003 *******************************************************
0004 000D FP .set A13
0005 000E STK .set A14
0006 00000000 .bss STATIC_1,224,16
0007 000000E0 .bss STATIC_2,40,16
0008 00000110 .bss STATIC_3,18432,16
0009 .file "HELLO.c"
0010 ******************************************************
0011 * FUNCTION DEF : _build_font
0012 ******************************************************
0013 00000000 _build_font:
0014 00000000 A38F MOVE A12,-*SP,1
0015 00000010 1A2C MOVK 17,A12
0016 00000020 05EC MOVB A12,@STATIC_1
00000030 00000000+
0017 00000050 05EC MOVB A12,@STATIC_1+8
00000060 00000008+
0018 00000080 11CC ADDK 14,A12
0019 00000090 05EC MOVB A12,@STATIC_1+16
000000A0 00000010+
0020 000000C0 15CC SUBK 14,A12
0021 000000D0 05EC MOVB A12,@STATIC_1+24
000000E0 00000018+
0022 00000100 05EC MOVB A12,@STATIC_1+32
00000110 00000020+
0023 00000130 05EC MOVB A12,@STATIC_1+40
00000140 00000028+
0024 00000160 05EC MOVB A12,@STATIC_1+48
00000170 00000030+
0025 00000190 11CC ADDK 14,A12
0026 000001A0 05EC MOVB A12,@STATIC_1+56
000001B0 00000038+
0027 000001D0 15EC SUBK 15,A12
0028 000001E0 05EC MOVB A12,@STATIC_1+64
000001F0 00000040+
0029 00000210 05EC MOVB A12,@STATIC_1+72
00000220 00000048+
0030 00000240 11CC ADDK 14,A12
0031 00000250 05EC MOVB A12,@STATIC_1+80
00000260 00000050+
0032 00000280 15CC SUBK 14,A12
0033 00000290 05EC MOVB A12,@STATIC_1+88
000002A0 00000058+
0034 000002C0 05EC MOVB A12,@STATIC_1+96
000002D0 00000060+
0035 000002F0 11EC ADDK 15,A12
0036 00000300 05EC MOVB A12,@STATIC_1+104
00000310 00000068+
0037 00000330 15EC SUBK 15,A12
0038 00000340 05EC MOVB A12,@STATIC_1+112
00000350 00000070+
0039 00000370 05EC MOVB A12,@STATIC_1+120
00000380 00000078+
0040 000003A0 05EC MOVB A12,@STATIC_1+128
GSP COFF Assembler, Version 2.00, 87.300 Thu Oct 29 18:24:36 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
000003B0 00000080+
0041 000003D0 05EC MOVB A12,@STATIC_1+136
000003E0 00000088+
0042 00000400 05EC MOVB A12,@STATIC_1+144
00000410 00000090+
0043 00000430 05EC MOVB A12,@STATIC_1+152
00000440 00000098+
0044 00000460 11EC ADDK 15,A12
0045 00000470 05EC MOVB A12,@STATIC_1+160
00000480 000000A0+
0046 000004A0 162C SUBK 17,A12
0047 000004B0 05EC MOVB A12,@STATIC_1+168
000004C0 000000A8+
0048 000004E0 106C ADDK 3,A12
0049 000004F0 05EC MOVB A12,@STATIC_1+176
00000500 000000B0+
0050 00000520 05EC MOVB A12,@STATIC_1+184
00000530 000000B8+
0051 00000550 05EC MOVB A12,@STATIC_1+192
00000560 000000C0+
0052 00000580 05EC MOVB A12,@STATIC_1+200
00000590 000000C8+
0053 000005B0 05EC MOVB A12,@STATIC_1+208
000005C0 000000D0+
0054 000005E0 146C SUBK 3,A12
0055 000005F0 05EC MOVB A12,@STATIC_1+216
00000600 000000D8+
0056 00000620 458C SUB A12,A12
0057 00000630 05EC MOVB A12,@STATIC_2
00000640 000000E0+
0058 00000660 102C ADDK 1,A12
0059 00000670 05EC MOVB A12,@STATIC_2+8
00000680 000000E8+
0060 000006A0 418C ADD A12,A12
0061 000006B0 05EC MOVB A12,@STATIC_2+16
000006C0 000000F0+
0062 000006E0 05EC MOVB A12,@STATIC_2+24
000006F0 000000F8+
0063 00000710 102C ADDK 1,A12
0064 00000720 05EC MOVB A12,@STATIC_2+32
00000730 00000100+
0065 00000750 EPI0_1:
0066 00000750 97EC MOVE *SP+,A12,1
0067 00000760 0960 RETS 0
0068 .globl _main
0069 ******************************************************
0070 * FUNCTION DEF : _main
0071 ******************************************************
0072 00000770 _main:
0073 00000770 098F MMTM SP,A3,A5,A7,A12,FP
00000780 150C
0074 00000790 4DCD MOVE STK,FP
0075 000007A0 0B0E ADDI 288,STK
000007B0 0120
0076 000007C0 0D5F CALLA _build_font
000007D0 00000000'
GSP COFF Assembler, Version 2.00, 87.300 Thu Oct 29 18:24:36 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 3
0077 000007F0 09EC MOVI 1212501068,A12
00000800 48454C4C
0078 00000820 078C MOVE A12,@0018A8000h,1
00000830 018A8000
0079 00000850 578C CLR A12
0080 00000860 B38D MOVE A12,*FP(192),1
00000870 00C0
0081 00000880 C01F JRUC L1
0082 00000890 L4:
0083 00000890 578C CLR A12
0084 000008A0 B38D MOVE A12,*FP(160),1
000008B0 00A0
0085 000008C0 C011 JRUC L5
0086 000008D0 L8:
0087 000008D0 B7A7 MOVE *FP(192),A7,1
000008E0 00C0
0088 000008F0 2507 SLL 8,A7
0089 00000900 0B27 ADDI STATIC_3,A7
00000910 00000110+
0090 00000930 B7A5 MOVE *FP(160),A5,1
00000940 00A0
0091 00000950 2465 SLL 3,A5
0092 00000960 40A7 ADD A5,A7
0093 00000970 56A5 CLR A5
0094 00000980 8CA7 MOVB A5,*A7
0095 00000990 B7A7 MOVE *FP(160),A7,1
000009A0 00A0
0096 000009B0 1027 ADDK 1,A7
0097 000009C0 B2ED MOVE A7,*FP(160),1
000009D0 00A0
0098 000009E0 L5:
0099 000009E0 B7A7 MOVE *FP(160),A7,1
000009F0 00A0
0100 00000A00 0B47 CMPI 32,A7
00000A10 FFDF
0101 00000A20 C4EA JRLT L8
0102 00000A30 B7A5 MOVE *FP(192),A5,1
00000A40 00C0
0103 00000A50 1025 ADDK 1,A5
0104 00000A60 B2AD MOVE A5,*FP(192),1
00000A70 00C0
0105 00000A80 L1:
0106 00000A80 B7A7 MOVE *FP(192),A7,1
00000A90 00C0
0107 00000AA0 0B47 CMPI 72,A7
00000AB0 FFB7
0108 00000AC0 C4DC JRLT L4
0109 00000AD0 578C CLR A12
0110 00000AE0 838D MOVE A12,*FP,1
0111 00000AF0 C000 JRUC L9
00000B00 0085
0112 00000B10 L12:
0113 00000B10 578C CLR A12
0114 00000B20 B38D MOVE A12,*FP(32),1
00000B30 0020
0115 00000B40 C079 JRUC L13
GSP COFF Assembler, Version 2.00, 87.300 Thu Oct 29 18:24:36 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 4
0116 00000B50 L16:
0117 00000B50 87A7 MOVE *FP,A7,1
0118 00000B60 2467 SLL 3,A7
0119 00000B70 0B27 ADDI STATIC_2,A7
00000B80 000000E0+
0120 00000BA0 0548 SETF 8,0,0
0121 00000BB0 84E7 MOVE *A7,A7
0122 00000BC0 09CC MOVI 56,A12
00000BD0 0038
0123 00000BE0 5D87 MPYS A12,A7
0124 00000BF0 0B27 ADDI STATIC_1,A7
00000C00 00000000+
0125 00000C20 B7A5 MOVE *FP(32),A5,1
00000C30 0020
0126 00000C40 2465 SLL 3,A5
0127 00000C50 40A7 ADD A5,A7
0128 00000C60 84E7 MOVE *A7,A7
0129 00000C70 B2ED MOVE A7,*FP(224),1
00000C80 00E0
0130 00000C90 578C CLR A12
0131 00000CA0 B38D MOVE A12,*FP(64),1
00000CB0 0040
0132 00000CC0 C057 JRUC L17
0133 00000CD0 L20:
0134 00000CD0 1A07 MOVK 16,A7
0135 00000CE0 B7A5 MOVE *FP(64),A5,1
00000CF0 0040
0136 00000D00 03A5 NEG A5
0137 00000D10 64A7 SRA A5,A7
0138 00000D20 B7A5 MOVE *FP(224),A5,1
00000D30 00E0
0139 00000D40 50A7 AND A5,A7
0140 00000D50 CA49 JRZ L18
0141 00000D60 56E7 CLR A7
0142 00000D70 B2ED MOVE A7,*FP(128),1
00000D80 0080
0143 00000D90 C040 JRUC L22
0144 00000DA0 L25:
0145 00000DA0 578C CLR A12
0146 00000DB0 B38D MOVE A12,*FP(96),1
00000DC0 0060
0147 00000DD0 C032 JRUC L26
0148 00000DE0 L29:
0149 00000DE0 87A7 MOVE *FP,A7,1
0150 00000DF0 4CE5 MOVE A7,A5
0151 00000E00 24A7 SLL 5,A7
0152 00000E10 2485 SLL 4,A5
0153 00000E20 40E5 ADD A7,A5
0154 00000E30 1105 ADDK 8,A5
0155 00000E40 B7A7 MOVE *FP(64),A7,1
00000E50 0040
0156 00000E60 2467 SLL 3,A7
0157 00000E70 40E5 ADD A7,A5
0158 00000E80 B7A7 MOVE *FP(96),A7,1
00000E90 0060
0159 00000EA0 40E5 ADD A7,A5
GSP COFF Assembler, Version 2.00, 87.300 Thu Oct 29 18:24:36 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 5
0160 00000EB0 B2AD MOVE A5,*FP(160),1
00000EC0 00A0
0161 00000ED0 B7A7 MOVE *FP(32),A7,1
00000EE0 0020
0162 00000EF0 2467 SLL 3,A7
0163 00000F00 1107 ADDK 8,A7
0164 00000F10 B7A5 MOVE *FP(128),A5,1
00000F20 0080
0165 00000F30 40A7 ADD A5,A7
0166 00000F40 B2ED MOVE A7,*FP(192),1
00000F50 00C0
0167 00000F60 2507 SLL 8,A7
0168 00000F70 0B27 ADDI STATIC_3,A7
00000F80 00000110+
0169 00000FA0 B7A5 MOVE *FP(160),A5,1
00000FB0 00A0
0170 00000FC0 2BA5 SRA 3,A5
0171 00000FD0 2465 SLL 3,A5
0172 00000FE0 40A7 ADD A5,A7
0173 00000FF0 B7A5 MOVE *FP(160),A5,1
00001000 00A0
0174 00001010 18EC MOVK 7,A12
0175 00001020 5185 AND A12,A5
0176 00001030 1823 MOVK 1,A3
0177 00001040 62A3 SLL A5,A3
0178 00001050 2703 SLL 24,A3
0179 00001060 2D03 SRL 24,A3
0180 00001070 0548 SETF 8,0,0
0181 00001080 84E5 MOVE *A7,A5
0182 00001090 5465 OR A3,A5
0183 000010A0 8CA7 MOVB A5,*A7
0184 000010B0 B7A7 MOVE *FP(96),A7,1
000010C0 0060
0185 000010D0 1027 ADDK 1,A7
0186 000010E0 B2ED MOVE A7,*FP(96),1
000010F0 0060
0187 00001100 L26:
0188 00001100 B7A7 MOVE *FP(96),A7,1
00001110 0060
0189 00001120 0B47 CMPI 8,A7
00001130 FFF7
0190 00001140 C4C9 JRLT L29
0191 00001150 B7A5 MOVE *FP(128),A5,1
00001160 0080
0192 00001170 1025 ADDK 1,A5
0193 00001180 B2AD MOVE A5,*FP(128),1
00001190 0080
0194 000011A0 L22:
0195 000011A0 B7A7 MOVE *FP(128),A7,1
000011B0 0080
0196 000011C0 0B47 CMPI 8,A7
000011D0 FFF7
0197 000011E0 C4BB JRLT L25
0198 000011F0 L18:
0199 000011F0 B7A7 MOVE *FP(64),A7,1
00001200 0040
GSP COFF Assembler, Version 2.00, 87.300 Thu Oct 29 18:24:36 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 6
0200 00001210 1027 ADDK 1,A7
0201 00001220 B2ED MOVE A7,*FP(64),1
00001230 0040
0202 00001240 L17:
0203 00001240 B7A7 MOVE *FP(64),A7,1
00001250 0040
0204 00001260 0B47 CMPI 5,A7
00001270 FFFA
0205 00001280 C4A4 JRLT L20
0206 00001290 B7A5 MOVE *FP(32),A5,1
000012A0 0020
0207 000012B0 1025 ADDK 1,A5
0208 000012C0 B2AD MOVE A5,*FP(32),1
000012D0 0020
0209 000012E0 L13:
0210 000012E0 B7A7 MOVE *FP(32),A7,1
000012F0 0020
0211 00001300 0B47 CMPI 7,A7
00001310 FFF8
0212 00001320 C482 JRLT L16
0213 00001330 87A5 MOVE *FP,A5,1
0214 00001340 1025 ADDK 1,A5
0215 00001350 82AD MOVE A5,*FP,1
0216 00001360 L9:
0217 00001360 87A7 MOVE *FP,A7,1
0218 00001370 0B47 CMPI 5,A7
00001380 FFFA
0219 00001390 C400 JRLT L12
000013A0 FF76
0220 000013B0 578C CLR A12
0221 000013C0 B38D MOVE A12,*FP(192),1
000013D0 00C0
0222 000013E0 C02E JRUC L30
0223 000013F0 L33:
0224 000013F0 B7A7 MOVE *FP(192),A7,1
00001400 00C0
0225 00001410 0B07 ADDI 800,A7
00001420 0320
0226 00001430 2547 SLL 10,A7
0227 00001440 0B27 ADDI 67108904,A7
00001450 04000028
0228 00001470 B2ED MOVE A7,*FP(256),1
00001480 0100
0229 00001490 578C CLR A12
0230 000014A0 B38D MOVE A12,*FP(160),1
000014B0 00A0
0231 000014C0 C016 JRUC L34
0232 000014D0 L37:
0233 000014D0 B7A7 MOVE *FP(256),A7,1
000014E0 0100
0234 000014F0 B7A5 MOVE *FP(160),A5,1
00001500 00A0
0235 00001510 2465 SLL 3,A5
0236 00001520 40E5 ADD A7,A5
0237 00001530 B7A7 MOVE *FP(192),A7,1
00001540 00C0
GSP COFF Assembler, Version 2.00, 87.300 Thu Oct 29 18:24:36 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 7
0238 00001550 2507 SLL 8,A7
0239 00001560 0B27 ADDI STATIC_3,A7
00001570 00000110+
0240 00001590 B7A3 MOVE *FP(160),A3,1
000015A0 00A0
0241 000015B0 2463 SLL 3,A3
0242 000015C0 4067 ADD A3,A7
0243 000015D0 9CE5 MOVB *A7,*A5
0244 000015E0 B7A7 MOVE *FP(160),A7,1
000015F0 00A0
0245 00001600 1027 ADDK 1,A7
0246 00001610 B2ED MOVE A7,*FP(160),1
00001620 00A0
0247 00001630 L34:
0248 00001630 B7A7 MOVE *FP(160),A7,1
00001640 00A0
0249 00001650 0B47 CMPI 32,A7
00001660 FFDF
0250 00001670 C4E5 JRLT L37
0251 00001680 B7A5 MOVE *FP(192),A5,1
00001690 00C0
0252 000016A0 1025 ADDK 1,A5
0253 000016B0 B2AD MOVE A5,*FP(192),1
000016C0 00C0
0254 000016D0 L30:
0255 000016D0 B7A7 MOVE *FP(192),A7,1
000016E0 00C0
0256 000016F0 0B47 CMPI 72,A7
00001700 FFB7
0257 00001710 C4CD JRLT L33
0258 00001720 09EC MOVI 1146048069,A12
00001730 444F4E45
0259 00001750 078C MOVE A12,@0018A8020h,1
00001760 018A8020
0260 00001780 5708 CLR A8
0261 00001790 EPI0_2:
0262 00001790 0B0E ADDI -288,STK
000017A0 FEE0
0263 000017B0 09AF MMFM SP,A3,A5,A7,A12,FP
000017C0 30A8
0264 000017D0 0960 RETS 0
0265 .end
No Errors, No Warnings
+49
View File
@@ -0,0 +1,49 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Thu Oct 29 18:24:36 2026
OUTPUT FILE NAME: <HELLO.out>
ENTRY POINT SYMBOL: "_start" address: 018A17E0
MEMORY CONFIGURATION
name origin length attributes
-------- -------- --------- ----------
prog 018A0000 000020000 RWIX
ram 01A00000 000040000 RWIX
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.text 0 018A0000 00001870
018A0000 000017E0 HELLO.obj (.text)
018A17E0 00000090 ENTRY.obj (.text)
.data 0 018A1870 00000000
.cinit 0 018A1870 00000000 UNINITIALIZED
.bss 0 01A00000 0000C910 UNINITIALIZED
01A00000 00004910 HELLO.obj (.bss)
01A04910 00008000 ENTRY.obj (.bss)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
01A00000 .bss 018A0000 .text
018A1870 .data 018A0770 _main
018A0000 .text 018A17E0 _start
018A0770 _main 018A1870 edata
018A17E0 _start 018A1870 .data
018A1870 edata 018A1870 etext
01A0C910 end 01A00000 .bss
018A1870 etext 01A0C910 end
[8 symbols]
Binary file not shown.
+265
View File
@@ -0,0 +1,265 @@
*******************************************************
* GSP C COMPILER, Version 2.01, 87.300 *
*******************************************************
FP .set A13
STK .set A14
.bss STATIC_1,224,16
.bss STATIC_2,40,16
.bss STATIC_3,18432,16
.file "HELLO.c"
******************************************************
* FUNCTION DEF : _build_font
******************************************************
_build_font:
MOVE A12,-*SP,1
MOVK 17,A12
MOVB A12,@STATIC_1
MOVB A12,@STATIC_1+8
ADDK 14,A12
MOVB A12,@STATIC_1+16
SUBK 14,A12
MOVB A12,@STATIC_1+24
MOVB A12,@STATIC_1+32
MOVB A12,@STATIC_1+40
MOVB A12,@STATIC_1+48
ADDK 14,A12
MOVB A12,@STATIC_1+56
SUBK 15,A12
MOVB A12,@STATIC_1+64
MOVB A12,@STATIC_1+72
ADDK 14,A12
MOVB A12,@STATIC_1+80
SUBK 14,A12
MOVB A12,@STATIC_1+88
MOVB A12,@STATIC_1+96
ADDK 15,A12
MOVB A12,@STATIC_1+104
SUBK 15,A12
MOVB A12,@STATIC_1+112
MOVB A12,@STATIC_1+120
MOVB A12,@STATIC_1+128
MOVB A12,@STATIC_1+136
MOVB A12,@STATIC_1+144
MOVB A12,@STATIC_1+152
ADDK 15,A12
MOVB A12,@STATIC_1+160
SUBK 17,A12
MOVB A12,@STATIC_1+168
ADDK 3,A12
MOVB A12,@STATIC_1+176
MOVB A12,@STATIC_1+184
MOVB A12,@STATIC_1+192
MOVB A12,@STATIC_1+200
MOVB A12,@STATIC_1+208
SUBK 3,A12
MOVB A12,@STATIC_1+216
SUB A12,A12
MOVB A12,@STATIC_2
ADDK 1,A12
MOVB A12,@STATIC_2+8
ADD A12,A12
MOVB A12,@STATIC_2+16
MOVB A12,@STATIC_2+24
ADDK 1,A12
MOVB A12,@STATIC_2+32
EPI0_1:
MOVE *SP+,A12,1
RETS 0
.globl _main
******************************************************
* FUNCTION DEF : _main
******************************************************
_main:
MMTM SP,A3,A5,A7,A12,FP
MOVE STK,FP
ADDI 288,STK
CALLA _build_font
MOVI 1212501068,A12
MOVE A12,@0018A8000h,1
CLR A12
MOVE A12,*FP(192),1
JRUC L1
L4:
CLR A12
MOVE A12,*FP(160),1
JRUC L5
L8:
MOVE *FP(192),A7,1
SLL 8,A7
ADDI STATIC_3,A7
MOVE *FP(160),A5,1
SLL 3,A5
ADD A5,A7
CLR A5
MOVB A5,*A7
MOVE *FP(160),A7,1
ADDK 1,A7
MOVE A7,*FP(160),1
L5:
MOVE *FP(160),A7,1
CMPI 32,A7
JRLT L8
MOVE *FP(192),A5,1
ADDK 1,A5
MOVE A5,*FP(192),1
L1:
MOVE *FP(192),A7,1
CMPI 72,A7
JRLT L4
CLR A12
MOVE A12,*FP,1
JRUC L9
L12:
CLR A12
MOVE A12,*FP(32),1
JRUC L13
L16:
MOVE *FP,A7,1
SLL 3,A7
ADDI STATIC_2,A7
SETF 8,0,0
MOVE *A7,A7
MOVI 56,A12
MPYS A12,A7
ADDI STATIC_1,A7
MOVE *FP(32),A5,1
SLL 3,A5
ADD A5,A7
MOVE *A7,A7
MOVE A7,*FP(224),1
CLR A12
MOVE A12,*FP(64),1
JRUC L17
L20:
MOVK 16,A7
MOVE *FP(64),A5,1
NEG A5
SRA A5,A7
MOVE *FP(224),A5,1
AND A5,A7
JRZ L18
CLR A7
MOVE A7,*FP(128),1
JRUC L22
L25:
CLR A12
MOVE A12,*FP(96),1
JRUC L26
L29:
MOVE *FP,A7,1
MOVE A7,A5
SLL 5,A7
SLL 4,A5
ADD A7,A5
ADDK 8,A5
MOVE *FP(64),A7,1
SLL 3,A7
ADD A7,A5
MOVE *FP(96),A7,1
ADD A7,A5
MOVE A5,*FP(160),1
MOVE *FP(32),A7,1
SLL 3,A7
ADDK 8,A7
MOVE *FP(128),A5,1
ADD A5,A7
MOVE A7,*FP(192),1
SLL 8,A7
ADDI STATIC_3,A7
MOVE *FP(160),A5,1
SRA 3,A5
SLL 3,A5
ADD A5,A7
MOVE *FP(160),A5,1
MOVK 7,A12
AND A12,A5
MOVK 1,A3
SLL A5,A3
SLL 24,A3
SRL 24,A3
SETF 8,0,0
MOVE *A7,A5
OR A3,A5
MOVB A5,*A7
MOVE *FP(96),A7,1
ADDK 1,A7
MOVE A7,*FP(96),1
L26:
MOVE *FP(96),A7,1
CMPI 8,A7
JRLT L29
MOVE *FP(128),A5,1
ADDK 1,A5
MOVE A5,*FP(128),1
L22:
MOVE *FP(128),A7,1
CMPI 8,A7
JRLT L25
L18:
MOVE *FP(64),A7,1
ADDK 1,A7
MOVE A7,*FP(64),1
L17:
MOVE *FP(64),A7,1
CMPI 5,A7
JRLT L20
MOVE *FP(32),A5,1
ADDK 1,A5
MOVE A5,*FP(32),1
L13:
MOVE *FP(32),A7,1
CMPI 7,A7
JRLT L16
MOVE *FP,A5,1
ADDK 1,A5
MOVE A5,*FP,1
L9:
MOVE *FP,A7,1
CMPI 5,A7
JRLT L12
CLR A12
MOVE A12,*FP(192),1
JRUC L30
L33:
MOVE *FP(192),A7,1
ADDI 800,A7
SLL 10,A7
ADDI 67108904,A7
MOVE A7,*FP(256),1
CLR A12
MOVE A12,*FP(160),1
JRUC L34
L37:
MOVE *FP(256),A7,1
MOVE *FP(160),A5,1
SLL 3,A5
ADD A7,A5
MOVE *FP(192),A7,1
SLL 8,A7
ADDI STATIC_3,A7
MOVE *FP(160),A3,1
SLL 3,A3
ADD A3,A7
MOVB *A7,*A5
MOVE *FP(160),A7,1
ADDK 1,A7
MOVE A7,*FP(160),1
L34:
MOVE *FP(160),A7,1
CMPI 32,A7
JRLT L37
MOVE *FP(192),A5,1
ADDK 1,A5
MOVE A5,*FP(192),1
L30:
MOVE *FP(192),A7,1
CMPI 72,A7
JRLT L33
MOVI 1146048069,A12
MOVE A12,@0018A8020h,1
CLR A8
EPI0_2:
ADDI -288,STK
MMFM SP,A3,A5,A7,A12,FP
RETS 0
.end
+26
View File
@@ -0,0 +1,26 @@
; entry.asm -- process entry for the C hello world.
;
; The C runtime's boot.obj is designed for a ROM system: _c_int00 sets SP (the
; *system* stack), calls main, calls exit (which is `for(;;)`) and ends in
; `reti`. None of that fits a process made by the VT1200's create_process:
; the spin never yields, and `reti` returns from an interrupt that never
; happened (it pops a garbage PC -> illegal opcode).
;
; So we enter here instead: set the C program stack (STK = A14, FP = A13), call
; main, and `rets` back to the create_process trampoline -- the same return the
; xhello payload uses. SP (the OS's interrupt stack) is left alone.
;
; _cstack is 4096 bytes; the compiler grows the program stack upward from STK.
.text
.globl _start
.globl _main
_start:
setf 32, 0, 1
movi _cstack, a14
move a14, a13
calla _main
rets
.bss _cstack, 32768, 16 ; 32768 bits = 4096 bytes
.end
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

+103
View File
@@ -0,0 +1,103 @@
/*
* hello.c -- the VT1200's first C program.
*
* Writes the word HELLO straight into video RAM, no X11 involved:
*
* framebuffer bit 0x04000000, 256-byte row pitch on the real unit
* (the emulator uses 128; this image is linked for the real one)
* pixels 1 bpp, LSB-first within each byte
* text area black 256x72 box at x=40 y=800, white 5x7 glyphs scaled 8x
*
* The program also leaves a marker word at 0x018A8000 so the host can tell the
* C runtime reached main(): 0x48454C4C == 'HELL'.
*
* K&R C only: no prototypes, no '//', no unsigned suffixes, declarations first.
* The tables are filled in code, not by static initializers, because this image
* is entered through entry.asm and does not run boot.obj's .cinit pass.
*/
#define VRAM_BASE 0x04000000 /* bit address of the framebuffer */
#ifndef ROW_BYTES
#define ROW_BYTES 256 /* real unit: 256-byte row pitch */
#endif
#define ROW_BITS (ROW_BYTES * 8)
#define BOX_X 40 /* box left edge, pixels (1 bit per pixel) */
#define BOX_Y 800 /* box top edge, pixels */
#define BOX_W 256 /* 32 bytes */
#define BOX_H 72
#define MARKER 0x018A8000 /* free RAM, outside .text and .bss */
static unsigned char font[4][7]; /* H E L O (HELLO uses L twice) */
static unsigned char order[5];
static unsigned char box[BOX_H][BOX_W / 8];
/* 5x7 glyphs, bit 4 = leftmost pixel */
static void build_font()
{
font[0][0] = 17; font[0][1] = 17; font[0][2] = 31; font[0][3] = 17;
font[0][4] = 17; font[0][5] = 17; font[0][6] = 17; /* H */
font[1][0] = 31; font[1][1] = 16; font[1][2] = 16; font[1][3] = 30;
font[1][4] = 16; font[1][5] = 16; font[1][6] = 31; /* E */
font[2][0] = 16; font[2][1] = 16; font[2][2] = 16; font[2][3] = 16;
font[2][4] = 16; font[2][5] = 16; font[2][6] = 31; /* L */
font[3][0] = 14; font[3][1] = 17; font[3][2] = 17; font[3][3] = 17;
font[3][4] = 17; font[3][5] = 17; font[3][6] = 14; /* O */
order[0] = 0; order[1] = 1; order[2] = 2; order[3] = 2; order[4] = 3;
}
int main()
{
int c, r, gx, dx, dy, px, py;
unsigned int v;
unsigned int addr;
build_font();
/* 1. prove we are here */
*(unsigned int *)MARKER = 0x48454C4C;
/* 2. clear the box (black) */
for (py = 0; py < BOX_H; py++)
for (px = 0; px < BOX_W / 8; px++)
box[py][px] = 0;
/* 3. draw HELLO, each glyph pixel as an 8x8 block */
for (c = 0; c < 5; c++) {
for (r = 0; r < 7; r++) {
v = font[order[c]][r];
for (gx = 0; gx < 5; gx++) {
if (!(v & (16 >> gx)))
continue;
for (dy = 0; dy < 8; dy++) {
for (dx = 0; dx < 8; dx++) {
px = 8 + c * 48 + gx * 8 + dx;
py = 8 + r * 8 + dy;
box[py][px >> 3] |= 1 << (px & 7);
}
}
}
}
}
/* 4. blit the box into video RAM, one byte at a time.
*
* Pointers here are BIT addresses and pointer arithmetic scales by the
* object size, so a `char *` step is 8 bits: p + n is n bytes, not n*8.
* Address the bytes as addr + px*8 bits and cast, which is unambiguous.
*/
for (py = 0; py < BOX_H; py++) {
addr = VRAM_BASE + (BOX_Y + py) * ROW_BITS + BOX_X;
for (px = 0; px < BOX_W / 8; px++) {
*(unsigned char *)(addr + px * 8) = box[py][px];
}
}
/* 5. second marker: the blit finished */
*(unsigned int *)(MARKER + 0x20) = 0x444F4E45; /* 'DONE' */
return 0;
}