Files
vt1200/xie/MAME_XIE_TRACE.md
T
arti d8d54bb990 feat(xie): a client-chosen XIE image is displayed on the 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).
2026-11-01 23:22:25 +02:00

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, 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

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).