Commit Graph
90 Commits
Author SHA1 Message Date
SDD 1051bf2940 patches: MAME is now pushed as a full repo (branch vt1200-local) -- correct the README, which said it was not, and say why the patch is still kept 2026-10-16 17:50:58 +03:00
SDD 1561e34967 patches: capture the MAME local edits as a 50-line patch (the MAME remote rejects shallow updates, so a mirror would cost GBs for a 50-line diff) 2026-10-16 17:42:13 +03:00
SDD 264d5330ad harness/serve.py: optional BOOTP responder (--bootp) so the VT1200 gets an IP at boot
The terminal broadcasts an RFC 951 BOOTP request at power-up. Add an opt-in
responder that answers it with yiaddr 192.168.99.2 and siaddr 192.168.99.1,
echoing htype/hlen/xid/chaddr. It offers no boot file: the request's sname and
file are empty, so the reply's are too.

Off by default -- a bare 'serve.py 192.168.99.1' behaves exactly as before
(TFTP on port 69, nothing else). Enable with --bootp.

Delivery note: the host IP stack never receives the source-0.0.0.0 broadcast,
so the responder attaches to the MAME tap's L2 (AF_PACKET) and writes the reply
frame back. See harness/BOOTP_REPORT.md for the evidence and the still-open
'User settings invalid' / 'Disk full' symptoms.
2026-10-16 17:27:00 +03:00
arti d4a3ccc42c harness: model the battery-backed NVR at bit 0x6000000
The terminal's settings NVR was not modelled: 0x6000000 fell inside the
video-memory mapping (0x04000000..0x1fffffff), so NVR reads returned stale
framebuffer words and writes were lost.  That is the owner's 'User settings
invalid' plus 'settings do not persist' (and the font path is stored here).
Map a persisted NVRAM over the 0x800-word settings block; MAME now saves and
reloads it (nvram/vt1200/nvram), verified write->restart->read.  No MAME-tree
change.
2026-10-16 17:25:04 +03:00
arti b6da987aae harness: dump the LANCE DMA; the C - LANCE TEST's failing frame carries no FCS by design
The failing loopback case is a negative test: its TX buffer deliberately has
no FCS, and the test expects a CRC error.  The DTCR=1 case that does carry an
FCS is delivered intact and passes, so the DMA is not dropping four bytes.
The sole remaining mismatch is one bit: the test wants RMD1=0x6B00
(ERR|FRAM|CRC|STP|ENP) and MAME's am79c90 reports 0x4B00 -- it never sets
RMD1_FRAM.  No MAME-tree change made; reported for a second reader.
2026-10-16 17:12:02 +03:00
SDD 5ed4048720 gitignore: ignore root RAM dumps (ROM stays tracked) and the Ghidra transient lock; untrack the lock file 2026-10-16 17:11:29 +03:00
SDD f05200e44e gitignore: cover test frame dumps written into the project root, not just harness/mame/ 2026-10-16 17:11:01 +03:00
SDD 82ab65bc82 run.sh: document ScrollLock (UI_TOGGLE_UI) as the fix when MAME's menu stops responding, and that closing the window is a clean exit 2026-10-16 17:01:04 +03:00
SDD 14f78f3cbe plan: the network provider must be selected per device (interface=-1 is none); index 0 = taptun on this build; NVRAM must not be isolated 2026-10-16 16:56:24 +03:00
SDD b65d9ef670 run.sh net: the per-device interface selection must PERSIST (an empty cfg dir produces no tap); -networkprovider alone does not choose one 2026-10-16 16:54:08 +03:00
SDD b356553825 run.sh net: use a private cfg directory -- a saved per-device interface=-1 silently overrides -networkprovider and no tap is ever opened 2026-10-16 16:53:14 +03:00
SDD a0d752062f run.sh: add a net mode (skip + tablet + networkprovider taptun) for the crash-work configuration 2026-10-16 16:48:40 +03:00
SDD 7612fcbda9 reference: LANCE loopback-FCS datasheet evidence (MAME condition is right)
Add the Am7990 Technical Manual and Am79C90 datasheet to
reference/lance-datasheet/ and a report, reference/lance-loopback-fcs.md,
that answers whether MAME's am79c90 receive() FCS condition
(!(MODE_LOOP) || MODE_DTCR) is inverted.

