forked from opencode.energia.arti.ee/vt1200
The XIE path now runs end to end: XieCreateImage -> XieCreatePhoto ->
XiePutTile -> XieExport(photomap -> depth-1 pixmap) -> XCopyArea(pixmap ->
window), and the client's tile appears on screen at the client's own window
position, pixel-exact.
TWO FAULTS BEHIND THE LONG DEAD END
1. Device model (harness/mame/vt1200.cpp, opt-in VT1200_ACCEL=1). The
accelerator's output port 0x5600200 returns the pixel stream the firmware
pushed into the FIFO -- the firmware then stores it into the drawable itself
(file 0x125528: MOVE *B6,*B1 ; ADDK 0x10,B1). The FIFO read pointer was
never reset between transfers, so consecutive exports read stale words and
the same fill produced 759 then 516 set pixels. Reset m_fifo_in/out on the
data-register write; the export is now deterministic.
2. Measurement, not the device.
- dwt/screenshot.py without --real reads 1024x1024 at a 128-byte row stride,
but the VR319 default programs 1280x1024 at a 2048-bit (256-byte) pitch.
That is the "shifted" picture; --real is the correct read.
- The earlier "0 differing bytes over 128 KiB" VRAM comparison stepped peek
by 1024 *bit* addresses, so it scanned rows 0..63 only -- never the window
at rows 200..263. Over the real raster the white/black diff is 576 bytes
spanning exactly those rows.
- New instrument: decclient does a server-side XGetImage readback of the
pixmap and window and counts set pixels. That separated "the server never
drew it" from "the framebuffer view is wrong".
EVIDENCE (reproduced twice, the second time from a fresh machine)
no export vs 0xFF : 4096 / 4096 pixels differ
no export vs 0x00 : 0 / 4096 (the window background is black)
0xFF vs 0x00 : 4096 / 4096
0xAA vs 0x0F : 2048 / 4096 (the two stripe phases)
Tile byte 0xAA reproduces as 1-pixel vertical stripes, 0x0F as 4-pixel, with
no shear -- so the placement is right and the pixels are the client's.
Contents: xie/ holds DEC XIE 2.3 headers, 84 man pages and complete
client+server source; a libXie.a and decclient built from DEC's own code; the
XIE probes; and evidence/ with every measurement, including explicit
retractions of the earlier wrong readings (VRAM_IDENTICAL_FOR_BOTH_FILLS and
friends). xie/evidence/XIE_IMAGE_DISPLAYED.md is the report; frames are in
xie/evidence/png/.
The accelerator model stays opt-in: it answers the status poll and relays the
pixel stream, but performs no compositing, so it is a stand-in and the verified
default configuration is unchanged (a no-env run still parks in the level-0
diagnostics menu at PC=3FDCE400).
233 lines
9.1 KiB
Markdown
233 lines
9.1 KiB
Markdown
# Does the VT1200 firmware issue XIE requests? A MAME trace
|
|
|
|
Short answer: **no.** Over three configurations — level-0 diagnostics, the booted
|
|
OS with the Terminal Manager, and a forced jump into the Scalution test — the
|
|
server's XIE dispatcher `XieProc` is **never entered**. The built-in image tests
|
|
are hardware diagnostics that program the image-option/scaler registers directly.
|
|
|
|
There is therefore **no ROM-side XIE client sequence to replay**, and the
|
|
`PUT_TILE` band question cannot be settled this way.
|
|
|
|
Everything below is measured, with a control that proves the measurement works.
|
|
|
|
---
|
|
|
|
## 1. How the test was triggered, and why the entry point is not the problem
|
|
|
|
### 1.1 The Scalution test entry
|
|
|
|
`"error initializing scalution"` lives at file `0x371F2`; its only xref is the
|
|
instruction at file `0x36CB6`. Scanning backwards from there for the
|
|
`MMTM SP,0x…` prologue (`8F 09`) finds the test's entry at **file `0x35EA8`**
|
|
= bit `0x3F1AF540`:
|
|
|
|
```
|
|
rom:00035ea8 MMTM SP,0x154
|
|
rom:00035eac MOVE A14,A13
|
|
rom:00035eae ADDI 0x6e0,A14
|
|
rom:00035eb2 SUB A11,A11
|
|
rom:00035eb4 MOVE A11,*A13(0x520),0x1
|
|
...
|
|
rom:00035ecc CALLA 0x07f67f38 ; 0x127F38 test-framework entry
|
|
rom:00035ed2 MOVE A8,@0xa5f00,0x1
|
|
rom:00035ee0 MOVK 0x1,A11 / MOVB A11,*A13 ; mode 1
|
|
rom:00035ee6 MOVK 0x3,A11 / MOVB A11,*A13 ; mode 3
|
|
rom:00035eec MOVK 0x5,A11 / MOVB A11,*A13 ; mode 5
|
|
```
|
|
|
|
It is reached from a descriptor table (`refs to 0x35EA8` = file `0x1AFE8` and
|
|
`0x1BA46`), i.e. the "5 - Scalution Test" menu entry, whose label string is
|
|
`0x2B5D2` and whose menu table is built by the routine at `0x2A9A8`
|
|
(`MOVI 0x3f35ae90` = that label, stored at base + `0xa00000` bits).
|
|
|
|
**What it does:** the body writes the image-option/scaler hardware directly —
|
|
|
|
```
|
|
rom:00036b02 MOVB A9,0xca2b0 ; scaler control registers
|
|
rom:00036b0c MOVB A7,0xca2c0 ; (0xca270 … 0xca3a0)
|
|
rom:00036b7c MOVB A11,0xca330
|
|
rom:00036c02 MOVE A11,@0x5600100,0x0 ; image-option registers
|
|
rom:00036c0c MOVE A7,@0x5600020,0x0
|
|
rom:00036c16 MOVE A7,@0x5600030,0x0
|
|
```
|
|
|
|
No call to the server, no request buffer, no `XieProc`.
|
|
|
|
### 1.2 Triggering it in MAME
|
|
|
|
The menu path needs the LK401 keyboard model and a menu map that is not
|
|
documented; the diagnostic menu's own key handling was not reversed. Instead the
|
|
test was entered by PC assignment from the menu idle loop, the same mechanism
|
|
`hello.lua` uses:
|
|
|
|
```lua
|
|
dbg:command("bpset 3FDCE400,,{ pc = 3F1AF540 ; g }") -- idle -> scaled test entry
|
|
```
|
|
|
|
(Gotcha: the firmware reaches the idle PC `3FDCE400` **from frame 1**, not at
|
|
frame 300 — `progress.lua` samples exactly that PC for all 199 frames of the
|
|
baseline. So an "enter the test at frame N" breakpoint actually fires at frame 1
|
|
unless it is gated on a frame counter.)
|
|
|
|
---
|
|
|
|
## 2. The tracer
|
|
|
|
Script: **`harness/mame/xie_trace.lua`** (new file, this task).
|
|
Breakpoint inside `XieProc`, one instruction *after* it loads the request buffer,
|
|
so `A9` is the buffer:
|
|
|
|
```
|
|
rom:00064b98 MMTM SP,0x54 <- XieProc entry bit 3F525CC0
|
|
rom:00064ba2 MOVE *A11(0x40),A9,0x1 ; A9 = client->requestBuffer
|
|
rom:00064ba6 SETF 0x8,0x0,0x0
|
|
rom:00064ba8 MOVE *A9(0x8),A11,0x0 ; <- breakpoint here, bit 3F525D40
|
|
```
|
|
|
|
Action (generated by the script):
|
|
|
|
```
|
|
{ printf "XIEHIT buf=%08X %04X %04X %04X %04X %04X %04X %04X %04X\n",
|
|
a9, w@(a9+0), w@(a9+16), w@(a9+32), w@(a9+48),
|
|
w@(a9+64), w@(a9+80), w@(a9+96), w@(a9+112) ; g }
|
|
```
|
|
|
|
`w@` is used rather than `b@` because the TMS34010 program space is 16-bit wide
|
|
and bit-addressed; `+16` bits = the next word.
|
|
|
|
**Critical harness detail:** debugger `printf` output goes to the *debug
|
|
console*, which is discarded unless MAME is started with **`-debuglog`**. Without
|
|
it the runs look like "zero hits" whether or not the breakpoint fires. All runs
|
|
below use `-debuglog`.
|
|
|
|
---
|
|
|
|
## 3. The control run (proof the measurement works)
|
|
|
|
Same script, breakpoint moved to the menu idle PC, which executes continuously:
|
|
|
|
```
|
|
XIE_TRACE=0x3FDCE400 XIE_FRAMES=60 XIE_WORDS=0 \
|
|
$M vt1200 -rompath /home/arti/code/k-space/vt1200/harness/mame/roms \
|
|
-video none -sound none -nothrottle -debug -debugger none -debuglog \
|
|
-autoboot_script /home/arti/code/k-space/vt1200/harness/mame/xie_trace.lua \
|
|
-autoboot_delay 0
|
|
```
|
|
|
|
Result: **4 634 965 hits** in `debug.log` (`XIEHIT pc=3FDCE400`). The breakpoint,
|
|
the action, the memory accessors and the log path all work.
|
|
|
|
---
|
|
|
|
## 4. The three trace runs
|
|
|
|
| run | configuration | frames | `XieProc` hits |
|
|
|---|---|---|---|
|
|
| A | plain boot → level-0 diagnostics menu | 1200 | **0** |
|
|
| B | `VT1200_SKIP_LEVEL1=1` → OS + Terminal Manager | 4500 | **0** |
|
|
| C | forced jump into the Scalution test at `0x35EA8` | 900 | **0** |
|
|
|
|
Logs: `xie/ghidra-evidence/mame/run_a_level0_diagnostics.txt`,
|
|
`run_b_os_terminal_manager.txt`, `run_c_scalution_jump.txt`,
|
|
`run_d_control.txt`.
|
|
|
|
Run A's PC stays at `3FDCE400` (menu) throughout; run B ends at
|
|
`3F579870` (OS code); run C leaves the menu and runs code at `3F208xxx`
|
|
(file `0x109xx`) — so the PC assignment did divert execution. Caveat: a
|
|
breakpoint placed on `0x35EA8` itself did **not** fire in run C, so the exact
|
|
instruction the jump landed on, and how far the test body executed before
|
|
diverting, is not proven. It does not affect the conclusion — the XIE breakpoint
|
|
covered the whole run either way.
|
|
|
|
**No request bytes were captured because no request was ever dispatched.** The
|
|
XIE breakpoint would have printed `buf=… 0081 0002 …` (reqType `0x81` = major
|
|
opcode 129) if the server had been asked to do anything.
|
|
|
|
Corroborating static evidence: the ROM contains exactly three strings containing
|
|
`Xie` — `"Xie"`, `"XieExtensionInit: AddExtension failed"`,
|
|
`"XieExtensionInit: Device Init failed"` — all server-side registration text.
|
|
There is no client-side XIE API (no `XieInitialize`/`XieCreatePhotomap`-style
|
|
names), which is what a firmware-resident XIE client would have left behind.
|
|
|
|
---
|
|
|
|
## 5. What this means for the import problem
|
|
|
|
The plan "trace the firmware's own XIE client to see the working `PUT_TILE`
|
|
sequence" **cannot work**: the firmware has no XIE client, and its image tests
|
|
drive the scaler registers instead of the protocol.
|
|
|
|
That leaves the static picture as the only route to the band/import question:
|
|
|
|
* `PUT_TILE` (minor 19) requires, from `0x6B966`: resource byte 40 == 0,
|
|
resource byte 36 != 0, and the band bit `1 << band` set in resource byte 8 or
|
|
byte 12 (`GHIDRA_XIE_IMPORT.md` §1).
|
|
* Nothing in the create path (`slot 8` → `0x678DA` → `0x6CA82`) writes byte 36,
|
|
so some *other* request must. Slot 43 rebuilds a resource record from another
|
|
resource's bands (`GHIDRA_XIE_IMPORT.md` §3) and remains the best candidate.
|
|
|
|
### Next probes (unchanged, and now the only path)
|
|
|
|
1. `PUT_TILE` with **band = 0** (request word 6 = 0) instead of 1.
|
|
`BadMatch (8)` ⇒ byte 36 is set and only the mask is wrong; `BadAccess (10)`
|
|
⇒ byte 36 is zero and a band must be created first.
|
|
2. If (1) fails: `minor 43, len 10, [id, 0…]` on the class-2 resource, then repeat
|
|
(1).
|
|
3. If (1) and (2) fail: `minor 7, len 4, [op=1, type=2, id]` (note the field
|
|
order: byte 8 is the *type*, byte 12 the *id*), or slot 20 (35 words).
|
|
|
|
---
|
|
|
|
## 6. Confirmed / Inferred / Unknown
|
|
|
|
**Confirmed**
|
|
1. The firmware never enters `XieProc` during POST/diagnostics, during the booted
|
|
OS/Terminal Manager, or when the Scalution test is entered (0 hits in 6600
|
|
frames, with a 4.6-M-hit control proving the tracer works).
|
|
2. The Scalution test (`0x35EA8`, bit `0x3F1AF540`) writes image-option/scaler
|
|
registers `0xCA2xx`/`0x56000xx`; it contains no server call.
|
|
3. The ROM has no client-side XIE strings; the only `Xie` strings are the
|
|
server's registration messages.
|
|
4. Debugger `printf` output requires `-debuglog`; without it, breakpoint actions
|
|
are invisible (this silently invalidated a first round of runs here).
|
|
|
|
**Inferred**
|
|
1. The built-in image tests are board-level diagnostics, not protocol clients.
|
|
2. If any code did call XIE it would still arrive at `XieProc` (dix dispatch);
|
|
a private internal bypass is not fully excluded, but nothing suggests one.
|
|
|
|
**Unknown**
|
|
1. Whether slot 43 or slot 20 is the band-materialising request (unchanged).
|
|
2. The image-option menu's key map (not needed for the conclusion).
|
|
|
|
---
|
|
|
|
## 7. Reproduce
|
|
|
|
```sh
|
|
M=/home/arti/code/k-space/mame0289/vt1200
|
|
R=/home/arti/code/k-space/vt1200
|
|
|
|
# A: level-0 diagnostics
|
|
XIE_FRAMES=1200 $M vt1200 -rompath $R/harness/mame/roms \
|
|
-video none -sound none -nothrottle -debug -debugger none -debuglog \
|
|
-autoboot_script $R/harness/mame/xie_trace.lua -autoboot_delay 0
|
|
# -> debug.log: no XIEHIT lines
|
|
|
|
# B: booted OS
|
|
VT1200_SKIP_LEVEL1=1 XIE_FRAMES=4500 $M vt1200 <same args>
|
|
# -> no XIEHIT lines
|
|
|
|
# C: forced Scalution test
|
|
XIE_JIT=3F1AF540 XIE_FRAMES=900 $M vt1200 <same args>
|
|
# -> no XIEHIT lines
|
|
|
|
# control: breakpoint on the menu idle PC (fires every frame)
|
|
XIE_TRACE=0x3FDCE400 XIE_WORDS=0 XIE_FRAMES=60 $M vt1200 <same args>
|
|
# -> hundreds of thousands of "XIEHIT pc=3FDCE400" lines in debug.log
|
|
```
|
|
|
|
`xie_trace.lua` env: `XIE_FRAMES`, `XIE_WORDS` (0 = print PC only),
|
|
`XIE_TRACE` (breakpoint address override), `XIE_JIT` / `XIE_AT` (optional
|
|
debugger entry).
|