Files
vt1200/xie/evidence/handoff_dispatch_and_create_shape.txt
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

76 lines
4.3 KiB
Plaintext

TURN RECORD: THE HANDOFF'S REAL DISPATCH, CREATE'S TRUE WIRE SHAPE, AND A
TYPE-SIGNATURE GATE. Two earlier claims are CORRECTED here.
A) CORRECTION: 0x6B84C IS NOT A "band+0xd8 GUARD". IT IS THE SUCCESS RETURN.
The handoff at file 0x6B640 begins:
6B640 MMTM SP,0x154 / MOVE A14,A13 / ADDI 0x230,A14
6B64A JR 0x6B834 <-- jumps to the real entry
and 0x6B834 dispatches on *object->byte8:
6B834 A11 = *A13(0xffe0) ; SETF 8
6B83A A8 = *A11(8) <-- BIT OFFSET 8 = BYTE 1
6B83E DEC A8 ; JREQ 0x6B64E ; byte1 == 1
6B844 SUBK 2 ; JREQ 0x6B75E ; byte1 == 3
6B848 DEC ; JREQ 0x6B7E8 ; byte1 == 4
6B84C SUB A8,A8 -> epilogue <-- A8 = 0 = SUCCESS
So 0x6B84C is the shared success return, reached from three places
(0x6B674, 0x6B688, 0x6B746/0x6B75C). My long-standing "H_84C_NOOP" label
was wrong: an H_84C hit after real work is a SUCCESSFUL completion.
Also: why H_684 never fired in earlier runs -- 0x6B684 lies in the byte1==1
block (0x6B64E...), which is only entered when the dispatch value is 1.
The dispatch value was 0, so control fell straight through to 0x6B84C.
B) THE HANDOFF'S OBJECT IS *(object->byte36), NOT THE RESOURCE.
Measured at 0x6B83E with the import gate satisfied:
H_83E ddobj=00010100 b1=00 a8=0 -> H_84C_default (byte1 not in {1,3,4})
ddobj 0x00010100 was my scratch pointer == *(byte36). So the handoff
dispatches on BYTE 1 OF THE STRUCTURE THAT byte36 POINTS AT.
Setting that byte made the handoff run its real body:
ddobj[1]=1 -> H_64E -> H_674(cnt=0) -> H_684(d8=<element, nonzero>)
-> H_688 -> CALLA 0x7EAC356 -> CALLA 0x7E80008 -> success
ddobj[1]=3 -> dispatch reached, PUT_TILE BadValue(2)
ddobj[1]=4 -> dispatch reached, PUT_TILE BadMatch(8)
and in that run element+0x28 (bits) became NON-ZERO (0x00929990) -- the first
time any element source pointer was populated.
C) CREATE'S TRUE SHAPE (new, measured)
- The request must be EXACTLY 12 words (11 data words). Length 11 works;
13, 15, 17, 19, 23, 27 words all produce NO OBJECT.
- word0 (op) dispatches to four routines:
op 1,2 -> CALLA 0x7EA78DA op 4 -> 0x7EA76CA
op 5 -> 0x7EA7B46 op 6 -> 0x7EA7DA8 else BadValue
- ops 4,5,6 are accepted (no error) but register NOTHING: a following arm
returns BadIDChoice(14) with bad = the id. Only ops 1 and 2 register.
- Field attribution for op=2 (vary one word, diff 64 object bytes):
w2 -> bytes 16..19 (width)
w3 -> bytes 20..23 (height)
w8/w9 -> byte 8 (bits/pixel = w9>>8; must be 1)
w10 -> byte 10
w5 -> bytes 24..31
w1 -> the id at bytes 0..3 ; byte 4 = class (2 for op=2)
bytes 32..39 (incl. byte 36) are ALL ZERO for every value tried.
D) object->byte36 IS NEVER SET BY ANY CLIENT REQUEST.
Swept: op in 0..15; payload length 11..27; w2/w3 geometry 0x0, 1x1, 64x1,
1x64, 64x64, 640x480, 1024x1024, 32768x1; w4 in 0..4; w5 in 0..6; w6 in 0..8.
byte36 == 00000000 in EVERY class-2 object. The import gate dereferences it
(0x6BAF2 `A7 = *A7`), so on a client-created resource the gate reads address 0.
Only the class-1 object (op=1) has a non-zero byte36, and its other fields at
those offsets are not meaningful (b8=0xD0, b44=0x02410092), i.e. that object's
layout differs by class.
E) NEW GATE FOUND: TYPE-SIGNATURE VALIDATION IN THE ELEMENT EXECUTOR.
The helper the failing handoff calls is file 0x40008 (CALLA 0x07E80008):
40018 CALLA 0x07E80162 ; get a signature for arg object
40026 SUBI 0x9ED8014,A8 ; JREQ 0x40022 -> MOVK 2,A8 (return BadValue)
4002E SUBK 8 ; JREQ 0x40022 ; 0x9ED801C also rejected
40032 SUBK 8 ; JREQ 0x40022 ; 0x9ED8024 also rejected
So the executor type-checks the objects it is handed and returns 2 on a
mismatch. Our PUT_TILE BadValue(2) comes from here.
STATUS. No client-chosen XIE image; src_base (rp+0x610) still 0 in every run
where it could be read; the window is still the stipple; xshow (core X) remains
the only viewer that has displayed an image. Everything in this file is measured
against the running emulator; D and C are exhaustive for the shapes listed.