Verdict: MAME is right. The CRC generator and checker share one circuit,
so with LOOP=1 the receiver can only check the FCS when DTCR=1 -- exactly
what MAME does. The proposed inversion would be wrong in both loopback
cases. No MAME change made.
2026-10-16 16:46:47 +03:00
SDD 60b0b02e3c run.sh+README: fix the stale tablet comment; amend rule 2 with the orchestrator's own collision (uncommitted edits get swept too) 2026-10-16 16:41:16 +03:00
SDD d1be7da1f1 run.sh: replace the now-redundant tablet mode with a faithful mouse mode (tablet is the default) 2026-10-16 16:40:52 +03:00
SDD 634246ecb1 harness: LANCE Ethernet -- register file, 8-byte address ROM, INT1 and byte<->bit DMA
Milestone 1 of docs/superpowers/plans/2026-10-16-lance-ethernet.md.

Modelled:
  * MAME am79c90 (AM79C90) at the firmware's two windows -- bit 0x5900000 is
    RAP, 0x5800000 is RDP; every other offset in those windows still falls
    through to the board model.
  * the Ethernet address ROM at bit 0x6800000, as EIGHT bytes.  The plan said
    six; the firmware's reader (0x3FDD7520) actually loops i = 0..7 and then
    validates a folded ones-complement checksum over bytes 0..5 against
    bytes 6..7 (0x3FDD78B0).  For the MAC 08:00:2b:16:4b:5a that is 0xC186, so
    the ROM is 08 00 2b 16 4b 5a c1 86.  A six-byte ROM returns expected = 0
    and fails LEVEL1/2 ERROR -> ETHERNET ROM CHECKSUM - 23.  The checksum
    bytes are derived from the firmware's own algorithm (documented in
    LANCE_REPORT.md); they are not read off a real PROM.
  * the interrupt on INT1, matching the ISR 0x3FA93400 and INTENB bit 1.
  * bus-master DMA, translating the LANCE's byte address to the TMS34010's
    bit-addressed main RAM (byte B -> word B>>1), cross-checked against the
    firmware's own CSR1 = 0xFF60 = RAM word 0x7FB0.
  * VT1200_LANCELOG to trace the register/ROM accesses.

Observed with the firmware's own diagnostics menu (driven by the real LK401
model; new menu_keys.lua): the M -- ETHERNET ROM TEST now PASSES.  The
C -- LANCE TEST runs the chip for real -- the firmware's init block
(mode 0x004C = LOOP|INTL|DTCR, PADR 08:00:2b:16:4b:5a) is read via the new DMA,
INIT completes (CSR0 = 0x6FE3, IDON), the chip transmits and receives -- but its
internal-loopback receive still reports a CRC error under MAME (RCV descriptor
1 = 0x4B00, message count 0).  Cause: MAME's receive() runs the FCS check when
MODE_LOOP && MODE_DTCR (am79c90.cpp:263) even though DTCR means no FCS was
appended.  No MAME change was made; quoted and reported in LANCE_REPORT.md.

The OS (skip gate) reads the ROM MAC, programs CSR1/2/3, INITs, sees IDON,
STRTs and polls CSR0; the Terminal Manager now shows Ethernet Address
08-00-2B-16-4B-5A (was 00-00-00-00-00-00) and LAT_08002B164B5A.

