Download the SCN2681 (Philips 1995), SCC2681, SCN68681 and MC68HC681 UM
datasheets into reference/duart-datasheet/ with pdftotext extractions, and
audit each claimed justification against them:
Claim 1 (TxRDY asserted in tra_complete, not tra_callback): REFUTED.
The quoted p.7 sentence is real, but SCN2681 p.22 says explicitly
'TxRDY sets at the end of the start bit time' -- which is exactly the
removed upstream behaviour. Upstream was right.
Claim 2 (overrun latched on the start bit, not completion): CONFIRMED.
'the overrun error status bit (SR[4]) will be set upon receipt of the
start bit of the new (overrunning) character' (p.8, also SRA[4] p.14).
Caveats: p.8 also says errors are 'strobed ... at the received
character boundary' (internal tension); and a valid start bit is
validated ~half a bit after the falling edge, not at it.
Claim 3 (3-deep FIFO, 4th held, overrun on 5th; MAME faithful): CONFIRMED.
'capacity of three characters' + 4th held in the shift register (p.8);
MAME's SIZE+1 guard overruns exactly on the 5th.
Also snapshot the worker's uncommitted MAME diff and upstream 0.289 code.
Root cause of the missing THRA write (HOST PORT test): the level-1 host-port
test's transmit is ISR-driven, and the DUART interrupt was never wired to the
CPU. The firmware installs RAM trampolines in the fixed vector table (INT1
vector 0xffffffc0 -> stub at bit 0x0f60 = JA 0x3FA92F40, which calls the DUART
ISR L3FA78D90 with (2, 0x270860, 0x6400000)). Counters: INTENB reaches 0x0006
(INT1|INT2) at the test, so interrupts are enabled.
vt1200.cpp: wire m_duart1/m_duart2 irq_cb() to CPU external interrupt 1/2
(duart1_irq_w/duart2_irq_w), gated on VT1200_DUART. Result: THRA writes go
from 0 to 20 per run; the test's SRA-overrun and RHRA-pattern checks now pass.
MAME tree (mc68681.cpp/.h), two datasheet-backed corrections with revert notes:
1. TxRDY was asserted mid-character ("not until the end of start bit time");
the datasheet asserts it at the THR->TSR transfer. Corrected.
2. The overrun error was latched when the overrunning character *completed*
(rx_fifo_push); the datasheet latches it "upon receipt of the start bit of
the new (overrunning) character". Corrected via duart_channel::rx_w().
This clears every check in the RXCHECK sub-test (flags 1 -> 0).
Acceptance is NOT met: cap.lua still prints 'LEVEL1/2 ERROR -> HOST PORT - 15'.
The next failure is the preceding L3FA71BC0 (DUART baud/timer) sub-test
returning 6; its flag-set sites were breakpointed and never fired. Regression
holds (no VT1200_* env -> PC=3FDCE400 samples=199). Details, numbers and the
datasheet audit: harness/mame/DUART_REPORT.md sections FINAL FINDINGS / UPDATE.
Adds SCN2681 devices at 0x0640000 (DUART1 = host/printer) and 0x0620000
(DUART2 = keyboard/mouse), gated on VT1200_DUART, with the remap
verified as duart_register = handler_off (duart_byte = off*2, value in
the low byte of the firmware's 16-bit move). Optional external TX->RX
loopback (VT1200_DUART_LB1/2) models the loopback connectors; the
monitor switch is driven on IP4-IP6. New VT1200_DUARTLOG gives a full
non-deduplicated DUART access log.
Result: the level-1 HOST PORT test is reached and executed against the
real DUART, but still reports 'LEVEL1/2 ERROR -> HOST PORT - 15'. The
test reads SRA/RHRA and requires a 5-byte external pattern
(0xAA,0xFF,0xAA,0x55) plus SRA overrun, yet the firmware never writes
the transmit register (0 writes to reg 3/B on either DUART in 1400
frames), so no internal or external loopback can supply it. See
harness/mame/DUART_REPORT.md.
Regression holds: no VT1200_* env -> PC=3FDCE400 samples=199.
The dispatch status is 0x100 (printed as '22' in the message). A driver-side
transparent low-RAM write log (VT1200_LOWLOG) shows the slot at bit 0x16F0 is
written by the store at 3FDF9090 from a13(0x10), which L3FA7C050 sets to the
literal 0x100 when the memory test L3F2018B0 returns non-zero. L3F2018B0 is the
level-1 video-memory test (base bit 0x04000000, count 0x20000). Its failing
checks: the 16-bit walking-bit read-back at 0x04000000 (baseline, unmapped) and,
with video RAM mapped, the REFCNT (0xC00001F0) 'must change' check.
Closed cross-check (single run): the catch-all and VT1200_CAL proxies are
directly comparable (both base 0) and resolve identically; last-wins holds
for same- and mismatched-width overlaps. The apparent conflict was a units
error: a .rw(FUNC(offs_t)) handler receives (bitaddr-base)>>4 (tms34010
Width=1, AddrShift=3), so the catch-all logs bitaddr>>4. Its 0x400000..0x40D7FF
is bit 0x04000000..0x040D7FF0 (bytes 0x800000..0x81AFFE), outside the declared
4 MiB RAM -- genuinely unmapped. The old 0x00400000 proxy was 16x too low.
Catch-all reproduces the committed log byte-for-byte and does not perturb
coverage (56 / PC=3F208950 with and without). Regression holds: PC=3FDCE400
samples=199. Report: harness/mame/XCROSS_REPORT.md