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).
9.1 KiB
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:
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, from0x6B966: resource byte 40 == 0, resource byte 36 != 0, and the band bit1 << bandset 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)
PUT_TILEwith 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.- If (1) fails:
minor 43, len 10, [id, 0…]on the class-2 resource, then repeat (1). - 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
- The firmware never enters
XieProcduring 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). - The Scalution test (
0x35EA8, bit0x3F1AF540) writes image-option/scaler registers0xCA2xx/0x56000xx; it contains no server call. - The ROM has no client-side XIE strings; the only
Xiestrings are the server's registration messages. - Debugger
printfoutput requires-debuglog; without it, breakpoint actions are invisible (this silently invalidated a first round of runs here).
Inferred
- The built-in image tests are board-level diagnostics, not protocol clients.
- 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
- Whether slot 43 or slot 20 is the band-materialising request (unchanged).
- The image-option menu's key map (not needed for the conclusion).
7. Reproduce
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).