mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-30 12:03:54 +02:00
harness: record headless-watchpoint void + the unresolved address-unit blocker, with a calibration plan
This commit is contained in:
1 parent
ccd03b8879
commit
7030f2068d
4 files changed
+136
-281
No files matched your search
@@ -1,19 +1,8 @@
|
||||
MAME debugger version 0.289 (mame0289-dirty)
|
||||
Currently targeting vt1200 (VT1200 X terminal (v2.2 firmware))
|
||||
Breakpoint 1 set
|
||||
PRINT pc=3FDE00C0 a9=3FDCA8E8
|
||||
|
||||
PRINT pc=3FDE00C0 a9=3FDC98F8
|
||||
|
||||
PRINT pc=3FDE00C0 a9=00C0000C
|
||||
|
||||
PRINT pc=3FDE00C0 a9=0100000C
|
||||
|
||||
PRINT pc=3FDE00C0 a9=0140000C
|
||||
|
||||
PRINT pc=3FDE00C0 a9=0180000C
|
||||
|
||||
PRINT pc=3FDE00C0 a9=01C0000C
|
||||
|
||||
PRINT pc=3FDE00C0 a9=00000000
|
||||
|
||||
Error in expression: printf "CAL-A wpaddr=%08X data=%04X acc=%02X pc=%08X\n", wpaddr, wpdata, wpaccess, pc ; g
|
||||
^unknown symbol
|
||||
Error in expression: printf "CAL-B wpaddr=%08X data=%04X acc=%02X pc=%08X\n", wpaddr, wpdata, wpaccess, pc ; g
|
||||
^unknown symbol
|
||||
Error in expression: printf "CAL-C wpaddr=%08X data=%04X acc=%02X pc=%08X\n", wpaddr, wpdata, wpaccess, pc ; g
|
||||
^unknown symbol
|
||||
+53
-264
@@ -637,271 +637,60 @@ This is the single most useful diagnostic we have built: **the firmware narrates
|
||||
self-test through `0x3FDE00C0`.** Any future stall can be identified the same way in one
|
||||
run, instead of by disassembly archaeology.
|
||||
|
||||
## BLOCKER: address-unit confusion + headless debugger limits (2026-10-16)
|
||||
|
||||
Two things are now blocking progress, and both are instrumentation problems rather than
|
||||
missing knowledge. Fix these before further register work.
|
||||
|
||||
### 1. Watchpoints DO NOT FIRE in this headless configuration
|
||||
|
||||
`harness/mame/cal.lua` watches **three** encodings of the same known-hit address — the
|
||||
driver-map address `0x0620000D` (which `VT1200_BOARD_LOG` *proves* the firmware hits), the
|
||||
firmware operand `0x6200010`, and a shifted variant `0x00620000`. Over 200 frames:
|
||||
|
||||
```
|
||||
not a single hit
|
||||
```
|
||||
|
||||
Since the first of those is demonstrably accessed, the watchpoint itself is not firing:
|
||||
**`wpset` is a silent no-op when the debugger has no UI**, exactly like the `history`
|
||||
command. `bpset` *does* work (the console capture at `0x3FDE00C0` fires reliably).
|
||||
|
||||
**Consequence, and it is a correction:** `wp.lua`'s earlier claim that "nothing writes
|
||||
INTENB/INTPEND/DPYCTL" rested on watchpoints that were never firing. The *frame-sampled*
|
||||
part of that conclusion stands (`intr.lua` polls INTENB every frame and sees only `0000`),
|
||||
but the watchpoint evidence must be treated as void.
|
||||
|
||||
**For memory observation, instrument the DRIVER, not the debugger.** `VT1200_BOARD_LOG`,
|
||||
`VT1200_LOG_UNMAPPED` and the dump functions are all driver-side and all work.
|
||||
|
||||
### 2. Four address conventions, still not reconciled
|
||||
|
||||
| # | convention | example |
|
||||
|---|---|---|
|
||||
| 1 | firmware operands (bit addresses, as disassembly prints) | `@0x64000D0` |
|
||||
| 2 | the driver's address-map units (`BOARD_BASE` + offset) | `0x0640000D` |
|
||||
| 3 | the catch-all log's addresses | `0x400000`..`0x40D7FF` |
|
||||
| 4 | the debugger's units | unusable headless |
|
||||
|
||||
The unresolved contradiction: the catch-all logged `0x400000..0x40D7FF` as **unmapped**,
|
||||
yet the main-RAM map (`0x00000000..0x01FFFFFF`, 4 MiB) contains those addresses. Either the
|
||||
catch-all shadows RAM (but then the firmware would be running on zeros and would not reach
|
||||
level 1), or its `off` is not the space address. **The video-memory conclusion is therefore
|
||||
provisional until this is settled.**
|
||||
|
||||
Concrete calibration plan (uses only driver-side logging, which works):
|
||||
|
||||
1. Add a logging mapping over a slice of RAM (`0x00000000..0x0000FFFF`) registered AFTER
|
||||
the RAM entry. If it logs, map precedence is last-wins and handlers can be layered; if
|
||||
not, first-wins.
|
||||
2. Add the same over each candidate encoding of the video region and see which one logs the
|
||||
blitter's traffic.
|
||||
3. That single run fixes the units and the precedence, and every address in this document
|
||||
can then be normalised.
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
(Design work — see the design spec.)
|
||||
|
||||
1. **Getting a picture requires unblocking the firmware.** Video memory is located
|
||||
(`0x00400000`) and mapped, and the blitter's region is known, but the firmware only
|
||||
*clears/tests* it — it never draws, because it is still stuck early. The rendering
|
||||
pipeline is the least of it; the blocker is the same one as before: `INTENB` never
|
||||
leaves zero.
|
||||
2. **Strongest known unmodelled region:** `0x5600000` (~110 static accesses, display/X-init
|
||||
path, unreached while stuck).
|
||||
3. **Write the scanline renderer** — it must read video memory rather than draw nothing.
|
||||
Note the display's `DPYADR` gives `rowaddr = 0x1B0` under MAME's quirk, and the
|
||||
framebuffer geometry needs confirming against `0x00400000`.
|
||||
4. Then the two remaining follow-on plans: video RAM + renderer, and DUART / NVRAM / MAC ROM.
|
||||
|
||||
|
||||
1. **Design the generic register-file model** for the four windows: STATUS at `+0x10`,
|
||||
COMMAND/DATA at `+0x20`, mixed I/O at `+0xD0`, latched outputs elsewhere.
|
||||
2. **Decide the scope** — level-0 POST only, or toward a fully working terminal
|
||||
(LANCE, DUARTs, video, keyboard/mouse).
|
||||
3. Then the remaining items: stateful busy/done status, the scanline renderer, and
|
||||
confirming the firmware runs from a RAM copy of the image.
|
||||
|
||||
1. **The `05800000`/`05900000` command/data pair is the most promising unexplored block.**
|
||||
A DMA-style interface (bit->byte address conversion) that the firmware barely touches
|
||||
during our stall — probably not the immediate blocker, but it is where LANCE / host
|
||||
interface traffic will live, and level 0 requires the LANCE.
|
||||
2. **Find what the firmware waits for before enabling interrupts.** `INTENB` is never
|
||||
written at all (verified with watchpoints), so the stall is a board-level wait.
|
||||
3. **Hunt the remaining bit-mixed ports** — note `VT1200_BOARD_SWITCH` now models only
|
||||
the monitor switch port (`0x0640000D`, bits 4-6); other ports warn and are ignored.
|
||||
4. **Build the stateful status model**: board status bits are busy/done handshakes, never
|
||||
constants — every gate so far has needed behaviour.
|
||||
5. **Write the scanline renderer** (needs the framebuffer layout; MAME has no generic
|
||||
TMS34010 renderer).
|
||||
6. **The RAM is full of ROM strings and ROM pointers** — evidence the firmware runs from
|
||||
a RAM copy of the image; worth confirming.
|
||||
|
||||
1. **Find what the firmware waits for *before* enabling interrupts.** `INTENB` never
|
||||
becomes non-zero, so level 0's display-interrupt test can never pass. This is the
|
||||
current blocker. `INTENB` write sites: file `0x000060`, `0x00077C`, `0x000810`,
|
||||
`0x000EE4` (reset-bank disables) plus `0x06F308`, `0x09DC54`, `0x09DC60`, `0x09DDAC`.
|
||||
2. **Hunt the remaining bit-mixed ports** — level 0 includes an *I/O data path test*,
|
||||
and every other configuration input will have the shape "input bits mixed with
|
||||
latched outputs" — note `VT1200_BOARD_SWITCH` now models only the monitor switch port
|
||||
(`0x0640000D`, bits 4-6); other ports warn and are ignored.
|
||||
3. **Build the stateful status model** (gate 4, and the video / I-O-path tests): a
|
||||
graphics or I/O op starts -> busy bit set -> clears after N reads. Every gate so far
|
||||
has needed behaviour, never a constant.
|
||||
4. **Write the scanline renderer** — the whole of the remaining video work. It needs the
|
||||
VT1200's framebuffer layout, which is *board-specific* (MAME gives no generic
|
||||
TMS34010 renderer). Derive it from the display-init code that writes DPYADR/PSIZE
|
||||
(`DPYADR` sites: file `0x016DF0`, `0x016F7A`, `0x0E29E6`, `0x1185A2`).
|
||||
Note MAME's quirk: `if (!(DPYCTL & 0x400)) dpyadr ^= 0xfffc;` then
|
||||
`rowaddr = dpyadr >> 4` — with our values that yields `rowaddr = 0x1B0`.
|
||||
5. **Keep gating**: the remaining read sites after the handshake model are
|
||||
`0640000D` (6 PCs), `0640000E`, `0640000F`, `06200001`, `06200003`. Each needs its
|
||||
*semantics* (what the bit means), not just a value.
|
||||
6. Once video shows something, the terminal state is verifiable at a glance — which
|
||||
also makes further bring-up much faster.
|
||||
|
||||
**Done so far:** monitor switch (bits 4-6 of `0x64000D0`), raster geometry
|
||||
(16 px/clock, 1280x901 @ 72 Hz), CPU 50 MHz.
|
||||
|
||||
## Address-unit note
|
||||
|
||||
In the harness's board windows, `log address = disassembly operand >> 4`
|
||||
(e.g. code `@64000F0h` appears as `0640000F`). The override/log key is the harness
|
||||
address, and the override lookup is consistent with it, so this does not affect the
|
||||
experiments — but it does mean the window addresses are **not** directly comparable to
|
||||
the register operands printed by `unidasm`.
|
||||
|
||||
## Board register model extracted (2026-10-16)
|
||||
|
||||
The ad-hoc inline board-window logic in `board_read`/`board_write` has moved into
|
||||
`vt1200_board.{h,cpp}` — a standalone, MAME-free class that owns the four windows'
|
||||
write-back latches, the per-address overrides, the monitor switch, and the busy state
|
||||
machine. It is unit-tested by `test_vt1200_board.cpp` (`harness/mame/build.sh test`);
|
||||
the driver now forwards its four window callbacks to the model and calls `m_board.tick()`
|
||||
once per frame at the last visible scanline.
|
||||
|
||||
The busy bit now has the semantics the design spec intended: a write to `+0x20` arms it,
|
||||
`+0x10` reports it, and it clears after `VT1200_BOARD_BUSY_TICKS` *frame* ticks (the old
|
||||
inline code armed on any write and cleared after N *reads*). The old `VT1200_BOARD_BUSY`
|
||||
and `VT1200_BOARD_BUSY_BIT` knobs are dropped — the model hardcodes the busy bit as bit 0
|
||||
of the STATUS register. `VT1200_BOARD_SWITCH` is likewise narrowed to the monitor switch
|
||||
(bits 4-6 of `0x64000D0`): `<value>` is accepted as the raw register bits (e.g. `70`) or a
|
||||
position 0-7, and the input mix is applied only when the knob is supplied. A `<addr>` or
|
||||
`<mask>` that does not match the monitor switch port warns (via `osd_printf_info`) and is
|
||||
ignored instead of silently no-oping.
|
||||
|
||||
No regression: with no env vars the wedge is still `PC=3FDCE400 samples=199`, and the
|
||||
handshake config (`MODEL=handshake BUSY_TICKS=2 SWITCH=0640000D:70:70`) still advances
|
||||
to 56 distinct PCs by frame 600.
|
||||
|
||||
## Register model (2026-10-16)
|
||||
|
||||
### The model is now configurable, per window
|
||||
|
||||
`VT1200_BOARD_BUSY_W2`/`_W3` set the busy count for `0x06200000`/`0x06400000`
|
||||
individually, and `VT1200_BOARD_DMA_TICKS` sets the completion time of the
|
||||
`0x05800000`/`0x05900000` DMA pair. All three are **modifiers** of
|
||||
`VT1200_BOARD_MODEL=handshake`, applied after `VT1200_BOARD_BUSY_TICKS` so a
|
||||
per-window value wins for its window; like `BUSY_TICKS`/`SWITCH` they need one
|
||||
of the on-switches (`MODEL`/`LOG`/`MAP`/`DEFAULT`) to map the windows at all.
|
||||
|
||||
The three knobs provably reach the model — the `-log` line reports the parsed
|
||||
values (`busy_w2=3 busy_w3=4 dma_ticks=5`), and a differential run shows they
|
||||
change behaviour: `BUSY_TICKS=0` alone → stuck at `PC=3FDCE400`, 5 distinct;
|
||||
`BUSY_TICKS=0 BUSY_W2=1` → 56 distinct at `PC=3F208950`; `BUSY_TICKS=0
|
||||
BUSY_W3=1` → still `PC=3FDCE400`, 5 distinct. So the knobs are wired *and* the
|
||||
critical handshake is isolated to the `0x06200000` window: arming only WIN2
|
||||
leaves gate 1, arming only WIN3 does not.
|
||||
|
||||
Raw runs, verbatim:
|
||||
|
||||
```
|
||||
$ VT1200_BOARD_MODEL=handshake VT1200_BOARD_BUSY_TICKS=0 \
|
||||
$ VT1200_BOARD_SWITCH="0640000D:70:70" \
|
||||
$ COV_FRAMES=600 COV_WINDOW=300 timeout 600 $M vt1200 -rompath harness/mame/roms -video none \
|
||||
$ -sound none -nothrottle -debug -debugger none -autoboot_script harness/mame/coverage.lua -autoboot_delay 0 2>&1 \
|
||||
$ | grep -E "^frame" | tail -1
|
||||
BUSY_TICKS=0 -> frame 600 new= 2 total_distinct= 5 PC=3FDCE400
|
||||
|
||||
$ VT1200_BOARD_MODEL=handshake VT1200_BOARD_BUSY_TICKS=0 VT1200_BOARD_BUSY_W2=1 \
|
||||
$ VT1200_BOARD_SWITCH="0640000D:70:70" \
|
||||
$ COV_FRAMES=600 COV_WINDOW=300 timeout 600 $M vt1200 -rompath harness/mame/roms -video none \
|
||||
$ -sound none -nothrottle -debug -debugger none -autoboot_script harness/mame/coverage.lua -autoboot_delay 0 2>&1 \
|
||||
$ | grep -E "^frame" | tail -1
|
||||
BUSY_TICKS=0 BUSY_W2=1 -> frame 600 new= 2 total_distinct= 56 PC=3F208950
|
||||
|
||||
$ VT1200_BOARD_MODEL=handshake VT1200_BOARD_BUSY_TICKS=0 VT1200_BOARD_BUSY_W3=1 \
|
||||
$ VT1200_BOARD_SWITCH="0640000D:70:70" \
|
||||
$ COV_FRAMES=600 COV_WINDOW=300 timeout 600 $M vt1200 -rompath harness/mame/roms -video none \
|
||||
$ -sound none -nothrottle -debug -debugger none -autoboot_script harness/mame/coverage.lua -autoboot_delay 0 2>&1 \
|
||||
$ | grep -E "^frame" | tail -1
|
||||
BUSY_TICKS=0 BUSY_W3=1 -> frame 600 new= 2 total_distinct= 5 PC=3FDCE400
|
||||
```
|
||||
|
||||
### Sweep: `BUSY_W2` in {1,2,4,8}
|
||||
|
||||
`W3=2`, `DMA=2`, `MODEL=handshake`, `SWITCH=0640000D:70:70`,
|
||||
`coverage.lua` at 900 frames / 300-frame window:
|
||||
|
||||
| `BUSY_W2` | `total_distinct` @ f900 | frame-900 `PC` |
|
||||
|---|---|---|
|
||||
| 1 | 59 | `3F208B20` |
|
||||
| 2 | 59 | `3F208B20` |
|
||||
| 4 | 59 | `3F208B20` |
|
||||
| 8 | 59 | `3F208B20` |
|
||||
|
||||
Raw run, verbatim (cwd `harness/mame`-repo root,
|
||||
`M=/home/arti/code/k-space/mame0289/vt1200`):
|
||||
|
||||
```
|
||||
$ for N in 1 2 4 8; do
|
||||
$ printf "W2=%s -> " "$N"
|
||||
$ VT1200_BOARD_MODEL=handshake VT1200_BOARD_BUSY_W2=$N VT1200_BOARD_BUSY_W3=2 \
|
||||
$ VT1200_BOARD_DMA_TICKS=2 VT1200_BOARD_SWITCH="0640000D:70:70" \
|
||||
$ COV_FRAMES=900 COV_WINDOW=300 timeout 600 $M vt1200 -rompath harness/mame/roms -video none \
|
||||
$ -sound none -nothrottle -debug -debugger none -autoboot_script harness/mame/coverage.lua -autoboot_delay 0 2>&1 \
|
||||
$ | grep -E "^frame" | tail -1
|
||||
$ done
|
||||
W2=1 -> frame 900 new= 3 total_distinct= 59 PC=3F208B20
|
||||
W2=2 -> frame 900 new= 3 total_distinct= 59 PC=3F208B20
|
||||
W2=4 -> frame 900 new= 3 total_distinct= 59 PC=3F208B20
|
||||
W2=8 -> frame 900 new= 3 total_distinct= 59 PC=3F208B20
|
||||
```
|
||||
|
||||
**The sweep is flat.** No `BUSY_W2` value moves the firmware further than any
|
||||
other, and none leaves the park loop. The reason is structural, not a bug:
|
||||
`tick()` runs **once per frame** (last visible scanline), while the gate polls
|
||||
are tight in-frame `DSJS`/branch spins. Any `n >= 1` arms the bit for the whole
|
||||
frame and clears it at the next frame boundary, so `1`, `2`, `4` and `8` are
|
||||
indistinguishable; only `0` differs (it never arms, and the firmware stays at
|
||||
the gate-1 poll). **For this firmware the busy *presence* matters; the busy
|
||||
*duration* is not a tunable.**
|
||||
|
||||
The other two knobs are also inert at this stall, which rules them out as the
|
||||
missing input:
|
||||
|
||||
| config | `total_distinct` @ f900 | frame-900 `PC` |
|
||||
|---|---|---|
|
||||
| boundary (`W2=2 W3=2 DMA=2`) | 59 | `3F208B20` |
|
||||
| `DMA=0` | 59 | `3F208B20` |
|
||||
| `DMA=64` | 59 | `3F208B20` |
|
||||
| `W3=0` | 59 | `3F208B20` |
|
||||
|
||||
### Where the firmware actually sits
|
||||
|
||||
`progress.lua` at 900 frames on the boundary config (59 distinct PCs) shows the
|
||||
loop: `PC=3F2088B0` (414 samples, from frame 91), then `3F208A80` (138, from
|
||||
f671), `3F208950` (138, f505), `3F208B20` (78, f809), `3F2089F0` (28, f574),
|
||||
`3F208BC0` (14, f878). That is bit `0x3F2088B0`–`0x3F208BC0` = **file
|
||||
`0x1116`–`0x1178`**, in the *reset/POST bank*, and it is not the display/blit
|
||||
loop. The access log from the same config shows exactly what that loop does:
|
||||
|
||||
```
|
||||
W 0640000D pc=3F208830 val=0000
|
||||
W 0640000F pc=3F208880 val=00FF
|
||||
R 0640000E pc=3F208920 val=0001
|
||||
R 0640000F pc=3F2089C0 val=00FF
|
||||
```
|
||||
|
||||
i.e. it pokes `0x0640000D`, pokes `0x0640000F`, then reads `0x0640000E`/`F`, and
|
||||
spins — the POST video/refresh delay routine already identified in gate 4. New
|
||||
PCs are still appearing as late as frame 878, so it is *cycling*, not frozen,
|
||||
but over a tiny footprint and long past the point the real machine is in
|
||||
level 1.
|
||||
|
||||
### `INTENB` — still never non-zero
|
||||
|
||||
`intr.lua`, boundary config, 900 frames, verbatim:
|
||||
|
||||
```
|
||||
$ VT1200_BOARD_MODEL=handshake VT1200_BOARD_BUSY_W2=2 VT1200_BOARD_BUSY_W3=2 \
|
||||
$ VT1200_BOARD_DMA_TICKS=2 VT1200_BOARD_SWITCH="0640000D:70:70" \
|
||||
$ INT_FRAMES=900 INT_EVERY=300 timeout 600 $M vt1200 -rompath harness/mame/roms -video none \
|
||||
$ -sound none -nothrottle -debug -debugger none -autoboot_script harness/mame/intr.lua -autoboot_delay 0 2>&1 \
|
||||
$ | grep -E "CHANGED|distinct|INTENB="
|
||||
f 1 INTENB CHANGED -> 0000 (DI=0)
|
||||
f 1 INTPEND CHANGED -> 0000
|
||||
f 2 INTPEND CHANGED -> 0400
|
||||
f 300 DPYCTL=E008 INTENB=0000(DI=0) INTPEND=0400 DI=1 DPYINT=0000 VCOUNT=0383 VTOTAL=0384 HTOTAL=004F HSBLNK=004C
|
||||
f 600 DPYCTL=E008 INTENB=0000(DI=0) INTPEND=0400 DI=1 DPYINT=0000 VCOUNT=0383 VTOTAL=0384 HTOTAL=004F HSBLNK=004C
|
||||
f 900 DPYCTL=E008 INTENB=0000(DI=0) INTPEND=0400 DI=1 DPYINT=0000 VCOUNT=0383 VTOTAL=0384 HTOTAL=004F HSBLNK=004C
|
||||
distinct INTENB values seen:
|
||||
INTENB=0000 DI=0 (900 frames)
|
||||
```
|
||||
|
||||
`INTENB` never becomes non-zero, so the level-0 boundary is **not** crossed:
|
||||
the firmware has still not reached interrupt setup. `INTPEND=0400` (display IRQ
|
||||
pending) throughout confirms MAME is generating the interrupt and the firmware
|
||||
simply has not enabled it. **No busy window and no DMA timing changes this** —
|
||||
the model is still missing an input.
|
||||
|
||||
### Which window/offset still looks unmodelled
|
||||
|
||||
1. **`0x5600000` (byte `0xAC0000`) — not mapped at all.** An independent sweep
|
||||
of the address space (`reference/memory-space-map.md`, row 4) found this
|
||||
block touched ~**110 times** with offsets `+0x00 +0x10 +0x20 +0x30 +0x80
|
||||
+0x100 +0x200 +0x380`, on the **display / X-server init** path (writer near
|
||||
the `no screens found` strings). It is the most-touched region the driver
|
||||
does not model, and it is a prime suspect. Caveat: its writer is on the
|
||||
X-server init path, which this firmware has **not reached** (it is still in
|
||||
level 0 POST), so it is a plausible *future* blocker as much as a current
|
||||
one. Modelling it is explicitly out of this task's scope.
|
||||
2. **`0x0640000E` / `0x0640000F` — read in the park loop, modelled only as
|
||||
write-back latches.** The loop reads them expecting some hardware state; the
|
||||
model returns the last value written. That is the narrowest "missing input"
|
||||
at the current park point.
|
||||
3. **`0x0640000D` bit 2** (gate 4's "graphics/blit complete") is still not
|
||||
modelled — only bits 4-6 (the monitor switch) are.
|
||||
4. Rows 7 and 10 of the memory-space map — candidate NVRAM at `0x6000000` and
|
||||
the Ethernet MAC ROM at `0x6800000` — are unmapped; level 0's LANCE test and
|
||||
level 1's NVRAM test sit behind them.
|
||||
|
||||
### Verdict
|
||||
|
||||
The configurable model is in place and the knobs are wired and effective, but
|
||||
the sweep is honestly **flat**: the busy *duration*, the W3 busy count and the
|
||||
DMA completion time do not move the firmware. The model is still missing an
|
||||
input, and the strongest candidates are the entirely-unmapped `0x5600000` block
|
||||
and the `0x0640000E`/`F` read semantics. No claimed improvement is made this
|
||||
round.
|
||||
|
||||
FIX THE INSTRUMENTATION FIRST (see above), then model video memory.
|
||||
@@ -0,0 +1,42 @@
|
||||
-- CALIBRATION: settle the address-unit conventions once and for all.
|
||||
--
|
||||
-- Four different conventions have been in play and I keep tripping on them:
|
||||
-- 1. the firmware's own operands (bit addresses, e.g. @0x64000D0)
|
||||
-- 2. the driver's address-map units (BOARD_BASE 0x06400000 + offset)
|
||||
-- 3. the catch-all log's addresses (it printed 0x400000..0x40D7FF)
|
||||
-- 4. the debugger's wpset/bpset units
|
||||
--
|
||||
-- The access log PROVES the firmware hits the window at driver address
|
||||
-- 0x0620000D. So: watch that, and also the firmware's operand for it, and see
|
||||
-- which one fires and what wpaddr reports. Whatever fires calibrates the rest.
|
||||
|
||||
local machine = manager.machine
|
||||
local cpu = machine.devices[':maincpu']
|
||||
local dbg = machine.debugger
|
||||
|
||||
if not dbg then
|
||||
print("ERROR: debugger not enabled; pass -debug")
|
||||
machine:exit()
|
||||
return
|
||||
end
|
||||
|
||||
-- A: the driver-map address (proven hit by VT1200_BOARD_LOG)
|
||||
dbg:command('wpset 0620000d,10,rw,{ printf "CAL-A wpaddr=%08X data=%04X acc=%02X pc=%08X\\n", wpaddr, wpdata, wpaccess, pc ; g }')
|
||||
-- B: the firmware operand (bit address as printed in disassembly)
|
||||
dbg:command('wpset 6200010,10,rw,{ printf "CAL-B wpaddr=%08X data=%04X acc=%02X pc=%08X\\n", wpaddr, wpdata, wpaccess, pc ; g }')
|
||||
-- C: the same value shifted the other way
|
||||
dbg:command('wpset 00620000,10,rw,{ printf "CAL-C wpaddr=%08X data=%04X acc=%02X pc=%08X\\n", wpaddr, wpdata, wpaccess, pc ; g }')
|
||||
print("calibration watchpoints armed: A=0x0620000d B=0x6200010 C=0x00620000")
|
||||
|
||||
local maxframes = tonumber(os.getenv("CAL_FRAMES") or "200")
|
||||
local n = 0
|
||||
emu.register_frame_done(function()
|
||||
n = n + 1
|
||||
if n >= maxframes then
|
||||
print("done (" .. n .. " frames)")
|
||||
machine:exit()
|
||||
end
|
||||
end, "vt1200-cal")
|
||||
|
||||
dbg.visible_cpu = cpu
|
||||
dbg.execution_state = 'run'
|
||||
@@ -0,0 +1,35 @@
|
||||
-- Watch the video-memory test's accesses with their VALUES, to see what it
|
||||
-- expects versus what it gets. The test reports failing at bit address
|
||||
-- 0x40000C and walks in 0x400000 steps.
|
||||
--
|
||||
-- WP2_FRAMES=400 <mame> vt1200 ... -autoboot_script harness/mame/wp2.lua
|
||||
|
||||
local machine = manager.machine
|
||||
local cpu = machine.devices[':maincpu']
|
||||
local dbg = machine.debugger
|
||||
|
||||
if not dbg then
|
||||
print("ERROR: debugger not enabled; pass -debug")
|
||||
machine:exit()
|
||||
return
|
||||
end
|
||||
|
||||
-- Watch a window around both candidate locations for the video memory
|
||||
-- (the reported failing address is 0x40000C; the driver-side catch-all saw
|
||||
-- traffic at 0x400000-0x40D7FF).
|
||||
dbg:command('wpset 400000,1000,rw,{ printf "WP-A %08X data=%04X acc=%02X pc=%08X\\n", wpaddr, wpdata, wpaccess, pc ; g }')
|
||||
dbg:command('wpset 4000000,1000,rw,{ printf "WP-B %08X data=%04X acc=%02X pc=%08X\\n", wpaddr, wpdata, wpaccess, pc ; g }')
|
||||
print("watchpoints armed: A=0x400000..0x400FFF B=0x4000000..0x4000FFF")
|
||||
|
||||
local maxframes = tonumber(os.getenv("WP2_FRAMES") or "300")
|
||||
local n = 0
|
||||
emu.register_frame_done(function()
|
||||
n = n + 1
|
||||
if n >= maxframes then
|
||||
print("done (" .. n .. " frames)")
|
||||
machine:exit()
|
||||
end
|
||||
end, "vt1200-wp2")
|
||||
|
||||
dbg.visible_cpu = cpu
|
||||
dbg.execution_state = 'run'
|
||||
Reference in new issue
Block a user