Baselines unchanged: no-env samples=198 (3 PCs), VT1200_IO_PATH_STUB samples=53
(75 PCs).  ROM md5 unchanged.  No MAME tree changes.
2026-10-16 16:39:21 +03:00
SDD 7bf195e615 reference: commit skip_frame3000.png (the X11 weave, cited as evidence in the README); ignore worker scratch 2026-10-16 16:23:15 +03:00
SDD 97dbea7fed reference: commit the real-boot frame evidence (33MB) with a NOTES.md; gitignore the 201MB source recording 2026-10-16 16:22:59 +03:00
SDD f46363b473 AGENTS.md: symlink to harness/mame/README.md so agent harnesses auto-read the working conventions (single source, no drift) 2026-10-16 16:20:37 +03:00
SDD 6d8097360c harness: the VSXXX-AB tablet is the default pointing device; VT1200_MOUSE=1 forces the faithful mouse back
The tablet was opt-in (VT1200_TABLET=1) with the mouse as the default.  Invert
it: the tablet is selected with no environment, and VT1200_MOUSE=1 (a
value-aware inverse switch, so VT1200_MOUSE=0 selects the tablet) restores the
VSXXX-AA mouse.

The real terminal almost certainly has a mouse, so this is a DELIBERATE
divergence from the target machine, documented in README.md alongside
VT1200_SKIP_LEVEL1 and VT1200_IO_PATH_STUB.  It is on by default because the OS
is only reachable through the skip gate and there the tablet's absolute reports
are what make the Terminal Manager usable.

Baselines re-measured, both unchanged:
  * no-env progress.lua at 200 frames: PC=3FDCE400 samples=198 (3 PCs) -> same.
    DUART2-B is never addressed in that window (the T/R exchange is OS-phase
    only), so the reply bytes A0 04 00 00 vs A0 02 00 00 and the 5- vs 3-byte
    framing do not reach the CPU.
  * VT1200_SKIP_LEVEL1=1 frame 3000: pixel-identical for tablet and
    VT1200_MOUSE=1 (magick AE=0); both reproduce the committed
    tablet_cursor_*.png frames exactly.

