Files
vt1200/harness/mame/README.md
T

115 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# VT1200 execution harness (MAME)
A minimal MAME machine that loads the VT1200 firmware into a TMS34010 CPU so
we can **run it under MAME's debugger**: instruction trace, breakpoints,
single-stepping, and direct memory watch. It is a *visibility* tool, not an
accurate VT1200 emulation.
Everything in this directory is source-of-truth in this repo; the MAME source
tree is disposable and lives outside the project
(`/home/arti/code/k-space/mame0289`).
```
harness/mame/
├── vt1200.cpp # the MAME driver (symlinked into the MAME tree)
├── build.sh # clone-safe build wrapper
├── trace.lua # Lua: trace execution from the reset vector
├── overflow.lua # Lua: exercise the pcfReadBitmaps n*4 overflow
├── FINDINGS.md # results, evidence, and what was learned
└── roms/vt1200/ # MAME ROM dir (symlink to ../../vt1200_v22.bin)
```
## Address model (the important part)
The TMS34010 is **bit-addressed**: a register/PC holds a bit address, and a
pointer `P` refers to physical byte `P >> 3`. MAME models this with a program
space of `memory_access<32, 16, 3>`, i.e. the **address-map unit is 1 bit**
(a 16-bit word spans 16 address units). Therefore:
* Address-map entries here are **bit addresses**, not byte addresses.
* `read_word(0x3f200000)` returns ROM bytes 0..1 (physical byte 0x07e40000).
* The reset vector is read from logical bit `0xffffffe0`, which maps to the
last 4 bytes of the image (file offset `0x1bfffc`).
The driver maps:
| region | bit range | bytes |
|---|---|---|
| RAM | `0x00000000`–`0x001fffff` | 4 MiB at byte 0 |
| ROM | `0x3f200000`–`0x3fffffff` | 1.75 MiB at byte 0x07e40000 |
| ROM aliases | `0x7f…`, `0xbf…`, `0xff200000`–`0xffffffff` | same ROM (top 2 logical bits not decoded) |
The `0xff…` alias is what makes the reset-vector page resolve. Board
peripherals (LANCE Ethernet, DUARTs) are **not** modelled; their reads return
`0xffff` and writes are dropped. The terminal will therefore not boot to the
X server — that is expected and not the goal.
## Build
MAME source is required. A shallow 0.289 checkout is large and slow to fetch.
```sh
git clone --depth 1 --branch mame0289 \
https://github.com/mamedev/mame.git /home/arti/code/k-space/mame0289
harness/mame/build.sh # symlinks the driver in and runs make
```
`build.sh` runs `make -j$JOBS SUBTARGET=vt1200
SOURCES=src/mame/dec/vt1200.cpp`, which builds a single-driver binary
`/home/arti/code/k-space/mame0289/vt1200`.
The MAME tree is large and the build is **memory-hungry**: `build.sh`
defaults to **`-j8`**, not all cores. Override with `JOBS=4
harness/mame/build.sh` on a small/low-memory machine. Progress is written to
`harness/mame/build.log`.
## Run
Headless execution and inspection use MAME's Lua debugger API from
`-autoboot_script`. (`-debugscript` only works when a debugger UI drives the
console, so it is not usable headless.)
```sh
cd /home/arti/code/k-space/vt1200
M=/home/arti/code/k-space/mame0289/vt1200
# trace execution from the reset vector
$M vt1200 -rompath harness/mame/roms -video none -sound none -nothrottle \
-debug -debugger none \
-autoboot_script harness/mame/trace.lua -autoboot_delay 0
# demonstrate the pcfReadBitmaps n*4 overflow (OVF_N overrides n, decimal)
$M vt1200 -rompath harness/mame/roms -video none -sound none -nothrottle \
-debug -debugger none -debuglog -seconds_to_run 5 \
-autoboot_script harness/mame/overflow.lua -autoboot_delay 0
```
The Lua API exposes `manager.machine.debugger`, `device.debug` (step, go,
bpset, wpset), CPU registers (`cpu.state['A0'].value`), memory
(`cpu.spaces['program']:read_u32/write_u32`), and frame hooks.
### Trace from the reset vector (`trace.lua`)
Prints the reset PC (expect `3F200040`), disassembles the power-on code to
`reset.dasm`, and writes an instruction trace of the first two frames to
`vt1200-reset.trace`.
### Exercise the `pcfReadBitmaps` overflow (`overflow.lua`)
Instead of booting the parser we jump directly into its arithmetic block with
a crafted in-memory `PCF_CharInfo`:
```
a9 = 0x00040000 ; fake pCS; pCS->nChars at a9+0x270
a13 = 0x00060000 ; fake arg blk; n (from pcfReadInt32) at a13+0x20
write_u32(0x00040270, 0) ; nChars == 0
write_u32(0x00060020, n) ; n
pc = 3f984e70
break at 3f985060 ; just after 'sll 0x2,a11'
```
This is possible because the font parser's field moves use **field 1**, which
`SETF 0,0,1` leaves at 32 bits, so `n` is a full 32-bit `pcfReadInt32` value.
See `FINDINGS.md` for results and the rest of the analysis.