harness: level-1 VIDEO MEMORY test passes (video RAM mapped + REFCNT advances); next gate is HOST PORT

This commit is contained in:
SDD committed 2026-10-16 10:57:06 +03:00
1 parent 5ef8712960
commit 5000b8bc07
4 files changed
+71 -49

No files matched your search

+10 -2
View File
@@ -1,7 +1,15 @@
MAME debugger version 0.289 (mame0289-dirty)
Currently targeting vt1200 (VT1200 X terminal (v2.2 firmware))
Breakpoint 1 set
DISPATCH sp=00005280 w=00001580 00000000 00000001 3FDF8A20 000016B0 00001560 00000000 00000000
PRINT pc=3FDE00C0 a9=3FDCA8E8 a11=0040000C a5=00000000
DISPATCH sp=00005280 w=00001580 00000100 00000000 3FDF90E0 000016B0 00001560 00000000 00000000
PRINT pc=3FDE00C0 a9=3FDC9C68 a11=00000015 a5=00000000
PRINT pc=3FDE00C0 a9=0080000C a11=00000015 a5=00000000
PRINT pc=3FDE00C0 a9=00C0000C a11=00000015 a5=00000000
PRINT pc=3FDE00C0 a9=0100000C a11=00000015 a5=00000000
PRINT pc=3FDE00C0 a9=0200000C a11=00000015 a5=00000000
+2 -2
View File
@@ -1,9 +1,9 @@
#Ghidra Lock File
#Fri Oct 16 10:37:43 EEST 2026
#Fri Oct 16 10:54:50 EEST 2026
<META>\ Supports\ File\ Channel\ Locking=Channel Lock
Hostname=sid
OS\ Architecture=amd64
OS\ Name=Linux
OS\ Version=7.2.4-arch1-2
Timestamp=10/16/26, 10\:37\u202FAM
Timestamp=10/16/26, 10\:54\u202FAM
Username=arti
+56 -42
View File
@@ -927,49 +927,63 @@ one `0xffe0` reference in the routine, the read in the dispatcher, so the code i
locally). The failing code is therefore chosen by **whatever calls this routine** — and that
caller is what still needs finding.
## MILESTONE: the level-1 VIDEO MEMORY test now PASSES (2026-10-16)
The code-22 investigation (`harness/mame/CODE22_REPORT.md`) found exactly what the test
requires, and two changes satisfy it. **The firmware has moved on to the next level-1 test.**
### What raises code 22 (in the firmware's own terms)
```
level-1 video-memory self-test at bit 0x3F2018B0 (base 0x04000000, count 0x20000)
returns non-zero -> L3FA7C050 -> code 0x100 stored at 0x3FA7DE30
-> dispatcher 0x3FDF0630 -> the VIDEO MEMORY - 22 handler
```
Its failing condition depended on configuration, which turned out to be two separate bugs:
1. **Default driver:** the 16-bit walking-bit read-back at `0x04000000` returns 0 because
**video RAM is unmapped** -> fixed by mapping it (`VT1200_VRAM=1`, base bit `0x04000000`).
2. **With video RAM mapped:** the pattern walk then *passes*, and the failure moved to the
**REFCNT check at `0x3F201ED0`** — `0xC00001F0` returned the **same value twice**, which
the firmware treats as an error (`a8=0x0E`).
### The REFCNT fix (a local MAME core change — revert note included)
MAME modelled the refresh counter too coarsely:
```cpp
case REG_REFCNT:
return (total_cycles() / 16) & 0xfffc; // changes only every 64 cycles
```
The test reads REFCNT twice a few instructions apart and requires the value to have moved.
Changed in `/home/arti/code/k-space/mame0289/src/devices/cpu/tms34010/tms34010.cpp` to
`return total_cycles() & 0xffff;`, with the original line preserved in a comment directly
above it for reverting. **This is a local change to the emulator, not to anything DEC made** —
the ROM is untouched, and the change makes the emulator's refresh counter behave the way the
firmware is probing for.
### Result
With video RAM mapped and REFCNT advancing:
```
error-22 prints: 0 <- the video-memory test PASSES
next failure: 'LEVEL1/2 ERROR -> HOST PORT - 15 '
```
### Where it stands now
The level-1 sequence has advanced to the **HOST PORT** test — DUART1 channel A, per the
service guide's "Host port test". The DUARTs are not modelled at all, so that is the next
gate. The shape of the work is now established and repeatable: identify the test, find the
condition it fails on, model it, re-run the console capture.
---
## Next steps
1. Find the CALLER of FUN_rom_07fbd000 and the status code it passes -- that is the
failing test. Use smart34010 for call targets (Ghidra's CALLA does not resolve).
2. Optionally fix Ghidra's CALLA operand handling to get a usable call graph.
## Where the level-1 investigation stands (2026-10-16, end of this stretch)
**Not solved: level 1 still fails, no picture.**
Solid and committed (these do not need redoing):
* **Address units** — from MAME's source: the TMS34010 program space is
`memory_access<32,1,3>`, so map units are **bits** and bytes = bit >> 3; a handler on an
entry at `base` receives `(bitaddr - base) >> 4`. Precedence is plain last-wins.
* **Instruments** — the catch-all is trustworthy (closed cross-check: moving a probe to the
right address shifted exactly 183,536 accesses out of it). `VT1200_BOARD_LOG`,
`VT1200_LOG_UNMAPPED`, `VT1200_CAL`, `VT1200_VRAMLOG` all work. **Watchpoints do not work
headless**; `bpset` does.
* **Video memory** — located at bit `0x04000000` (~110 KiB first bank), mapped, and proven to
round-trip a walking-bit pattern. It is **not** the missing piece: the test still fails
with it mapped and round-tripping.
* **The level-1 video RAM test** — characterised: a walking-bit data-bus test (8,208 writes,
8,208 read-backs, 4,096 offsets).
* **Console capture** — `cap.lua`, breaking at the printer `3FDE00C0` and logging `a9`/`a11`,
gives the firmware's own self-test narration.
* **Ghidra** — project seeded and saved (25 functions) and it cross-validates `smart34010`
instruction-for-instruction. Caveat: **Ghidra's `CALLA` targets do not resolve**, so its
call graph is empty — use `smart34010` for call targets.
Withdrawn after being shown wrong: "the test fails at bit 0x040000C0" (the value came from a
stale register; the error strings are selected by a **status code**, and the numbers printed
with them are message constants, not addresses).
**The open question, stated cleanly:** which level-1 test raises status code 22 (video
memory), and what condition makes it raise it. The error dispatcher is
`FUN_rom_07fbd000` (Ghidra `0x07FBD000`-`0x07FBE201`), it takes the code as an argument, and
the stack at the dispatcher shows the **error-reporting framework**, not the test that
produced the code — so the test must be found another way.
**Suggested next approach** (not yet tried): intercept where the status code is *stored*
rather than where it is consumed — the framework keeps the code in a global, so watch the
global for transitions to 22 and take the PC there. That would land inside the failing test
directly.
1. Model the host DUART (DUART1 channel A) enough for the level-1 HOST PORT test
(bit 0x3F...); the DUARTs are unmodelled and are the current gate.
2. Keep using cap.lua to read which test fails next -- the loop is now repeatable.
+3 -3
View File
@@ -70,7 +70,7 @@ addr5: fwd is bits_5_9 & bits_10 = 0 [fwd = inst_next + (bits_5_9 * 2);] {export
addr5: bwd is bits_5_9 & bits_10 = 1 [bwd = inst_next - (bits_5_9 * 2);] {export *:4 bwd;}
addr8: addy is bits_0_7s [addy = inst_next + (bits_0_7s * 2);] {export *:4 addy;}
addr16: addy is bits_0_15s [addy = inst_next + (bits_0_15s * 2);] {export *:4 addy;}
addr32: addy is imm32 [addy = (imm32 / 8) & 0xfffff;] {export *:4 addy;}
addr32: addy is imm32 [addy = imm32 / 8;] {export *:4 addy;}
cc: "" is bits_8_11=0 { local tmp:1 = 1; export tmp; }
cc: "P" is bits_8_11=1 { local tmp:1 = (!$(N_Flag) & !$(Z_Flag)) != 0; export tmp; }
@@ -182,9 +182,9 @@ macro Update_V_Flag(V)
# -------------------------------------------------------------------------------------------------------------------------------------#
# ADDI IL Add Immediate (32-bytes) 0000 1011 001R DDDD
# -------------------------------------------------------------------------------------------------------------------------------------#
:ADDI link,Rd is bits_5_15=0b00001011001 & Rd; imm32 [link=(imm32 / 8) & 0xfffff;]
:ADDI imm32,Rd is bits_5_15=0b00001011001 & Rd; imm32
{
Rd = link;
Rd = imm32;
}