VT1200_TABLET is now a no-op; run.sh's tablet mode is reported to the owner for
rewording (its comments are his).
2026-10-16 16:19:46 +03:00
SDD 7f0b2ff27c plan: record host-side tap/bridge plumbing for the LANCE network milestone (MAME's tap is tap-mess-<uid>-0, not tap0) 2026-10-16 16:17:43 +03:00
SDD 0e2d7d9d0d docs: PROTOCOL.md tablet coordinate range (0..2199) and the device-code discriminator, confirmed against the running OS 2026-10-16 16:10:11 +03:00
SDD 942a45800b run.sh: tablet mode (skip + VSXXX-AB absolute pointing); lightgun options in COMMON, verified inert by frame-md5 A/B 2026-10-16 16:09:51 +03:00
arti 065f946e2f harness: VSXXX-AB tablet on DUART2, driven by the absolute host pointer
The terminal tells the two pointing devices apart from the 'T' self-test
device code (0010 mouse / 0100 tablet) and switches report framing on it:
3-byte relative for the mouse, 5-byte absolute (header 110) for the tablet.
Verified against the running OS: with the tablet it reads the self-test as
A0 04 00 00 and then reads RHRB in groups of 5 (groups of 3 for the mouse).

Refactor the VSXXX model into a shared base + mouse/tablet subclasses and
select the device on DUART2-B with VT1200_TABLET=1 (default: the mouse, so
the mouse stays and is selectable, not replaced).  The tablet reports its
documented 0..2199 active area (VCB02 D.1) and reads the host pointer
through IPT_LIGHTGUN_X/Y, MAME's absolute control, so the emulated cursor
follows the host pointer positionally: corner (0,0) -> (194,38), centre
(1100,1100) -> (704,467), corner (2199,2199) -> (1214,898), reproducible
pixel-for-pixel on a repeated coordinate.  Driving it from the host mouse
needs '-lightgun -lightgun_device mouse' (documented for run.sh; run.sh is
not edited here).

The mouse and keyboard are unchanged, and all baselines hold: no env
PC=3FDCE400 samples=198 (3 PCs); VT1200_IO_PATH_STUB=1 samples=53 (75 PCs);
ROM md5 unchanged.  Nothing is tuned to satisfy level 0's I/O data path test.
2026-10-16 16:07:36 +03:00
arti 02acabb7ef harness: real LK401 keyboard + VSXXX-AA mouse devices on DUART2
Add the terminal's actual input parts to the harness as device models on the
already-modelled SCN2681 at DUART2: a DEC LK401 keyboard (channel A, 4800 8N1)
and a DEC VSXXX-AA mouse (channel B, 4800 8O1), both driven by MAME's host
input and wired bit-by-bit to the DUART (rx_a_w/rx_b_w and a_tx_cb/b_tx_cb).

Route: the docs, not MAME's lk201. MAME's lk201 device executes the 68HC05
firmware 23-001s9-00.bin, which is not in our ROM set (the downloaded zip only
carries the 8051 23-004M2-00.bin, MAME's unused second region), so route 1 is
unusable without sourcing that ROM. The models follow PROTOCOL.md: the keyboard
answers FD with the 4-byte self-test and reports documented keycodes honouring
the division modes; the mouse answers T with its 4-byte self-test and streams
3-byte incremental reports.

One physical-layer detail was required: the SCN2681 receiver mis-samples the
first byte after a receiver reset unless the line is explicitly idle-high
before the start bit. Both models now hold TxD at mark when idle (which is
faithful anyway) -- isolated evidence: bit-banging 0x55 into rx_a_w gives
RHRA=D5 with no idle-high, RHRA=55 with four idle-high bits.

Verified (VT1200_SKIP_LEVEL1=1, input_inject.lua): the OS reads the keyboard
keycode 0xC2 (A) and ~900 bytes of VSXXX reports (dx=+16/+32); after the
self-test it switches the mouse to stream mode; the X11 cursor arrow is visible
at frame 4400 and has moved by frame 4600.

Nothing was tuned for the level-0 I/O data-path test: with no env the boot
still fails it honestly and the regression baseline is unchanged
(PC=3FDCE400 samples=198, 3 PCs). VT1200_IO_PATH_STUB=1 (53/75) and the skip
run (Terminal Manager at frame 3000) are also unchanged. ROM md5 unchanged.

See harness/mame/INPUT_REPORT.md.
2026-10-16 15:33:30 +03:00
SDD 7e65692b54 reference: DUART counter/timer period when CTUR/CTLR unprogrammed -- datasheet does not settle it 2026-10-16 15:00:20 +03:00
SDD a6b6ae82ef docs: correct Q4 of the level-1 bypass analysis -- a level-1 failure is NOT fatal (superseded answer kept as record) 2026-10-16 14:57:54 +03:00
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
SDD 7296a86034 run.sh: add the stub mode and document VT1200_IO_PATH_STUB as a non-faithful opt-in 2026-10-16 14:32:07 +03:00
SDD f7caf9aed8 harness: opt-in VT1200_IO_PATH_STUB stand-in for the level-0 keyboard-port test fixture
The level-0 I/O data path test writes one 0xE1 byte to DUART2-A THRA and
demands exactly 10 bytes back; it checks only the count and never compares
the content, and no documented keyboard/mouse/tablet message is 10 bytes.
Add an opt-in stand-in that watches for that 0xE1 write and feeds 10
arbitrary (0x00) bytes on the channel's receive path via the SCN2681's
public rx_fifo_push(), refilling the 4-deep FIFO on each RHRA read.

This is explicitly NOT a keyboard model: it stands in for an unknown test
fixture on the keyboard port. It replies only while the channel is polled
(IMR=0x00), so it raises no interrupt; with the stub on the run clears
level 0 and reaches level 1's HOST PORT - 15, but still no OS (SKIP_LEVEL1
remains the only route to X11). Default is unchanged: no env still fails
level 0 honestly (progress.lua samples=198/3 PCs); stub-on is 53/75 PCs.
See harness/mame/README.md.
2026-10-16 14:31:20 +03:00
SDD 215fd573db docs: level-0 I/O test is not honestly satisfiable by any documented device; record why and the only honest route to close it 2026-10-16 14:17:10 +03:00
SDD a1e3ebfaff reference: the level-0 10-byte puzzle -- count-only, no loopback, no 10-byte device message 2026-10-16 14:16:37 +03:00
SDD d017953d52 docs: plan the LANCE Ethernet model + network font delivery
Evidence for the RAP/RDP window pair (0x5900000/0x5800000), INT1 as the LANCE
interrupt, and the separate MAC address ROM at 0x6800000; MAME am79c90 drop-in
assessment with the kn01/ncd68k templates; the TFTP/LAT font delivery path
(no X font server on 7100); acceptance, risks and sequencing.
2026-10-16 14:16:05 +03:00
SDD 47dac6b283 docs: DUART2 modelled; Terminal Manager reached; the bare run's old level-1 pass was a latch artefact (honest failure now) 2026-10-16 14:00:23 +03:00
SDD 1ca4817745 harness: model DUART2 by default (drop the VT1200_DUART2 gate)
The real VT1200 board has a DUART2 (SCN2681) at 0x0620000 for the keyboard
(ch A) and mouse (ch B) with INT2 wired.  Map it unconditionally instead of
opting in via VT1200_DUART2; the OS's DUART interrupt dispatcher needs a real
read-only ISR distinct from the write-only IMR.

Verified with frame dumps: with ONLY VT1200_SKIP_LEVEL1=1 the Terminal Manager
V2.2 dialog now appears (frame 3000; VRAM md5 73c3c9a1..., identical to the old
skip+DUART2 run).

This does NOT keep the faithful no-env path: level 0's I/O data path test
(L3FDCE470) transmits 0xE1 to DUART2-A and drains the receiver until it has read
10 bytes (SRA RxRDY).  The board write-back latch used to alias CSRA/RHRA and
faked that (baseline first divergence: R 06200001 pc=3FDCE670 = 0x0099 vs the
real chip's 0x000C), so the firmware dropped into the interactive diagnostics
menu.  No faithful device we have (LK401 sends at most 4 bytes) supplies the 10
bytes; an external TX->RX loopback does not change the transmit count.  See
OS_BRINGUP_REPORT.md section 8 (DONE_WITH_CONCERNS).

The OS keyboard/mouse driver does initialise: skip-phase OS code programs
DUART2 (MR1A=0x13, CSRA=0x99, IMR=0x33, ...) and sends FD to the keyboard plus
the documented LED/click/bell/auto-repeat commands, and 'T' to the mouse.
2026-10-16 13:59:09 +03:00
SDD 6ce84b86f2 run.sh: skip mode also models DUART2 -- required for the OS (phantom ISR read at 0x06200005); reaches the Terminal Manager 2026-10-16 13:40:21 +03:00
SDD c06cf7096b harness: skip run is STUCK at the X11 weave -- wall is unmodelled DUART2 (phantom ISR read at 0x06200005); add multi-timestamp dumps + console string resolver
The skip gate reaches the root weave and stops: video RAM and the rendered
frame are byte-identical at frames 3000/10000/30000/45000/60000 (42 s -> 14
min), and all 4 MiB of main RAM is identical at every sample except one byte
that oscillates.  The PC histogram is tight: entered at frame ~611, dominated
by 0x3FB30390/0x3FB30110.

Wall: DUART2 (0x0620000, keyboard/mouse) is unmodelled, so the read-only ISR
at 0x06200005 is served by the board write-back latch and returns the value
the OS wrote to the write-only IMR (0x0033).  The OS's DUART dispatcher
(0x3FB43800) masks 0x66 -> 0x22, so it services a phantom interrupt that can
never clear, spinning in the channel handler 0x3FB42410 and queue routine
0x3FB300F0.  Forcing only 0x06200005 to 0 reproduces the full DUART2-mapped
run byte-for-byte; with VT1200_DUART2=1 the Terminal Manager dialog box from
the reference video appears at frame 3000 and the machine runs on.

Defaults unchanged: no-env still reaches HOST PORT - 15, skip still reaches
the weave.  New opt-in knobs VT1200_DUMP_{FRAME,RAM_FRAMES,VRAM_FRAMES} and
resolve_console.py; progress.lua untouched.
2026-10-16 13:39:37 +03:00
SDD 855f3e85e9 docs: the OS DOES paint -- skip run boots to a running X11 server (root weave confirmed in a frame dump); correct the claim I wrote 2026-10-16 13:26:27 +03:00
SDD b99b7de62e harness: add run.sh launcher (faithful/skip/pie/headless modes, verified end to end) 2026-10-16 13:21:51 +03:00
SDD c3faa7729d docs: correct stale README - DUARTs/VRAM are modelled, fix memory_access template args, add gate list and new baseline 2026-10-16 13:19:25 +03:00
SDD 5abf4f33be harness: promote the working VT1200 config to the default; retire settled env gates
A bare 'vt1200 vt1200' now boots exactly as the old six-variable incantation
(VRAM, handshake busy=2, DUART1, monitor switch) did, so the no-env run is no
longer a silently-broken machine.

Promoted (5): VT1200_VRAM, VT1200_BOARD_MODEL, VT1200_BOARD_BUSY_TICKS,
VT1200_DUART, VT1200_DUART_SEL (folded to DUART1-only; DUART2 is the new
opt-in VT1200_DUART2).

Deleted (15): VT1200_CAL/_VID4M/_W8, VT1200_BOARD_RAM/_DEFAULT/_BUSY_W2/
_BUSY_W3/_DMA_TICKS/_SWITCH, VT1200_DUART_LB1/LB2, VT1200_LOWLOG,
VT1200_VRAMLOG, VT1200_STRUCTLOG, VT1200_DUART1_INT2.
VT1200_BOARD_SWITCH is superseded: 0x0640000D is the DUART1 IP register, and
the DUART mapping wins the last-wins slice, so the board model switch was
never consulted (verified: identical output with and without it).

Renamed: VT1200_DUART_IP3 -> VT1200_SKIP_LEVEL1, which now also selects the
OS-phase DUART1 IRQ routing (INT2) instead of POST's INT1, removing the
standalone VT1200_DUART1_INT2 knob. The skip gate itself stays opt-in.

Evidence (equivalence): frame-160/200/600 md5, progress.lua at 200/1500
frames, and the cap.lua console transcript from the no-env run are
byte-identical to the incantation run. Re-baseline: no-env 200-frame hottest
PC 3FDCE400 samples 199 (1 PC) -> samples 53 (78 PCs). ROM md5 unchanged
b46a3e442ccb86134d2356bd70d22fd2. Header comment block updated; see
harness/mame/GATE_CLEANUP_REPORT.md.
2026-10-16 13:18:14 +03:00
SDD 9d912ae084 harness: l1patch.lua -- runtime level-1 host-port patch + test-map probe
Runtime region-writes (on-disk ROM untouched) applied after the level-0 ROM
checksum:
  three known failing checks: 3FA73980 CA04->C004, 3FA76060 CB04->C004,
    3FA760F0 CB04->C004 (skip the c6/c0/c1 flag stores)
  VT1200_L1PATCH_EXTRA adds the second-round checks 3FA761F0 / 3FA763A0
    (the retry loop reaches c3/c2 once c0/c1 stop short-circuiting)
  VT1200_L1PATCH_VERDICT optionally forces L3FA6E4B0's return (3FA71B60
    4D28 move a9,a8 -> 5708 clr a8)

With the five branch patches the HOST PORT test's caller returns 0 and no
'HOST PORT - 15' is printed, but level 1 does not complete: the CPU stays in
the DUART ISR chain (INT1 0x0F60 -> 3FA92F40 -> L3FA78D90 -> 3FA78xxx-3FA7Bxxx)
for >19000 frames with no error.  l1p_pie_frame1500.png is a frame dump of the
self-test circle/pie -- the renderer draws curves, fills and blits correctly.
2026-10-16 13:09:45 +03:00
SDD 55cf122edd docs: correct the stale 256 KiB RAM claim in BRINGUP_LOG
The '256 KiB / driver only models 256 KiB of main RAM' note was from an early
dump and is wrong.  The driver maps 0x00000000-0x01ffffff, which on this
bit-addressed space is 0x2000000 units = 0x400000 bytes = 4 MiB, confirmed
empirically (mainram share size == 4194304).  Keep the correction with the
original so the stale figure cannot mislead again.
2026-10-16 13:09:37 +03:00
SDD db535c2adc harness: explicit monochrome palette (pen 0 black, pen 1 white)
vt1200.cpp declared PALETTE(config, m_palette).set_entries(256) with no init
delegate, so render_active_line()'s pens 0/1 rendered in whatever MAME's
default palette held -- reported as red on screen.  Use
palette_device::MONOCHROME (emupal.cpp: palette_init_monochrome) with two
entries, so the colour is ours and deterministic.

Verified via a real MAME screenshot (screen:snapshot(), which renders through
the palette -- dump_frame()'s PPM is straight from bitmap pens and cannot show
colour): pal_mono_frame600.png is exactly black (0,0,0) + white (255,255,255).
palverify.lua takes the screenshot; the frame is the level-1 error screen.
2026-10-16 13:02:50 +03:00
SDD ac60ad2f89 docs: plan to retire the settled VT1200_* env gates (promote working config to default, delete finished experiments) 2026-10-16 13:02:20 +03:00
SDD 6cbb362bb9 harness: VT1200_DUART1_INT2 -- route DUART1's IRQ to INT2 (A/B knob)
The OS's DUART1 driver services the 0x6400000 window from the INT2 stub
(0x0F30 -> 0x3FA93070); with the default INT1 wiring the DUART1 TxRDY IRQ is
handed to the INT1 stub's 0x5800000 board-DMA handler (0x3F7151F0 ->
0x3F9D5B40), which never reads the DUART ISR, so INTPEND's INT1 bit stays
latched and the CPU re-enters the handler ~387x per frame.

