Files
vt1200/harness/mame/GATE_CLEANUP_REPORT.md
arti 41454d5d4c harness: the stub level-1 run continues past both DUART failures; correct the "fatal/LED loop" claim
The stub run does not park at HOST PORT - 15. Both DUART failures are reported,
the board LED blinks once (finite L3F208660), TYPE 'GO' TO CONTINUE is printed
(no input is read), and the level-1 runner continues ('CONTINUING THE TESTS').
The runner never returns to 3F204440, so 3F208060/3F208650 are never executed.

The run then wedges at frame ~2839 in a DUART1 counter-ready interrupt storm:
the ISR polls DUART1 reg 5 (bit 0x06400050) and always reads 0x08; the counter
runs in timer mode (ACR=0x60) with CTUR/CTLR never programmed, so MAME re-arms
at 1 tick and the interrupt re-asserts every ~229 CPU cycles. Frames at 3500 /
6000 / 12000 are byte-identical; RAM differs by one byte.

Corrects README.md and annotates GATE_CLEANUP_REPORT.md, BRINGUP_LOG.md and
DUART_REPORT.md. Adds a console+PC/milestone instrument and the finding report.
2026-10-16 14:56:47 +03:00

7.1 KiB
Raw Permalink Blame History

VT1200_* env-gate cleanup — outcome

CORRECTION (2026-10-16, later). This report's no-env section says the run goes "up to the HOST PORT test (then the LED loop)" and calls 3F2088B0/3F208B20/3F208A80/3F208950 "the LED loop". Measured over 20 000 frames (harness/mame/LEVEL1_CONTINUE_REPORT.md), those PCs are inside the finite one-shot blink L3F208660; 3F208060/3F208650 are never executed and the run does not end there. The DUART failures are followed by CONTINUING THE TESTS and then a DUART1 counter-ready interrupt storm from frame ~2839. The baseline values below are unchanged; only the "LED loop" reading is corrected.

Executes docs/superpowers/plans/2026-10-16-env-gate-cleanup.md. The working configuration is now the default: a bare vt1200 vt1200 (no env at all) behaves exactly like the old incantation

VT1200_VRAM=1 VT1200_BOARD_MODEL=handshake VT1200_BOARD_BUSY_TICKS=2 \
VT1200_BOARD_SWITCH="0640000D:70:70" VT1200_DUART=1 VT1200_DUART_SEL=1

Only harness/mame/vt1200.cpp was changed (build.sh needed no edit). ROM untouched: md5 b46a3e442ccb86134d2356bd70d22fd2.

Promoted (gate removed, value is now the default) — 5

gate new default (code)
VT1200_VRAM map(VRAM_BASE_BITS, 0x1fffffff).ram().share("vram") unconditional
VT1200_BOARD_MODEL m_board.set_model_handshake(true)
VT1200_BOARD_BUSY_TICKS m_board.set_busy_ticks(2)
VT1200_DUART DUART1 always mapped + ip4/5/6_w(1); irq_cb always wired
VT1200_DUART_SEL folded to DUART1 only; DUART2 is a new opt-in VT1200_DUART2

Deleted (never on a default path) — 15

VT1200_CAL, VT1200_CAL_VID4M, VT1200_CAL_W8, VT1200_BOARD_RAM, VT1200_BOARD_DEFAULT, VT1200_BOARD_BUSY_W2, VT1200_BOARD_BUSY_W3, VT1200_BOARD_DMA_TICKS, VT1200_BOARD_SWITCH (superseded — see below), VT1200_DUART_LB1, VT1200_DUART_LB2, VT1200_LOWLOG, VT1200_VRAMLOG, VT1200_STRUCTLOG, and VT1200_DUART1_INT2 (folded into VT1200_SKIP_LEVEL1).

Kept — 15

Instrumentation: VT1200_BOARD_LOG, VT1200_BOARD_MAP, VT1200_DUARTLOG, VT1200_IRQLOG, VT1200_LOG_UNMAPPED, VT1200_DPYLOG + VT1200_DPYLOG_FRAMES, VT1200_DUMP_FRAME, VT1200_DUMP_RAM, VT1200_DUMP_VRAM, VT1200_DUMP_DIR, VT1200_NO_RENDER. Behaviour switches: VT1200_SKIP_LEVEL1 (renamed from VT1200_DUART_IP3), VT1200_DUART2 (new opt-in for DUART2).


Equivalence proof (the promotion)

The "with env" capture is the six-variable incantation; the "after" capture is a bare run with no environment variables at all. Same binary MAME build (/home/arti/code/k-space/mame0289/vt1200), same commands, in the same order.

