forked from opencode.energia.arti.ee/vt1200
harness: level-1 VIDEO MEMORY test passes (video RAM mapped + REFCNT advances); next gate is HOST PORT
This commit is contained in:
1 parent
5ef8712960
commit
5000b8bc07
4 files changed
+71
-49
No files matched your search
@@ -1,7 +1,15 @@
|
|||||||
MAME debugger version 0.289 (mame0289-dirty)
|
MAME debugger version 0.289 (mame0289-dirty)
|
||||||
Currently targeting vt1200 (VT1200 X terminal (v2.2 firmware))
|
Currently targeting vt1200 (VT1200 X terminal (v2.2 firmware))
|
||||||
Breakpoint 1 set
|
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
@@ -1,9 +1,9 @@
|
|||||||
#Ghidra Lock File
|
#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
|
<META>\ Supports\ File\ Channel\ Locking=Channel Lock
|
||||||
Hostname=sid
|
Hostname=sid
|
||||||
OS\ Architecture=amd64
|
OS\ Architecture=amd64
|
||||||
OS\ Name=Linux
|
OS\ Name=Linux
|
||||||
OS\ Version=7.2.4-arch1-2
|
OS\ Version=7.2.4-arch1-2
|
||||||
Timestamp=10/16/26, 10\:37\u202FAM
|
Timestamp=10/16/26, 10\:54\u202FAM
|
||||||
Username=arti
|
Username=arti
|
||||||
+56
-42
@@ -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
|
locally). The failing code is therefore chosen by **whatever calls this routine** — and that
|
||||||
caller is what still needs finding.
|
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
|
## Next steps
|
||||||
|
|
||||||
1. Find the CALLER of FUN_rom_07fbd000 and the status code it passes -- that is the
|
1. Model the host DUART (DUART1 channel A) enough for the level-1 HOST PORT test
|
||||||
failing test. Use smart34010 for call targets (Ghidra's CALLA does not resolve).
|
(bit 0x3F...); the DUARTs are unmodelled and are the current gate.
|
||||||
2. Optionally fix Ghidra's CALLA operand handling to get a usable call graph.
|
2. Keep using cap.lua to read which test fails next -- the loop is now repeatable.
|
||||||
|
|
||||||
## 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.
|
|
||||||
@@ -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;}
|
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;}
|
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;}
|
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: "" 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; }
|
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 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user