Empirical A/B (level-1-skipped boot via VT1200_DUART_IP3):
  default (INT1): INT1 stub entered 387x in one frame; screen frozen.
  VT1200_DUART1_INT2=1: zero interrupt entries in a one-frame trace;
    the OS reads DUART1 ISR (reg5) at pc=3FB43900 right after the IRQ.
INTENB reads 0x0606 (INT1|INT2|HI|DI), so the routing (not the enable mask)
is what identifies the line.  Opt-in; default unchanged.

osprobe.lua: also print INTENB and DUART1 MR1A/CSRA in the globals dump.
2026-10-16 13:01:40 +03:00
SDD c19c603d77 harness: VT1200_DUART_IP3 -- drive DUART1 IP3 high to take the OS cold-start gate
Add an opt-in knob (VT1200_DUART_IP3=1) that asserts DUART1 input-port bit 3.
The POST gate at bit 0x3F2042D0 tests IP3 (@0x64000D0 bit 3) and, when it is
high and the 0x6200000 status handshake did not return 0x55, branches to the
OS cold-start 0x3F5788C0 (jauc), skipping the whole level-1 batch: the sole
caller of the level-1 runner 0x3FDF72D0 is 0x3F204400, inside the skipped
region.  Verified from the raw opcodes against MAME's tms34010 opcode table
(BTST_K sets Z=NOT bit; jane=JNE absolute-long) and empirically.