observable with env (before) no env (after) match
frame 160 md5 713c3e559e8e95b85e801901c505bf60 same ✅
frame 200 md5 330a44bfa3263eb54427a8e5320d69b8 same ✅
frame 600 md5 e8c133380ca1d4d063b95a74a39e17e3 same ✅
progress.lua 200 frames 78 distinct PCs, hot PC=3FDCE400 samples=53 byte-identical file ✅
progress.lua 1500 frames 103 distinct PCs, hot PC=3F2088B0 samples=415 byte-identical file ✅
cap.lua 3000-frame console 7 PRINT lines byte-identical file ✅

Console transcript (both runs, identical):

PRINT ... a9=3FDCA8E8   "LEVEL1/2 TESTING ** "
PRINT ... a9=3FDC9C68   "LEVEL1/2 ERROR -> HOST PORT - 15 "
PRINT ... a9=0080000C / 00C0000C / 0100000C / 0200000C   (RAM diagnostic pointers)
PRINT ... a9=3FDCD2A8   "TYPE 'GO' TO CONTINUE"

diff before/progress-*.txt after/progress-*.txt and the console diff are empty. A bare vt1200 vt1200 therefore reaches exactly as far as the incantation.

The five promoted gates were all set in the "before" capture (the incantation is their conjunction), so the before/after pair covers the promoted set. Each was load-bearing in the old code — its old default was off/0, and the committed reports record the consequence of the off state: RENDER_REPORT.md §6 (VRAM off → level-1 VIDEO MEMORY fails), BRINGUP_LOG.md Gate 1/3/4 (no handshake/busy → pole at PC=3FDCE400), DUART_REPORT.md FINAL FINDINGS (no DUART → host-port transmit never runs). None was a dead promotion.

VT1200_BOARD_SWITCH is superseded (deletion proof, the one uncertain gate)

0x0640000D is the DUART1 IP register — it is inside the DUART1 mapping (VT1200_WIN3..+0xff, off 0x0D < 0x10), which is registered after the board-window model, so map precedence (last-wins) hands the read to the DUART and the board model's switch is never consulted. Measured:

  • six-var incantation with BOARD_SWITCH vs without it: frame md5s, both progress files and the console file are byte-identical (before vs before_noswitch).
  • with no env at all, the DUART1 IP read is val=00F0 (bit-7 marker + the VR150 0x70), the monitor-switch value, from every PC that reads it.

Deletion proof (all deleted gates)

Every deleted gate was read only through getenv("<VAR>") and its handler had no other caller. After deletion the file has 0 getenv("<VAR>") occurrences for each, the removed handlers (log_probe/cal*, vramlog*, lowlog*, structlog*) are gone, and the driver links — so no default path can reach removed code. VT1200_DUART_LB1/2 had no effect unless set (the firmware sets MR2 local loopback itself). The deleted probe handlers were registered only inside their own if (getenv(...)) block. git diff: +126 / −480 lines.

Re-baseline (expected, recorded)

value
old no-env baseline (200 frames) PC=3FDCE400 samples=199 (1 distinct PC — the early hardware-ready wedge)
new no-env baseline (200 frames) PC=3FDCE400 samples=53, 78 distinct PCs; at 1500 frames hot PCs are the LED loop 3F2088B0/3F208B20/3F208A80/3F208950

Reason: the no-env run is now the working configuration, so it leaves the early wedge and runs POST/level 1 up to the HOST PORT test (then the LED loop). The baseline is a change detector, not a specification; it changed deliberately.

Design points

  1. VT1200_DUART_IP3 renamed to VT1200_SKIP_LEVEL1 and it now also selects the OS-phase interrupt routing: default (level 1 runs) → POST routing (m_duart1_int2 = false, INT1); VT1200_SKIP_LEVEL1 → drives IP3 high and sets m_duart1_int2 = true (INT2, the OS's DUART1 driver). The standalone VT1200_DUART1_INT2 knob is gone. Verified live: SKIP_LEVEL1=1 gives 143 distinct PCs, OS-phase hot PCs (3FAEE280, 3FB30390, …) and no console output, i.e. it really skips level 1.
  2. The skip gate itself is not promoted: the faithful default runs level 1 (real terminal reads IP3 low); VT1200_SKIP_LEVEL1 is how we diverge.

Not changed / follow-ups

  • harness/mame/README.md still says the DUARTs are "not modelled" and lists the old mapping table — now stale. Not edited (file ownership), flagged here.
  • vt1200_board.h/.cpp still expose set_default / set_monitor_switch / set_dma_ticks / set_window_busy_ticks; now unused by the driver but left untouched (not owned by this task).