Default behaviour is unchanged (no env -> the gate is not taken).  The real
terminal reads IP3 low, so this is a modelled board input, not a faithful POST
path; results from a level-1-skipped harness are not evidence about the real
hardware's POST, but are evidence about the OS/graphics route.

osprobe.lua: gate/OS/Park probe (breakpoints on 0x3F2043B0 / 0x3F204400 /
0x3F5788C0, per-frame PC histogram, optional instruction trace and RAM-global
dump).
2026-10-16 12:55:36 +03:00
SDD c69d2c295f reference: level-1 host-port test — can it be skipped? (analysis, no skip)
Answers the five sub-questions from the service guide, the linear dis34 dump,
the existing reports, and one empirical capture:

* level 1 runs unconditionally at power-up; the boot calls the level-1 runner
  at bit 0x3F204400 (calla L3FDF72D0). The only conditional at the call site is
  the DUART1 IP3 hardware input bit (firmware @0x64000D0 bit 3), not a stored
  value.
* the host-port test has no 'not installed' sense; only SIMMs (@0x5000000) and
  the Image Option (@0x62000D0 bit 5) have presence checks.
* no persistent test-selection record: the power-up test set is a hard-coded
  ROM immediate (0x10FEFD80) written into a RAM descriptor; the interactive
  menu and NCP P3 only modify a run. NVRAM is read only by the user-settings
  code, never on the level-1 path.
* a level-1 failure wedges the boot in the board-LED code loop (0x3F208060,
  jruc itself); transcript = LEVEL1/2 TESTING, HOST PORT - 15, TYPE 'GO' TO
  CONTINUE, then the LED loop.
* the one in-ROM bypass (0x3F2043B0 -> OS cold-start 0x3F5788C0) is a
  board-input gate (IP3 high + no 0x55 signature); it skips all of level 1,
  not just the host port, and is not a firmware setting.

Verdict: no persistent/configurable skip; harness must pass level 1 or assert
DUART1 IP3 (0x0640000D bit 3) to take the OS branch.

Evidence + scratch: reference/l1probe/.
2026-10-16 12:42:35 +03:00
SDD 571850e564 harness: render the TMS34010 active scanlines from video RAM
MAME's TMS34010 renderer does not read VRAM: tms340x0_ind16 calls the
driver's scanline callback for the active region and paints only the
blanking regions.  Our callback drew nothing, so the active area was
never painted and every frame dump was all-black.

Add render_active_line(), called from scanline(): it reads the
framebuffer out of the video-RAM share at bit 0x04000000 with a measured
1024-bit (0x40-word, 128-byte) row pitch and LSB-first bit order within
each 16-bit word.  The pitch comes from the firmware's own character
blitter (PIXBLT at pc=3FDF9A00 advances its destination by 0x40 words per
glyph row); at the 160-byte pitch MAME derived from HEBLNK/HSBLNK/HTOTAL
the text is sheared and unreadable.

Validated: frame 160 shows the level-1 CP437 character table legibly,
frame 600 the level-1 error screen.  VT1200_DPYLOG added as an opt-in
per-scanline display-params dump.

Regression (no VT1200_* env): PC=3FDCE400 samples=199 -- holds.

See harness/mame/RENDER_REPORT.md.
2026-10-16 12:42:33 +03:00
SDD bcbd7924af docs: last authorised timing change tested (idle-path transmit start) -- real deviation, not the cause; reverted
Mechanism quantified first, per byte over the 5-byte burst: start latency 2605, 15442,
20652, 20650, 20652 cycles -- i.e. 1 bit for the idle byte 0 only, then constant because
later characters are pinned by the previous character's end.  It does NOT accumulate.

Implemented the authorised contained change (write_TX idle path begins the start bit
immediately; new start_now parameter in emu/diserial.{h,cpp}; buffered path and receive
side untouched; SCN2681 16x-clock citations recorded).  Result: byte 0's latency 2605 -> 5
cycles, nothing else moved, and the outcome was identical -- same three failing checks,
same returns (L3FA71BC0=0x00900040, L3FA753D0=3, L3FA6E4B0=6), same console line.

DECISION: reverted.  The deviation is real but the change does not move the symptom and is
only a partial fidelity fix (a faithful model would clock the transmitter at 16x).  Keeping
a change that buys nothing adds noise.  MAME tree is back to edit 2 (overrun latch) only
plus the edit-1 refutation note; emu/diserial.{h,cpp} unmodified.

DUART_REPORT.md now carries the full handover: established / ruled out / remaining
discrepancy / open deviations.  Acceptance still fails; regression holds.
2026-10-16 12:26:01 +03:00